Fix non-supported curve initital error message also for STARTTLS

This is the last fix for #1087.

It determines STARTTLS_OPTIMAL_PROTO (unless --ssl-native is being used) with
sockets per default which removes cases where an openssl s_client
connect using STARTTLS failed with the initial message 'doesn't seem to be a TLS/SSL
enabled server' and prompt 'Really proceed ? ("yes" to continue)' now shouldn't
happen in those cases anymore.

To not have redundant code determine_optimal_proto_sockets_helper() is being
used for not STARTTLS and plain TLS/SSL.

In addition it looked like this determine_optimal_proto() was not always called in
the beginning when a STARTTLS scan was requested. Instead determine_service()
contained an openssl s_client connect called which was the wrong place and thus
removed. Also now determine_optimal_proto() also for STARTTLS will always being called.
This commit is contained in:
Dirk 2019-02-20 21:37:59 +01:00
parent 315005fc6f
commit c957e4e302

View File

@ -5994,8 +5994,6 @@ run_server_preference() {
elif [[ -n "$STARTTLS_PROTOCOL" ]]; then elif [[ -n "$STARTTLS_PROTOCOL" ]]; then
# now it still could be that we hit this bug: https://github.com/drwetter/testssl.sh/issues/188 # now it still could be that we hit this bug: https://github.com/drwetter/testssl.sh/issues/188
# workaround is to connect with a protocol # workaround is to connect with a protocol
debugme tm_out "(workaround #188) "
determine_optimal_proto $STARTTLS_PROTOCOL
[[ ! "$STARTTLS_OPTIMAL_PROTO" =~ ssl ]] && addcmd2="$SNI" [[ ! "$STARTTLS_OPTIMAL_PROTO" =~ ssl ]] && addcmd2="$SNI"
$OPENSSL s_client $(s_client_options "$STARTTLS $STARTTLS_OPTIMAL_PROTO -cipher $list_fwd -ciphersuites $tls13_list_fwd $BUGS -connect $NODEIP:$PORT $PROXY $addcmd2") </dev/null 2>$ERRFILE >$TMPFILE $OPENSSL s_client $(s_client_options "$STARTTLS $STARTTLS_OPTIMAL_PROTO -cipher $list_fwd -ciphersuites $tls13_list_fwd $BUGS -connect $NODEIP:$PORT $PROXY $addcmd2") </dev/null 2>$ERRFILE >$TMPFILE
if ! sclient_connect_successful $? $TMPFILE; then if ! sclient_connect_successful $? $TMPFILE; then
@ -14271,7 +14269,7 @@ run_tls_fallback_scsv() {
fi fi
# First determine the highest protocol that the server supports (not including TLSv1.3). # First determine the highest protocol that the server supports (not including TLSv1.3).
if [[ "$OPTIMAL_PROTO" == "-ssl2" ]]; then if [[ "$OPTIMAL_PROTO" == -ssl2 ]]; then
prln_svrty_critical "No fallback possible, SSLv2 is the only protocol" prln_svrty_critical "No fallback possible, SSLv2 is the only protocol"
fileout "$jsonID" "CRITICAL" "SSLv2 is the only protocol" fileout "$jsonID" "CRITICAL" "SSLv2 is the only protocol"
return 0 return 0
@ -17345,88 +17343,124 @@ sclient_auth() {
} }
# This function determines OPTIMAL_PROTO. It is a workaround function as under certain circumstances # This is a helper function for determine_optimal_proto() below. It sets the
# (e.g. IIS6.0 and openssl 1.0.2 as opposed to 1.0.1) needs a protocol otherwise s_client -connect will fail! # the global STARTTLS_OPTIMAL_PROTO / OPTIMAL_PROTO accordingly and returns 1
# Circumstances observed so far: 1.) IIS 6 2.) starttls + dovecot imap # if no protocol could be determined and 0 if this was possible.
#
determine_optimal_proto_sockets_helper() {
local all_failed=true
local proto=""
local optimal_proto=""
local starttls="$1"
for proto in 03 01 04 00 02 22; do
case $proto in
03) tls_sockets "$proto" "$TLS12_CIPHER"
if [[ $? -eq 0 ]]; then
add_tls_offered tls1_2 yes; optimal_proto="-tls1_2"
all_failed=false
break
elif [[ $? -eq 2 ]]; then
case $(get_protocol "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt") in
*1.1) add_tls_offered tls1_1 yes; optimal_proto="-tls1_1" ;;
TLSv1) add_tls_offered tls1 yes; optimal_proto="-tls1" ;;
SSLv3) add_tls_offered ssl3 yes; optimal_proto="-ssl3" ;;
esac
all_failed=false
break
fi ;;
04) tls_sockets "$proto" "$TLS13_CIPHER"
if [[ $? -eq 0 ]]; then
add_tls_offered tls1_3 yes; optimal_proto="-tls1_3"
all_failed=false
break
fi ;;
01|00|02) tls_sockets "$proto" "$TLS_CIPHER" "" "" "true"
if [[ $? -eq 0 ]]; then
case $proto in
01) add_tls_offered tls1 yes; optimal_proto="-tls1" ;;
00) add_tls_offered ssl3 yes; optimal_proto="-ssl3" ;;
02) add_tls_offered tls1_1 yes; optimal_proto="-tls1_1" ;;
esac
all_failed=false
break
elif [[ $? -eq 2 ]]; then
case $(get_protocol "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt") in
*1.1) add_tls_offered tls1_1 yes; optimal_proto="-tls1_1" ;;
TLSv1) add_tls_offered tls1 yes; optimal_proto="-tls1" ;;
SSLv3) add_tls_offered ssl3 yes; optimal_proto="-ssl3" ;;
esac
all_failed=false
break
fi ;;
22) sslv2_sockets
[[ $? -eq 3 ]] && all_failed=false && add_tls_offered ssl2 yes && optimal_proto="-ssl2"
;;
esac
done
[[ "$proto" != 22 ]] && cp $TEMPDIR/$NODEIP.parse_tls_serverhello.txt $TMPFILE
debugme echo "proto: $proto"
if [[ -n "$starttls" ]]; then
STARTTLS_OPTIMAL_PROTO="$optimal_proto"
else
OPTIMAL_PROTO="$optimal_proto"
fi
if "$all_failed"; then
return 1
else
return 0
fi
}
# This function determines (STARTTLS_)OPTIMAL_PROTO. It is basically is a workaround function as under certain
# circumstances (e.g. IIS6.0 and openssl 1.0.2 as opposed to 1.0.1) needs a protocol otherwise s_client -connect will fail!
# Circumstances observed so far: 1.) IIS 6 2.) starttls + dovecot imap.
# Except those cases it seems reasonable to to know upfront which protocol always works
#
# arg1: if empty: no STARTTLS, else: STARTTLS protocol
# The first try in the loop is empty as we prefer not to specify always a protocol if we can get along w/o it # The first try in the loop is empty as we prefer not to specify always a protocol if we can get along w/o it
# #
determine_optimal_proto() { determine_optimal_proto() {
local all_failed=true local all_failed=true
local tmp="" local tmp=""
local proto=""
local using_sockets=true local using_sockets=true
>$ERRFILE >$ERRFILE
"$SSL_NATIVE" && using_sockets=false "$SSL_NATIVE" && using_sockets=false
if [[ -n "$1" ]]; then if [[ -n "$1" ]]; then
# starttls workaround needed see https://github.com/drwetter/testssl.sh/issues/188 -- kind of odd # STARTTLS
for STARTTLS_OPTIMAL_PROTO in -tls1_2 -tls1 -ssl3 -tls1_1 -tls1_3 -ssl2; do if "$using_sockets"; then
case $STARTTLS_OPTIMAL_PROTO in determine_optimal_proto_sockets_helper "$1"
-tls1_3) "$HAS_TLS13" || continue ;; [[ $? -eq 1 ]] && all_failed=true || all_failed=false
-ssl3) "$HAS_SSL3" || continue ;; else
-ssl2) "$HAS_SSL2" || continue ;; # No sockets
*) ;; # STARTTLS workaround needed see https://github.com/drwetter/testssl.sh/issues/188 -- kind of odd
esac for STARTTLS_OPTIMAL_PROTO in -tls1_2 -tls1 -ssl3 -tls1_1 -tls1_3 -ssl2; do
#FIXME: to be replaced / added by socket ( if "$using_sockets" ...) case $STARTTLS_OPTIMAL_PROTO in
$OPENSSL s_client $(s_client_options "$STARTTLS_OPTIMAL_PROTO $BUGS -connect "$NODEIP:$PORT" $PROXY -msg -starttls $1") </dev/null >$TMPFILE 2>>$ERRFILE -tls1_3) "$HAS_TLS13" || continue ;;
if sclient_auth $? $TMPFILE; then -ssl3) "$HAS_SSL3" || continue ;;
all_failed=false -ssl2) "$HAS_SSL2" || continue ;;
break *) ;;
fi esac
all_failed=true #FIXME: to be replaced / added by socket ( if "$using_sockets" ...)
done $OPENSSL s_client $(s_client_options "$STARTTLS_OPTIMAL_PROTO $BUGS -connect "$NODEIP:$PORT" $PROXY -msg -starttls $1") </dev/null >$TMPFILE 2>>$ERRFILE
"$all_failed" && STARTTLS_OPTIMAL_PROTO="" if sclient_auth $? $TMPFILE; then
all_failed=false
break
fi
all_failed=true
done
"$all_failed" && STARTTLS_OPTIMAL_PROTO=""
fi
debugme echo "STARTTLS_OPTIMAL_PROTO: $STARTTLS_OPTIMAL_PROTO" debugme echo "STARTTLS_OPTIMAL_PROTO: $STARTTLS_OPTIMAL_PROTO"
else else
# No STARTTLS
if "$using_sockets"; then if "$using_sockets"; then
for proto in 03 01 04 00 02 22; do determine_optimal_proto_sockets_helper
case $proto in [[ $? -eq 1 ]] && all_failed=true || all_failed=false
03) tls_sockets "$proto" "$TLS12_CIPHER"
if [[ $? -eq 0 ]]; then
add_tls_offered tls1_2 yes; OPTIMAL_PROTO="-tls1_2"
all_failed=false
break
elif [[ $? -eq 2 ]]; then
case $(get_protocol "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt") in
*1.1) add_tls_offered tls1_1 yes; OPTIMAL_PROTO="-tls1_1" ;;
TLSv1) add_tls_offered tls1 yes; OPTIMAL_PROTO="-tls1" ;;
SSLv3) add_tls_offered ssl3 yes; OPTIMAL_PROTO="-ssl3" ;;
esac
all_failed=false
break
fi ;;
04) tls_sockets "$proto" "$TLS13_CIPHER"
if [[ $? -eq 0 ]]; then
add_tls_offered tls1_3 yes; OPTIMAL_PROTO="-tls1_3"
all_failed=false
break
fi ;;
01|00|02) tls_sockets "$proto" "$TLS_CIPHER" "" "" "true"
if [[ $? -eq 0 ]]; then
case $proto in
01) add_tls_offered tls1 yes; OPTIMAL_PROTO="-tls1" ;;
00) add_tls_offered ssl3 yes; OPTIMAL_PROTO="-ssl3" ;;
02) add_tls_offered tls1_1 yes; OPTIMAL_PROTO="-tls1_1" ;;
esac
all_failed=false
break
elif [[ $? -eq 2 ]]; then
case $(get_protocol "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt") in
*1.1) add_tls_offered tls1_1 yes; OPTIMAL_PROTO="-tls1_1" ;;
TLSv1) add_tls_offered tls1 yes; OPTIMAL_PROTO="-tls1" ;;
SSLv3) add_tls_offered ssl3 yes; OPTIMAL_PROTO="-ssl3" ;;
esac
all_failed=false
break
fi ;;
22) sslv2_sockets
[[ $? -eq 3 ]] && all_failed=false && add_tls_offered ssl2 yes && OPTIMAL_PROTO="-ssl2"
;;
esac
done
[[ "$proto" != 22 ]] && cp $TEMPDIR/$NODEIP.parse_tls_serverhello.txt $TMPFILE
debugme echo "proto: $proto"
else else
# no sockets # no sockets
for OPTIMAL_PROTO in '' -tls1_2 -tls1 -tls1_3 -ssl3 -tls1_1 -ssl2; do for OPTIMAL_PROTO in '' -tls1_2 -tls1 -tls1_3 -ssl3 -tls1_1 -ssl2; do
@ -17464,14 +17498,14 @@ determine_optimal_proto() {
done done
fi fi
"$all_failed" && OPTIMAL_PROTO="" "$all_failed" && OPTIMAL_PROTO=""
debugme echo "OPTIMAL_PROTO: $OPTIMAL_PROTO"
if [[ "$OPTIMAL_PROTO" == -ssl2 ]]; then if [[ "$OPTIMAL_PROTO" == -ssl2 ]]; then
prln_magenta "$NODEIP:$PORT appears to only support SSLv2." prln_magenta "$NODEIP:$PORT appears to only support SSLv2."
ignore_no_or_lame " Type \"yes\" to proceed and accept false negatives or positives" "yes" ignore_no_or_lame " Type \"yes\" to proceed and accept false negatives or positives" "yes"
[[ $? -ne 0 ]] && exit $ERR_CLUELESS [[ $? -ne 0 ]] && exit $ERR_CLUELESS
fi fi
[[ "$proto" != 22 ]] && grep -q '^Server Temp Key' $TMPFILE && HAS_DH_BITS=true # FIX #190 debugme echo "OPTIMAL_PROTO: $OPTIMAL_PROTO"
fi fi
[[ "$OPTIMAL_PROTO" != -ssl2 ]] && grep -q '^Server Temp Key' $TMPFILE && HAS_DH_BITS=true # FIX #190
if "$all_failed"; then if "$all_failed"; then
outln outln
@ -17511,7 +17545,8 @@ determine_optimal_proto() {
} }
# arg1: ftp smtp, lmtp, pop3, imap, xmpp, telnet, ldap, postgres, mysql, irc, nntp (maybe with trailing s) # arg1 (optional): ftp smtp, lmtp, pop3, imap, xmpp, telnet, ldap, postgres, mysql, irc, nntp (maybe with trailing s)
#
determine_service() { determine_service() {
local ua local ua
local protocol error_msg local protocol error_msg
@ -17534,7 +17569,7 @@ determine_service() {
outln outln
if [[ -z "$1" ]]; then if [[ -z "$1" ]]; then
# no STARTTLS. # no STARTTLS.
determine_optimal_proto "$1" determine_optimal_proto
$SNEAKY && \ $SNEAKY && \
ua="$UA_SNEAKY" || \ ua="$UA_SNEAKY" || \
ua="$UA_STD" ua="$UA_STD"
@ -17595,21 +17630,8 @@ determine_service() {
fatal "Your $OPENSSL does not support the \"-starttls nntp\" option" $ERR_OSSLBIN fatal "Your $OPENSSL does not support the \"-starttls nntp\" option" $ERR_OSSLBIN
fi fi
fi fi
determine_optimal_proto "$1"
$OPENSSL s_client $(s_client_options "-connect $NODEIP:$PORT $PROXY $BUGS $STARTTLS") 2>$ERRFILE >$TMPFILE </dev/null
if [[ $? -ne 0 ]]; then
error_msg="$OPENSSL couldn't connect to $NODEIP:$PORT via STARTTLS using $protocol"
debugme cat $TMPFILE | head -25
outln
if "$MULTIPLE_CHECKS"; then
ip_fatal "$error_msg"
return 1
else
fatal " $error_msg" $ERR_CONNECT
fi
fi
grep -q '^Server Temp Key' $TMPFILE && HAS_DH_BITS=true # FIX #190
out " Service set:$CORRECT_SPACES STARTTLS via " out " Service set:$CORRECT_SPACES STARTTLS via "
out "$(toupper "$protocol")" out "$(toupper "$protocol")"
[[ "$protocol" == mysql ]] && out " -- attention, this is experimental" [[ "$protocol" == mysql ]] && out " -- attention, this is experimental"
@ -18821,6 +18843,7 @@ stopwatch() {
} }
# arg1(optional): "init" --> just initializing. Or: STARTTLS protocol
lets_roll() { lets_roll() {
local -i ret=0 local -i ret=0
local section_number=1 local section_number=1