Merge pull request #3084 from testssl/fix_tls13_only_hosts

Fix confusion when scanning TLS-1.3-only hosts
This commit is contained in:
Dirk Wetter
2026-07-10 16:41:40 +02:00
committed by GitHub
2 changed files with 92 additions and 84 deletions
+11 -8
View File
@@ -122,14 +122,17 @@ $socket_out =~ s/ error querying OCSP responder .*\n//g;
unlike($socket_out, qr/$socket_regex_bl/, ""); unlike($socket_out, qr/$socket_regex_bl/, "");
$tests++; $tests++;
#7 # /usr/bin/openssl on MacOS doesn't seem to be available (anymore)
# https://ldapwiki.com/wiki/Public%20LDAP%20Servers if ( $os ne "darwin" ){
$uri="db.debian.org:389"; #7
printf "\n%s\n", "STARTTLS LDAP unit tests via sockets --> $uri ..."; # https://ldapwiki.com/wiki/Public%20LDAP%20Servers
$socket_out = `$prg $check2run -t ldap $uri 2>&1`; $uri="db.debian.org:389";
# $socket_json = json('tmp.json'); printf "\n%s\n", "STARTTLS LDAP unit tests via sockets --> $uri ...";
unlike($socket_out, qr/$socket_regex_bl/, ""); $socket_out = `$prg $check2run -t ldap $uri 2>&1`;
$tests++; # $socket_json = json('tmp.json');
unlike($socket_out, qr/$socket_regex_bl/, "");
$tests++;
}
# For NNTP there doesn't seem to be reliable host out there # For NNTP there doesn't seem to be reliable host out there
#$uri="144.76.182.167:119"; #$uri="144.76.182.167:119";
+81 -76
View File
@@ -361,6 +361,7 @@ HAS_ALPN=false
HAS_NPN=false HAS_NPN=false
HAS_FALLBACK_SCSV=false HAS_FALLBACK_SCSV=false
HAS_PROXY=false HAS_PROXY=false
HAS_LDAP=false
HAS_XMPP=false HAS_XMPP=false
HAS_XMPP_SERVER=false HAS_XMPP_SERVER=false
HAS_POSTGRES=false HAS_POSTGRES=false
@@ -2623,13 +2624,13 @@ service_detection() {
fi fi
jsonID="service" jsonID="service"
if [[ $SERVICE == HTTP ]] || "$ASSUME_HTTP" || [[ -n "$MTLS" ]]; then
dns_https_rr
fi
case $SERVICE in case $SERVICE in
HTTP) HTTP)
if [[ $SERVICE == HTTP ]]; then
dns_https_rr
fi
pr_bold " Service detected" pr_bold " Service detected"
out ": $CORRECT_SPACES $SERVICE" outln ": $CORRECT_SPACES $SERVICE"
fileout "${jsonID}" "INFO" "$SERVICE" fileout "${jsonID}" "INFO" "$SERVICE"
;; ;;
IMAP|POP|SMTP|NNTP|MongoDB) IMAP|POP|SMTP|NNTP|MongoDB)
@@ -2637,32 +2638,28 @@ service_detection() {
out ": $CORRECT_SPACES $SERVICE, thus skipping HTTP specific checks" out ": $CORRECT_SPACES $SERVICE, thus skipping HTTP specific checks"
fileout "${jsonID}" "INFO" "$SERVICE, thus skipping HTTP specific checks" fileout "${jsonID}" "INFO" "$SERVICE, thus skipping HTTP specific checks"
;; ;;
#FIXME: \/ \/ dns_https_rr
*) pr_bold " Service detected:"; out " $CORRECT_SPACES" *) pr_bold " Service detected:"; out " $CORRECT_SPACES"
if [[ ! -z $MTLS ]]; then if [[ -n "$MTLS" ]]; then
out " not identified, but mTLS authentication is set ==> trying HTTP checks" outln " not identified, but mTLS authentication is set ==> trying HTTP checks"
SERVICE=HTTP SERVICE=HTTP
fileout "${jsonID}" "DEBUG" "Couldn't determine service -- ASSUME_HTTP set" fileout "${jsonID}" "DEBUG" "Couldn't determine service -- ASSUME_HTTP set"
dns_https_rr
elif [[ "$CLIENT_AUTH" == required ]] && [[ -z $MTLS ]]; then elif [[ "$CLIENT_AUTH" == required ]] && [[ -z $MTLS ]]; then
out " certificate-based authentication without providing client certificate and private key => skipping all HTTP checks" | tee $TMPFILE outln " certificate-based authentication without providing client certificate and private key => skipping all HTTP checks" | tee $TMPFILE
fileout "${jsonID}" "INFO" "certificate-based authentication without providing client certificate and private key => skipping all HTTP checks" fileout "${jsonID}" "INFO" "certificate-based authentication without providing client certificate and private key => skipping all HTTP checks"
else else
out " Couldn't determine what's running on port $PORT" out " Couldn't determine what's running on port $PORT"
if "$ASSUME_HTTP"; then if "$ASSUME_HTTP"; then
SERVICE=HTTP SERVICE=HTTP
out " -- ASSUME_HTTP set though" outln " -- ASSUME_HTTP set though"
fileout "${jsonID}" "DEBUG" "Couldn't determine service -- ASSUME_HTTP set" fileout "${jsonID}" "DEBUG" "Couldn't determine service -- ASSUME_HTTP set"
dns_https_rr
else else
out ", assuming no HTTP service => skipping all HTTP checks" outln ", assuming no HTTP service => skipping all HTTP checks"
fileout "${jsonID}" "DEBUG" "Couldn't determine service, skipping all HTTP checks" fileout "${jsonID}" "DEBUG" "Couldn't determine service, skipping all HTTP checks"
fi fi
fi fi
;; ;;
esac esac
outln
tmpfile_handle ${FUNCNAME[0]}.txt tmpfile_handle ${FUNCNAME[0]}.txt
return 0 return 0
} }
@@ -21490,6 +21487,7 @@ find_openssl_binary() {
HAS_NPN=false HAS_NPN=false
HAS_FALLBACK_SCSV=false HAS_FALLBACK_SCSV=false
HAS_PROXY=false HAS_PROXY=false
HAS_LDAP=false
HAS_XMPP=false HAS_XMPP=false
HAS_XMPP_SERVER=false HAS_XMPP_SERVER=false
HAS_XMPP_SERVER2=false HAS_XMPP_SERVER2=false
@@ -21625,6 +21623,8 @@ find_openssl_binary() {
grep -q 'xmpp' $s_client_starttls_has && HAS_XMPP=true grep -q 'xmpp' $s_client_starttls_has && HAS_XMPP=true
grep -Eq 'xmpp-server|xmpp\[-server\]' $s_client_starttls_has && HAS_XMPP_SERVER=true grep -Eq 'xmpp-server|xmpp\[-server\]' $s_client_starttls_has && HAS_XMPP_SERVER=true
# Seems like LibreSSL on MacOS somehow lost this with 26.5.2?
grep -q 'ldap' $s_client_starttls_has && HAS_LDAP=true
grep -q 'postgres' $s_client_starttls_has && HAS_POSTGRES=true grep -q 'postgres' $s_client_starttls_has && HAS_POSTGRES=true
grep -q 'mysql' $s_client_starttls_has && HAS_MYSQL=true grep -q 'mysql' $s_client_starttls_has && HAS_MYSQL=true
grep -q 'lmtp' $s_client_starttls_has && HAS_LMTP=true grep -q 'lmtp' $s_client_starttls_has && HAS_LMTP=true
@@ -23891,80 +23891,80 @@ determine_optimal_proto() {
TLS12_CIPHER_OFFERED="$(get_cipher $TMPFILE)" TLS12_CIPHER_OFFERED="$(get_cipher $TMPFILE)"
TLS12_CIPHER_OFFERED="$(openssl2hexcode "$TLS12_CIPHER_OFFERED")" TLS12_CIPHER_OFFERED="$(openssl2hexcode "$TLS12_CIPHER_OFFERED")"
[[ ${#TLS12_CIPHER_OFFERED} -eq 9 ]] && TLS12_CIPHER_OFFERED="${TLS12_CIPHER_OFFERED:2:2},${TLS12_CIPHER_OFFERED:7:2}" || TLS12_CIPHER_OFFERED="" [[ ${#TLS12_CIPHER_OFFERED} -eq 9 ]] && TLS12_CIPHER_OFFERED="${TLS12_CIPHER_OFFERED:2:2},${TLS12_CIPHER_OFFERED:7:2}" || TLS12_CIPHER_OFFERED=""
fi
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."
fileout "$jsonID" "WARN" "$NODEIP:$PORT appears to only support SSLv2." fileout "$jsonID" "WARN" "$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 elif "$all_failed" && ! "$ALL_FAILED_SOCKETS"; then
if ! "$HAS_TLS13" && "$TLS13_ONLY"; then if ! "$HAS_TLS13" && "$TLS13_ONLY"; then
if "$HAS2_TLS13"; then if "$HAS2_TLS13"; then
if "$OSSL_SHORTCUT" || [[ "$WARNINGS" == batch ]]; then if "$OSSL_SHORTCUT" || [[ "$WARNINGS" == batch ]]; then
# switch w/o asking # switch w/o asking
OPEN_MSG=" $NODE:$PORT appeared to support TLS 1.3 ONLY. Thus switched automagically from\n \"$OPENSSL\" to \"$OPENSSL2\"." OPEN_MSG=" $NODE:$PORT appeared to support TLS 1.3 ONLY. Thus switched automagically from\n \"$OPENSSL\" to \"$OPENSSL2\"."
fileout "$jsonID" "INFO" "$NODE:$PORT appears to support TLS 1.3 ONLY, switching from $OPENSSL to $OPENSSL2 automagically" fileout "$jsonID" "INFO" "$NODE:$PORT appears to support TLS 1.3 ONLY, switching from $OPENSSL to $OPENSSL2 automagically"
OPENSSL="$OPENSSL2"
find_openssl_binary
prepare_arrays
else
# now we need to ask the user
ignore_no_or_lame " Type \"yes\" to proceed with \"$OPENSSL2\" OR accept all scan problems" "yes"
if [[ $? -eq 0 ]]; then
fileout "$jsonID" "INFO" "$NODE:$PORT appears to support TLS 1.3 ONLY, switching from $OPENSSL to $OPENSSL2 by the user"
OPENSSL="$OPENSSL2" OPENSSL="$OPENSSL2"
find_openssl_binary find_openssl_binary
prepare_arrays prepare_arrays
else else
fileout "$jsonID" "WARN" "$NODE:$PORT appears to support TLS 1.3 ONLY, switching from $OPENSSL to $OPENSSL2 was denied by user" # now we need to ask the user
ignore_no_or_lame " Type \"yes\" to proceed with \"$OPENSSL2\" OR accept all scan problems" "yes"
if [[ $? -eq 0 ]]; then
fileout "$jsonID" "INFO" "$NODE:$PORT appears to support TLS 1.3 ONLY, switching from $OPENSSL to $OPENSSL2 by the user"
OPENSSL="$OPENSSL2"
find_openssl_binary
prepare_arrays
else
fileout "$jsonID" "WARN" "$NODE:$PORT appears to support TLS 1.3 ONLY, switching from $OPENSSL to $OPENSSL2 was denied by user"
fi
fi fi
fi fi
fi elif ! "$HAS_SSL3" && [[ "$(has_server_protocol "ssl3")" -eq 0 ]] && [[ "$(has_server_protocol "tls1_3")" -ne 0 ]] && \
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_2")" -ne 0 ]] && [[ "$(has_server_protocol "tls1_1")" -ne 0 ]] && [[ "$(has_server_protocol "tls1")" -ne 0 ]]; then
[[ "$(has_server_protocol "tls1")" -ne 0 ]]; then prln_warning " $NODE:$PORT appears to support SSLv3 ONLY. You better use --openssl=<path_to_openssl_supporting_SSL_3>"
prln_warning " $NODE:$PORT appears to support SSLv3 ONLY. You better use --openssl=<path_to_openssl_supporting_SSL_3>" fileout "$jsonID" "WARN" "$NODE:$PORT appears to support SSLv3 ONLY, but $OPENSSL does not support SSLv3."
fileout "$jsonID" "WARN" "$NODE:$PORT appears to support SSLv3 ONLY, but $OPENSSL does not support SSLv3." ignore_no_or_lame " Type \"yes\" to proceed and accept all scan problems" "yes"
ignore_no_or_lame " Type \"yes\" to proceed and accept all scan problems" "yes" [[ $? -ne 0 ]] && exit $ERR_CLUELESS
[[ $? -ne 0 ]] && exit $ERR_CLUELESS MAX_OSSL_FAIL=10
MAX_OSSL_FAIL=10
else
outln
prln_warning " Your $OPENSSL cannot connect to $NODEIP:$PORT."
if [[ -x $OPENSSL2 ]] ; then
outln " Restarting with --openssl=$OPENSSL2 likely helps"
fileout "$jsonID" "WARN" "$OPENSSL cannot connect to $NODEIP:$PORT. Recommended using --openssl=$OPENSSL2"
else else
fileout "$jsonID" "WARN" "Your $OPENSSL cannot connect to $NODEIP:$PORT." outln
prln_warning " Your $OPENSSL cannot connect to $NODEIP:$PORT."
if [[ -x $OPENSSL2 ]] ; then
outln " Restarting with --openssl=$OPENSSL2 likely helps"
fileout "$jsonID" "WARN" "$OPENSSL cannot connect to $NODEIP:$PORT. Recommended using --openssl=$OPENSSL2"
else
fileout "$jsonID" "WARN" "Your $OPENSSL cannot connect to $NODEIP:$PORT."
fi
outln
ignore_no_or_lame " If you continue the results are likely not correct. Really proceed ? (\"yes\" to continue)" "yes"
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
fi fi
elif "$all_failed"; then
outln outln
ignore_no_or_lame " If you continue the results are likely not correct. Really proceed ? (\"yes\" to continue)" "yes" if "$IPv6_OK"; then
pr_bold " Your $OPENSSL is not IPv6 aware, or $NODEIP:$PORT "
fileout "$jsonID" "WARN" "Your $OPENSSL is not IPv6 aware, or $NODEIP:$PORT doesn't seem to be a TLS/SSL enabled server."
else
pr_bold " $NODEIP:$PORT "
fileout "$jsonID" "WARN" "$NODEIP:$PORT doesn't seem to be a TLS/SSL enabled server."
fi
tmpfile_handle ${FUNCNAME[0]}.txt
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"
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
elif ! "$all_failed" && "$ALL_FAILED_SOCKETS" && ! "$SSL_NATIVE"; then
# Edge case: connecting with tls_sockets/sslv2_sockets didn't work, but connecting with $OPENSSL s_client did.
# See #2807
prln_warning "This shouldn't happen (pls report): Testing $NODE:$PORT only succeeded using $OPENSSL."
prln_warning "But testssl.sh also needs bash sockets to perform its checks correctly.\n"
outln "You can try to continue using the --ssl-native option but the results are likely not complete."
outln "Or you can restart using --ssl-native with another openssl version (--openssl <PATH>)."
fileout "$jsonID" "WARN" "Sockets didn't work. Testing NODE:$PORT only succeeded using $OPENSSL."
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
elif "$all_failed"; then
outln
if "$IPv6_OK"; then
pr_bold " Your $OPENSSL is not IPv6 aware, or $NODEIP:$PORT "
fileout "$jsonID" "WARN" "Your $OPENSSL is not IPv6 aware, or $NODEIP:$PORT doesn't seem to be a TLS/SSL enabled server."
else
pr_bold " $NODEIP:$PORT "
fileout "$jsonID" "WARN" "$NODEIP:$PORT doesn't seem to be a TLS/SSL enabled server."
fi
tmpfile_handle ${FUNCNAME[0]}.txt
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"
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
elif ! "$all_failed" && "$ALL_FAILED_SOCKETS" && ! "$SSL_NATIVE"; then
# Edge case: connecting with tls_sockets/sslv2_sockets didn't work, but connecting with $OPENSSL s_client did.
# See #2807
prln_warning "This shouldn't happen (pls report): Testing $NODE:$PORT only succeeded using $OPENSSL."
prln_warning "But testssl.sh also needs bash sockets to perform its checks correctly.\n"
outln "You can try to continue using the --ssl-native option but the results are likely not complete."
outln "Or you can restart using --ssl-native with another openssl version (--openssl <PATH>)."
fileout "$jsonID" "WARN" "Sockets didn't work. Testing NODE:$PORT only succeeded using $OPENSSL."
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
@@ -24095,7 +24095,7 @@ determine_service() {
if "$HAS_XMPP"; then if "$HAS_XMPP"; then
# small hack -- instead of changing calls all over the place # small hack -- instead of changing calls all over the place
STARTTLS="$STARTTLS -xmpphost $NODE" STARTTLS="$STARTTLS -xmpphost $NODE"
else llelse
# If the XMPP name cannot be provided using -xmpphost, # If the XMPP name cannot be provided using -xmpphost,
# then it needs to be provided to the -connect option # then it needs to be provided to the -connect option
NODEIP="$NODE" NODEIP="$NODE"
@@ -24105,6 +24105,11 @@ determine_service() {
#FIXME: make use of HAS_XMPP_SERVER2 #FIXME: make use of HAS_XMPP_SERVER2
fatal "Your $OPENSSL does not support the \"-starttls xmpp-server\" option" $ERR_OSSLBIN fatal "Your $OPENSSL does not support the \"-starttls xmpp-server\" option" $ERR_OSSLBIN
fi fi
elif [[ "$protocol" == ldap ]]; then
# Check if openssl version supports postgres.
if ! "$HAS_LDAP"; then
fatal "Your $OPENSSL does not support the \"-starttls ldap\" option" $ERR_OSSLBIN
fi
elif [[ "$protocol" == postgres ]]; then elif [[ "$protocol" == postgres ]]; then
# Check if openssl version supports postgres. # Check if openssl version supports postgres.
if ! "$HAS_POSTGRES"; then if ! "$HAS_POSTGRES"; then