Merge pull request #1336 from dcooper16/ossl_determine_optimal_proto
Use OpenSSL for determine_optimal_proto()
This commit is contained in:
commit
3389d84103
166
testssl.sh
166
testssl.sh
|
@ -380,6 +380,7 @@ OPTIMAL_PROTO="" # Need this for IIS6 (sigh) + OpenSSL 1.
|
||||||
# https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892
|
# https://github.com/PeterMosmans/openssl/issues/19#issuecomment-100897892
|
||||||
STARTTLS_OPTIMAL_PROTO="" # Same for STARTTLS, see https://github.com/drwetter/testssl.sh/issues/188
|
STARTTLS_OPTIMAL_PROTO="" # Same for STARTTLS, see https://github.com/drwetter/testssl.sh/issues/188
|
||||||
OPTIMAL_SOCKETS_PROTO="" # Same for tls_sockets(). -- not yet used
|
OPTIMAL_SOCKETS_PROTO="" # Same for tls_sockets(). -- not yet used
|
||||||
|
ALL_FAILED_SOCKETS=true # Set to true if all attempts to connect to server using tls_sockets/sslv2_sockets failed
|
||||||
TLS_TIME="" # To keep the value of TLS server timestamp
|
TLS_TIME="" # To keep the value of TLS server timestamp
|
||||||
TLS_NOW="" # Similar
|
TLS_NOW="" # Similar
|
||||||
TLS_DIFFTIME_SET=false # Tells TLS functions to measure the TLS difftime or not
|
TLS_DIFFTIME_SET=false # Tells TLS functions to measure the TLS difftime or not
|
||||||
|
@ -17943,74 +17944,10 @@ determine_optimal_sockets_params() {
|
||||||
sslv2_sockets
|
sslv2_sockets
|
||||||
[[ $? -eq 3 ]] && all_failed=false && add_tls_offered ssl2 yes
|
[[ $? -eq 3 ]] && all_failed=false && add_tls_offered ssl2 yes
|
||||||
fi
|
fi
|
||||||
if [[ -n "$OPTIMAL_SOCKETS_PROTO" ]]; then
|
ALL_FAILED_SOCKETS="$all_failed"
|
||||||
prln_warning " $NODEIP:$PORT doesn't seem to handle version negotiation correctly. This may lead to some false positives and/or false negatives."
|
|
||||||
fi
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# This is a helper function for determine_optimal_proto() below. It sets the
|
|
||||||
# the global STARTTLS_OPTIMAL_PROTO / OPTIMAL_PROTO accordingly and returns 1
|
|
||||||
# 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"
|
|
||||||
local -i ret
|
|
||||||
|
|
||||||
for proto in 03 01 04 00 02 22; do
|
|
||||||
case $proto in
|
|
||||||
03) tls_sockets "$proto" "$TLS12_CIPHER"
|
|
||||||
ret=$?
|
|
||||||
if [[ $ret -eq 0 ]] || [[ $ret -eq 2 ]]; then
|
|
||||||
case $DETECTED_TLS_VERSION in
|
|
||||||
0303) add_tls_offered tls1_2 yes; optimal_proto="-tls1_2" ;;
|
|
||||||
0302) add_tls_offered tls1_1 yes; optimal_proto="-tls1_1" ;;
|
|
||||||
0301) add_tls_offered tls1 yes; optimal_proto="-tls1" ;;
|
|
||||||
0300) 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"
|
|
||||||
ret=$?
|
|
||||||
if [[ $ret -eq 0 ]] || [[ $ret -eq 2 ]]; then
|
|
||||||
case $DETECTED_TLS_VERSION in
|
|
||||||
0302) add_tls_offered tls1_1 yes; optimal_proto="-tls1_1" ;;
|
|
||||||
0301) add_tls_offered tls1 yes; optimal_proto="-tls1" ;;
|
|
||||||
0300) 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 a workaround function as under certain
|
# This function determines (STARTTLS_)OPTIMAL_PROTO. It is basically a workaround function as under certain
|
||||||
# circumstances a ClientHello without specifying a protocol will fail.
|
# circumstances a ClientHello without specifying a protocol will fail.
|
||||||
|
@ -18023,20 +17960,12 @@ determine_optimal_proto_sockets_helper() {
|
||||||
determine_optimal_proto() {
|
determine_optimal_proto() {
|
||||||
local all_failed=true
|
local all_failed=true
|
||||||
local tmp=""
|
local tmp=""
|
||||||
local using_sockets=true
|
local proto optimal_proto
|
||||||
|
|
||||||
"$do_tls_sockets" && return 0
|
"$do_tls_sockets" && return 0
|
||||||
|
|
||||||
>$ERRFILE
|
>$ERRFILE
|
||||||
"$SSL_NATIVE" && using_sockets=false
|
|
||||||
|
|
||||||
if [[ -n "$1" ]]; then
|
if [[ -n "$1" ]]; then
|
||||||
# STARTTLS
|
|
||||||
if "$using_sockets"; then
|
|
||||||
determine_optimal_proto_sockets_helper "$1"
|
|
||||||
[[ $? -eq 1 ]] && all_failed=true || all_failed=false
|
|
||||||
else
|
|
||||||
# No sockets
|
|
||||||
# STARTTLS workaround needed see https://github.com/drwetter/testssl.sh/issues/188 -- kind of odd
|
# STARTTLS workaround needed see https://github.com/drwetter/testssl.sh/issues/188 -- kind of odd
|
||||||
for STARTTLS_OPTIMAL_PROTO in -tls1_2 -tls1 -ssl3 -tls1_1 -tls1_3 -ssl2; do
|
for STARTTLS_OPTIMAL_PROTO in -tls1_2 -tls1 -ssl3 -tls1_1 -tls1_3 -ssl2; do
|
||||||
case $STARTTLS_OPTIMAL_PROTO in
|
case $STARTTLS_OPTIMAL_PROTO in
|
||||||
|
@ -18045,69 +17974,91 @@ determine_optimal_proto() {
|
||||||
-ssl2) "$HAS_SSL2" || continue ;;
|
-ssl2) "$HAS_SSL2" || continue ;;
|
||||||
*) ;;
|
*) ;;
|
||||||
esac
|
esac
|
||||||
#FIXME: to be replaced / added by socket ( if "$using_sockets" ...)
|
|
||||||
$OPENSSL s_client $(s_client_options "$STARTTLS_OPTIMAL_PROTO $BUGS -connect "$NODEIP:$PORT" $PROXY -msg -starttls $1" $SNI) </dev/null >$TMPFILE 2>>$ERRFILE
|
$OPENSSL s_client $(s_client_options "$STARTTLS_OPTIMAL_PROTO $BUGS -connect "$NODEIP:$PORT" $PROXY -msg -starttls $1" $SNI) </dev/null >$TMPFILE 2>>$ERRFILE
|
||||||
if sclient_auth $? $TMPFILE; then
|
if sclient_auth $? $TMPFILE; then
|
||||||
all_failed=false
|
all_failed=false
|
||||||
|
add_tls_offered "${proto/-/}" yes
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
all_failed=true
|
|
||||||
done
|
done
|
||||||
"$all_failed" && STARTTLS_OPTIMAL_PROTO=""
|
"$all_failed" && STARTTLS_OPTIMAL_PROTO=""
|
||||||
fi
|
optimal_proto="$STARTTLS_OPTIMAL_PROTO"
|
||||||
debugme echo "STARTTLS_OPTIMAL_PROTO: $STARTTLS_OPTIMAL_PROTO"
|
debugme echo "STARTTLS_OPTIMAL_PROTO: $STARTTLS_OPTIMAL_PROTO"
|
||||||
else
|
else
|
||||||
# No STARTTLS
|
# No STARTTLS
|
||||||
if "$using_sockets"; then
|
for proto in '' -tls1_2 -tls1 -tls1_3 -ssl3 -tls1_1 -ssl2; do
|
||||||
determine_optimal_proto_sockets_helper
|
case $proto in
|
||||||
[[ $? -eq 1 ]] && all_failed=true || all_failed=false
|
|
||||||
else
|
|
||||||
# no sockets
|
|
||||||
for OPTIMAL_PROTO in '' -tls1_2 -tls1 -tls1_3 -ssl3 -tls1_1 -ssl2; do
|
|
||||||
case $OPTIMAL_PROTO in
|
|
||||||
-tls1_3) "$HAS_TLS13" || continue ;;
|
-tls1_3) "$HAS_TLS13" || continue ;;
|
||||||
-ssl3) "$HAS_SSL3" || continue ;;
|
-ssl3) "$HAS_SSL3" || continue ;;
|
||||||
-ssl2) "$HAS_SSL2" || continue ;;
|
-ssl2) "$HAS_SSL2" || continue ;;
|
||||||
*) ;;
|
*) ;;
|
||||||
esac
|
esac
|
||||||
$OPENSSL s_client $(s_client_options "$OPTIMAL_PROTO $BUGS -connect "$NODEIP:$PORT" -msg $PROXY $SNI") </dev/null >$TMPFILE 2>>$ERRFILE
|
$OPENSSL s_client $(s_client_options "$proto $BUGS -connect "$NODEIP:$PORT" -msg $PROXY $SNI") </dev/null >$TMPFILE 2>>$ERRFILE
|
||||||
if sclient_auth $? $TMPFILE; then
|
if sclient_auth $? $TMPFILE; then
|
||||||
# we use the successful handshake at least to get one valid protocol supported -- it saves us time later
|
# we use the successful handshake at least to get one valid protocol supported -- it saves us time later
|
||||||
if [[ -z "$OPTIMAL_PROTO" ]]; then
|
if [[ -z "$proto" ]]; then
|
||||||
# convert to openssl terminology
|
# convert to openssl terminology
|
||||||
tmp=$(get_protocol $TMPFILE)
|
tmp=$(get_protocol $TMPFILE)
|
||||||
tmp=${tmp/\./_}
|
tmp=${tmp/\./_}
|
||||||
tmp=${tmp/v/}
|
tmp=${tmp/v/}
|
||||||
tmp="$(tolower $tmp)"
|
tmp="$(tolower $tmp)"
|
||||||
add_tls_offered "${tmp}" yes
|
add_tls_offered "${tmp}" yes
|
||||||
case $tmp in
|
|
||||||
tls1) OPTIMAL_PROTO="-tls1" ;;
|
|
||||||
tls1_1) OPTIMAL_PROTO="-tls1_1" ;;
|
|
||||||
tls1_2) OPTIMAL_PROTO="-tls1_2" ;;
|
|
||||||
tls1_3) OPTIMAL_PROTO="-tls1_3" ;;
|
|
||||||
ssl2) OPTIMAL_PROTO="-ssl2" ;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
add_tls_offered "${OPTIMAL_PROTO/-/}" yes
|
|
||||||
fi
|
|
||||||
debugme echo "one proto determined: $tmp"
|
debugme echo "one proto determined: $tmp"
|
||||||
|
OPTIMAL_PROTO=""
|
||||||
|
else
|
||||||
|
add_tls_offered "${proto/-/}" yes
|
||||||
|
OPTIMAL_PROTO="$proto"
|
||||||
|
fi
|
||||||
all_failed=false
|
all_failed=false
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
all_failed=true
|
|
||||||
done
|
done
|
||||||
fi
|
|
||||||
"$all_failed" && OPTIMAL_PROTO=""
|
"$all_failed" && OPTIMAL_PROTO=""
|
||||||
if [[ "$OPTIMAL_PROTO" == -ssl2 ]]; then
|
optimal_proto="$OPTIMAL_PROTO"
|
||||||
|
|
||||||
|
debugme echo "OPTIMAL_PROTO: $OPTIMAL_PROTO"
|
||||||
|
fi
|
||||||
|
[[ "$optimal_proto" != -ssl2 ]] && ! "$all_failed" && grep -q '^Server Temp Key' $TMPFILE && HAS_DH_BITS=true # FIX #190
|
||||||
|
if [[ "$(has_server_protocol "tls1_3")" -eq 0 ]] && [[ "$(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
|
||||||
|
fi
|
||||||
|
|
||||||
|
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
|
||||||
|
elif "$all_failed" && ! "$ALL_FAILED_SOCKETS"; then
|
||||||
|
if ! "$HAS_TLS13" && "$TLS13_ONLY"; then
|
||||||
|
pr_magenta " $NODE:$PORT appears to support TLS 1.3 ONLY. You better use --openssl=<path_to_openssl_supporting_TLS_1.3>"
|
||||||
|
if ! "$OSSL_SHORTCUT" || [[ ! -x /usr/bin/openssl ]] || /usr/bin/openssl s_client -tls1_3 -connect x 2>&1 | grep -aq "unknown option"; then
|
||||||
|
outln
|
||||||
|
ignore_no_or_lame " Type \"yes\" to proceed and accept all scan problems" "yes"
|
||||||
|
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
|
||||||
|
MAX_OSSL_FAIL=10
|
||||||
|
else
|
||||||
|
# dirty hack but an idea for the future to be implemented upfront: Now we know, we'll better off
|
||||||
|
# with the OS supplied openssl binary. We need to inittialize variables / arrays again though.
|
||||||
|
# And the service detection can't be made up for now
|
||||||
|
outln ", proceeding with /usr/bin/openssl"
|
||||||
|
OPENSSL=/usr/bin/openssl
|
||||||
|
find_openssl_binary
|
||||||
|
prepare_arrays
|
||||||
fi
|
fi
|
||||||
debugme echo "OPTIMAL_PROTO: $OPTIMAL_PROTO"
|
elif ! "$HAS_SSL3" && [[ "$(has_server_protocol "ssl3")" -eq 0 ]] && [[ "$(has_server_protocol "tls1_3")" -ne 0 ]] && \
|
||||||
|
[[ "$(has_server_protocol "tls1_2")" -ne 0 ]] && [[ "$(has_server_protocol "tls1_1")" -ne 0 ]] &&
|
||||||
|
[[ "$(has_server_protocol "tls1")" -ne 0 ]]; then
|
||||||
|
prln_magenta " $NODE:$PORT appears to support SSLv3 ONLY. You better use --openssl=<path_to_openssl_supporting_SSL_3>"
|
||||||
|
ignore_no_or_lame " Type \"yes\" to proceed and accept all scan problems" "yes"
|
||||||
|
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
|
||||||
|
MAX_OSSL_FAIL=10
|
||||||
|
else
|
||||||
|
prln_bold " Your $OPENSSL cannot connect to $NODEIP:$PORT"
|
||||||
|
ignore_no_or_lame " The results might look ok but they could be nonsense. Really proceed ? (\"yes\" to continue)" "yes"
|
||||||
|
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
|
||||||
fi
|
fi
|
||||||
[[ "$OPTIMAL_PROTO" != -ssl2 ]] && ! "$all_failed" && grep -q '^Server Temp Key' $TMPFILE && HAS_DH_BITS=true # FIX #190
|
elif "$all_failed"; then
|
||||||
|
|
||||||
if "$all_failed"; then
|
|
||||||
outln
|
outln
|
||||||
if "$HAS_IPv6"; then
|
if "$HAS_IPv6"; then
|
||||||
pr_bold " Your $OPENSSL is not IPv6 aware, or $NODEIP:$PORT "
|
pr_bold " Your $OPENSSL is not IPv6 aware, or $NODEIP:$PORT "
|
||||||
|
@ -18118,6 +18069,14 @@ determine_optimal_proto() {
|
||||||
prln_bold "doesn't seem to be a TLS/SSL enabled server";
|
prln_bold "doesn't seem to be a TLS/SSL enabled server";
|
||||||
ignore_no_or_lame " The results might look ok but they could be nonsense. Really proceed ? (\"yes\" to continue)" "yes"
|
ignore_no_or_lame " The results might look ok but they could be nonsense. Really proceed ? (\"yes\" to continue)" "yes"
|
||||||
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
|
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
|
||||||
|
elif ! "$all_failed" && "$ALL_FAILED_SOCKETS"; then
|
||||||
|
# For some reason connecting with tls_sockets/sslv2_sockets didn't work, but connecting
|
||||||
|
# with $OPENSSL s_client did.
|
||||||
|
# FIXME: Should we include some sort of "please report" note here?
|
||||||
|
prln_magenta " Testing with $NODE:$PORT only worked using $OPENSSL."
|
||||||
|
"$SSL_NATIVE" || prln_magenta " Test results may be somewhat better if the --ssl-native option is used."
|
||||||
|
ignore_no_or_lame " Type \"yes\" to proceed and accept false negatives or positives" "yes"
|
||||||
|
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
|
||||||
fi
|
fi
|
||||||
|
|
||||||
tmpfile_handle ${FUNCNAME[0]}.txt
|
tmpfile_handle ${FUNCNAME[0]}.txt
|
||||||
|
@ -19564,6 +19523,7 @@ reset_hostdepended_vars() {
|
||||||
PROTOS_OFFERED=""
|
PROTOS_OFFERED=""
|
||||||
CURVES_OFFERED=""
|
CURVES_OFFERED=""
|
||||||
OPTIMAL_PROTO=""
|
OPTIMAL_PROTO=""
|
||||||
|
ALL_FAILED_SOCKETS=true
|
||||||
SERVER_SIZE_LIMIT_BUG=false
|
SERVER_SIZE_LIMIT_BUG=false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue