Workarounds for missing curves in OpenSSL
In case where the OpenSSL version used cannot successfully do openssl s_client connects there are a few problems, see #1087. This PR partly addresses them by * changing the logic of HTTP header failure: we don't terminate anymore but continue with a warning message * we try to find out what the reason was: If it is a missing curve we signal it back to the user * we keep track in a global variable KNOWN_OSSL_PROB. It's not being used yet on all connects as it has not been decided whether we do a connect despite we know if there's a problem or rather not. * Give hints to the user for resumption tests, secure renegotiation, CRIME and BREACH. For the latter --assume-http needs to be supplied for any output. Also: for finding the OPTIMAL_PROTO now (unless --ssl-native is being used) sockets are the default which removes in cases where an openssl s_client connect fails, the initial message 'doesn't seem to be a TLS/SSL enabled server' and prompt 'Really proceed ? ("yes" to continue)'. For STARTTLS this needs to be done as well. Here a minor bug was fixed: when openssl s_client connect in determine_optimal_proto() succeeded without a protocol supplied, OPTIMAL_PROTO wasn't set. A statement was added but now it is only being used when --ssl-native was supplied. Leftover for this workaround is to find out why the number of certificate retrieved is zero in those cases, despite the fact that there's a valid 'host_certificate.pem' from tls_socket() calls. Thus still run_server_defaults() stops after 'TLS clock skew' as certificate_info() is not being called in run_server_defaults(). For now in those cases 'Problem: Host certificate found but we can't continue with "server defaults"' is being printed. In general for the future it would be great if we could e.g. retrieve the header over TLS sockets.
This commit is contained in:
parent
691ca28bb9
commit
5d1109a582
260
testssl.sh
260
testssl.sh
|
@ -232,7 +232,7 @@ IGN_OCSP_PROXY=${IGN_OCSP_PROXY:-false} # Also when --proxy is supplied it is ig
|
|||
HEADER_MAXSLEEP=${HEADER_MAXSLEEP:-5} # we wait this long before killing the process to retrieve a service banner / http header
|
||||
MAX_SOCKET_FAIL=${MAX_SOCKET_FAIL:-2} # If this many failures for TCP socket connects are reached we terminate
|
||||
MAX_OSSL_FAIL=${MAX_OSSL_FAIL:-2} # If this many failures for s_client connects are reached we terminate
|
||||
MAX_HEADER_FAIL=${MAX_HEADER_FAIL:-3} # If this many failures for HTTP GET are encountered we terminate
|
||||
MAX_HEADER_FAIL=${MAX_HEADER_FAIL:-2} # If this many failures for HTTP GET are encountered we don't try again to get the header
|
||||
MAX_WAITSOCK=${MAX_WAITSOCK:-10} # waiting at max 10 seconds for socket reply. There shouldn't be any reason to change this.
|
||||
CCS_MAX_WAITSOCK=${CCS_MAX_WAITSOCK:-5} # for the two CCS payload (each). There shouldn't be any reason to change this.
|
||||
HEARTBLEED_MAX_WAITSOCK=${HEARTBLEED_MAX_WAITSOCK:-8} # for the heartbleed payload. There shouldn't be any reason to change this.
|
||||
|
@ -284,6 +284,8 @@ 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().
|
||||
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=""
|
||||
TLS_EXTENSIONS=""
|
||||
declare -r NPN_PROTOs="spdy/4a2,spdy/3,spdy/3.1,spdy/2,spdy/1,http/1.1"
|
||||
|
@ -1959,6 +1961,8 @@ run_http_header() {
|
|||
local header
|
||||
local referer useragent
|
||||
local url redirect
|
||||
local jsonID="HTTP_status_code"
|
||||
local spaces=" "
|
||||
|
||||
HEADERFILE=$TEMPDIR/$NODEIP.http_header.txt
|
||||
if [[ $NR_HEADER_FAIL -eq 0 ]]; then
|
||||
|
@ -1966,16 +1970,16 @@ run_http_header() {
|
|||
outln; pr_headlineln " Testing HTTP header response @ \"$URL_PATH\" "
|
||||
outln
|
||||
fi
|
||||
if [[ $NR_HEADER_FAIL -ge $MAX_HEADER_FAIL ]]; then
|
||||
# signal to caller we have a problem
|
||||
return 1
|
||||
fi
|
||||
|
||||
pr_bold " HTTP Status Code "
|
||||
[[ -z "$1" ]] && url="/" || url="$1"
|
||||
if [[ "$SOCKETHEADER" == true ]]; then
|
||||
# This is just for testing only. It doesn't work (yet)
|
||||
tls_sockets "03" "$TLS12_CIPHER" "" "" "" false
|
||||
debugme echo "--> $?"
|
||||
printf -- "%b" "$GET_REQ11" >&5 # This GET request is not being logged on the server side --> probably we're still on the TLS layer
|
||||
cat <&5 >$HEADERFILE
|
||||
debugme xxd "$HEADERFILE" # 1503 -> TLS alert
|
||||
close_socket
|
||||
:
|
||||
#FIXME: would be great to complete the handshake and then e.g. tunnel HTTP over it
|
||||
else
|
||||
printf "$GET_REQ11" | $OPENSSL s_client $(s_client_options "$OPTIMAL_PROTO $BUGS -quiet -ign_eof -connect $NODEIP:$PORT $PROXY $SNI") >$HEADERFILE 2>$ERRFILE &
|
||||
wait_kill $! $HEADER_MAXSLEEP
|
||||
|
@ -1998,26 +2002,38 @@ run_http_header() {
|
|||
fileout "HTTP_status_code" "WARN" "HTTP header request failed"
|
||||
debugme cat $HEADERFILE
|
||||
((NR_HEADER_FAIL++))
|
||||
connectivity_problem $NR_HEADER_FAIL $MAX_HEADER_FAIL "HTTP header connect problem" "repeated HTTP header connect problems, doesn't make sense to continue"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [[ ! -s $HEADERFILE ]]; then
|
||||
prln_warning " HTTP header reply empty"
|
||||
fileout "HTTP_status_code" "WARN" "HTTP header reply empty"
|
||||
((NR_HEADER_FAIL++))
|
||||
connectivity_problem $NR_HEADER_FAIL $MAX_HEADER_FAIL "HTTP header zero" "repeatedly HTTP header was zero, doesn't make sense to continue"
|
||||
return 1
|
||||
if [[ $NR_HEADER_FAIL -ge $MAX_HEADER_FAIL ]]; then
|
||||
# Now, try to give a hint whether it would make sense to try with OpenSSL 1.1.0 or 1.1.1 instead
|
||||
if [[ $CURVES_OFFERED == X448 ]] && ! "$HAS_X448" ; then
|
||||
generic_nonfatal "HTTP header was repeatedly zero due to missing X448 curve." "${spaces}OpenSSL 1.1.1 might help. Skipping complete HTTP header section."
|
||||
elif [[ $CURVES_OFFERED == X25519 ]] && ! "$HAS_X25519" ; then
|
||||
generic_nonfatal "HTTP header was repeatedly zero due to missing X25519 curve." "${spaces}OpenSSL 1.1.0 might help. Skipping complete HTTP header section."
|
||||
elif [[ $CURVES_OFFERED =~ X25519 ]] && [[ $CURVES_OFFERED =~ X448 ]] && ! "$HAS_X25519" && ! "$HAS_X448"; then
|
||||
generic_nonfatal "HTTP header was repeatedly zero due to missing X25519/X448 curves." "${spaces}OpenSSL >=1.1.0 might help. Skipping complete HTTP header section."
|
||||
else
|
||||
# we could give more hints but these are the most likely cases
|
||||
generic_nonfatal "HTTP header was repeatedly zero." "Skipping complete HTTP header section."
|
||||
fi
|
||||
KNOWN_OSSL_PROB=true
|
||||
return 1
|
||||
else
|
||||
pr_warning "HTTP header reply empty. "
|
||||
fileout "$jsonID" "WARN" "HTTP header reply empty"
|
||||
fi
|
||||
fi
|
||||
|
||||
# populate vars for HTTP time
|
||||
# Populate vars for HTTP time
|
||||
debugme echo "$NOW_TIME: $HTTP_TIME"
|
||||
|
||||
# delete from pattern til the end. We ignore any leading spaces (e.g. www.amazon.de)
|
||||
sed -e '/<HTML>/,$d' -e '/<html>/,$d' -e '/<\!DOCTYPE/,$d' -e '/<\!doctype/,$d' \
|
||||
-e '/<XML/,$d' -e '/<xml/,$d' -e '/<\?XML/,$d' -e '/<?xml/,$d' $HEADERFILE >$HEADERFILE.tmp
|
||||
# ^^^ Attention: the filtering for the html body only as of now, doesn't work for other content yet
|
||||
# ^^^ Attention: filtering is for html body only as of now, doesn't work for other content yet
|
||||
mv $HEADERFILE.tmp $HEADERFILE
|
||||
|
||||
HTTP_STATUS_CODE=$(awk '/^HTTP\// { print $2 }' $HEADERFILE 2>>$ERRFILE)
|
||||
|
@ -2025,14 +2041,12 @@ run_http_header() {
|
|||
msg_thereafter=$(strip_lf "$msg_thereafter") # field separator, otherwise we need a loop with awk
|
||||
debugme echo "Status/MSG: $HTTP_STATUS_CODE $msg_thereafter"
|
||||
|
||||
pr_bold " HTTP Status Code "
|
||||
jsonID="HTTP_status_code"
|
||||
out " $HTTP_STATUS_CODE$msg_thereafter"
|
||||
[[ -n "$HTTP_STATUS_CODE" ]] && out " $HTTP_STATUS_CODE$msg_thereafter"
|
||||
case $HTTP_STATUS_CODE in
|
||||
301|302|307|308)
|
||||
redirect=$(grep -a '^Location' $HEADERFILE | sed 's/Location: //' | tr -d '\r\n')
|
||||
out ", redirecting to \""; pr_url "$redirect"; out "\""
|
||||
if [[ $redirect == "http://"* ]]; then
|
||||
if [[ $redirect =~ http:// ]]; then
|
||||
pr_svrty_high " -- Redirect to insecure URL (NOT ok)"
|
||||
fileout "insecure_redirect" "HIGH" "Redirect to insecure URL: \"$redirect\""
|
||||
fi
|
||||
|
@ -2059,7 +2073,7 @@ run_http_header() {
|
|||
fileout "$jsonID" "INFO" "$HTTP_STATUS_CODE$msg_thereafter (\"$URL_PATH\")"
|
||||
;;
|
||||
"")
|
||||
pr_warning ". No HTTP status code??"
|
||||
prln_warning "No HTTP status code."
|
||||
fileout "$jsonID" "WARN" "No HTTP status code"
|
||||
return 1
|
||||
;;
|
||||
|
@ -5791,7 +5805,11 @@ sub_session_resumption() {
|
|||
|
||||
$OPENSSL s_client $(s_client_options "$STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI $addcmd -sess_out $sess_data") </dev/null &>/dev/null
|
||||
ret1=$?
|
||||
if "$byID" && [[ $OSSL_VER_MINOR == "1.1" ]] && [[ $OSSL_VER_MAJOR == "1" ]] && [[ ! -s "$sess_data" ]]; then
|
||||
if [[ $ret1 -ne 0 ]]; then
|
||||
debugme echo -n "Couldn't connect #1 "
|
||||
return 7
|
||||
fi
|
||||
if "$byID" && [[ $OSSL_VER_MINOR == 1.1 ]] && [[ $OSSL_VER_MAJOR == 1 ]] && [[ ! -s "$sess_data" ]]; then
|
||||
# it seems OpenSSL indicates no Session ID resumption by just not generating output
|
||||
debugme echo -n "No session resumption byID (empty file)"
|
||||
ret=2
|
||||
|
@ -5802,6 +5820,10 @@ sub_session_resumption() {
|
|||
echo -n "$ret1, $ret2, "
|
||||
[[ -s "$sess_data" ]] && echo "not empty" || echo "empty"
|
||||
fi
|
||||
if [[ $ret2 -ne 0 ]]; then
|
||||
debugme echo -n "Couldn't connect #2 "
|
||||
return 7
|
||||
fi
|
||||
# now get the line and compare the numbers read" and "written" as a second criteria.
|
||||
rw_line="$(awk '/^SSL handshake has read/ { print $5" "$(NF-1) }' "$tmpfile" )"
|
||||
rw_line=($rw_line)
|
||||
|
@ -5821,7 +5843,7 @@ sub_session_resumption() {
|
|||
ret=0
|
||||
else
|
||||
debugme echo -n "unclear status: $ret1, $ret2, $new_sid, $new_sid2 -- "
|
||||
ret=7
|
||||
ret=5
|
||||
fi
|
||||
if [[ $DEBUG -ge 2 ]]; then
|
||||
"$byID" && echo "byID" || echo "by ticket"
|
||||
|
@ -8228,7 +8250,6 @@ certificate_info() {
|
|||
outln
|
||||
fi
|
||||
|
||||
|
||||
out "$indent"; pr_bold " Certificate Revocation List "
|
||||
jsonID="cert_crlDistributionPoints"
|
||||
# ~ get next 50 lines after pattern , strip until Signature Algorithm and retrieve URIs
|
||||
|
@ -8541,12 +8562,13 @@ run_server_defaults() {
|
|||
done
|
||||
|
||||
determine_tls_extensions
|
||||
if [[ $? -eq 0 ]] && [[ "$OPTIMAL_PROTO" != "-ssl2" ]]; then
|
||||
if [[ $? -eq 0 ]] && [[ "$OPTIMAL_PROTO" != -ssl2 ]]; then
|
||||
cp "$TEMPDIR/$NODEIP.determine_tls_extensions.txt" $TMPFILE
|
||||
>$ERRFILE
|
||||
[[ -z "$sessticket_lifetime_hint" ]] && sessticket_lifetime_hint=$(awk '/session ticket lifetime/' $TMPFILE)
|
||||
fi
|
||||
|
||||
debugme echo "# certificates found $certs_found"
|
||||
# Now that all of the server's certificates have been found, determine for
|
||||
# each certificate whether certificate transparency information is provided.
|
||||
for (( i=1; i <= certs_found; i++ )); do
|
||||
|
@ -8622,13 +8644,18 @@ run_server_defaults() {
|
|||
out "Tickets no, "
|
||||
fileout "$jsonID" "INFO" "not supported"
|
||||
;;
|
||||
5) SESS_RESUMPTION[2]="ticket=noclue"
|
||||
pr_warning "Ticket resumption test failed, pls report / "
|
||||
fileout "$jsonID" "WARN" "check failed, pls report"
|
||||
((ret++))
|
||||
;;
|
||||
6) SESS_RESUMPTION[2]="ticket=clientauth"
|
||||
pr_warning "Client Auth: Ticket resumption test not supported / "
|
||||
fileout "$jsonID" "WARN" "check couldn't be performed because of client authentication"
|
||||
;;
|
||||
7) SESS_RESUMPTION[2]="ticket=noclue"
|
||||
pr_warning "Ticket resumption test failed, pls report / "
|
||||
fileout "$jsonID" "WARN" "check failed, pls report"
|
||||
7) SESS_RESUMPTION[2]="ticket=unsuccessful"
|
||||
pr_warning "Connect problem: Ticket resumption test not possible / "
|
||||
fileout "$jsonID" "WARN" "check failed because of connect problem"
|
||||
((ret++))
|
||||
;;
|
||||
esac
|
||||
|
@ -8649,14 +8676,19 @@ run_server_defaults() {
|
|||
outln "ID: no"
|
||||
fileout "$jsonID" "INFO" "not supported"
|
||||
;;
|
||||
5) SESS_RESUMPTION[1]="ID=noclue"
|
||||
prln_warning "ID resumption test failed, pls report"
|
||||
fileout "$jsonID" "WARN" "check failed, pls report"
|
||||
((ret++))
|
||||
;;
|
||||
6) SESS_RESUMPTION[1]="ID=clientauth"
|
||||
[[ ${SESS_RESUMPTION[2]} =~ clientauth ]] || pr_warning "Client Auth: "
|
||||
prln_warning "ID resumption resumption test not supported"
|
||||
fileout "$jsonID" "WARN" "check couldn't be performed because of client authentication"
|
||||
;;
|
||||
7) SESS_RESUMPTION[1]="ID=noclue"
|
||||
prln_warning "ID resumption test failed, pls report"
|
||||
fileout "$jsonID" "WARN" "check failed, pls report"
|
||||
7) SESS_RESUMPTION[1]="ID=unsuccessful"
|
||||
prln_warning "ID resumption test failed"
|
||||
fileout "$jsonID" "WARN" "check failed because of connect problem"
|
||||
((ret++))
|
||||
;;
|
||||
esac
|
||||
|
@ -8700,6 +8732,9 @@ run_server_defaults() {
|
|||
$OPENSSL s_client $(s_client_options "$STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $OPTIMAL_PROTO") 2>>$ERRFILE </dev/null | \
|
||||
awk '/-----BEGIN/,/-----END/ { print $0 }' >$HOSTCERT.nosni
|
||||
fi
|
||||
elif [[ $certs_found -eq 0 ]] && [[ -s "$HOSTCERT" ]]; then
|
||||
outln
|
||||
generic_nonfatal "Problem: Host certificate found but we can't continue with \"server defaults\""
|
||||
fi
|
||||
[[ $DEBUG -ge 1 ]] && [[ -e $HOSTCERT.nosni ]] && $OPENSSL x509 -in $HOSTCERT.nosni -text -noout 2>>$ERRFILE > $HOSTCERT.nosni.txt
|
||||
|
||||
|
@ -9104,6 +9139,8 @@ run_pfs() {
|
|||
fi
|
||||
fi
|
||||
fi
|
||||
CURVES_OFFERED="$curves_offered"
|
||||
CURVES_OFFERED=$(strip_trailing_space "$CURVES_OFFERED")
|
||||
|
||||
# find out what groups are supported.
|
||||
if "$using_sockets" && ( "$pfs_tls13_offered" || "$ffdhe_offered" ); then
|
||||
|
@ -10840,7 +10877,7 @@ check_tls_serverhellodone() {
|
|||
remaining=$tls_alert_ascii_len-$i
|
||||
[[ $remaining -lt 4 ]] && return 1
|
||||
tls_err_level=${tls_alert_ascii:i:2} # 1: warning, 2: fatal
|
||||
[[ $tls_err_level == "02" ]] && DETECTED_TLS_VERSION="" && tm_out "" && return 0
|
||||
[[ $tls_err_level == 02 ]] && DETECTED_TLS_VERSION="" && tm_out "" && return 0
|
||||
done
|
||||
|
||||
# If there is a serverHelloDone or Finished, then we are done.
|
||||
|
@ -12194,8 +12231,8 @@ prepare_tls_clienthello() {
|
|||
local offer_compression=false compression_methods
|
||||
|
||||
# TLSv1.3 ClientHello messages MUST specify only the NULL compression method.
|
||||
[[ "$5" == "true" ]] && [[ "0x$tls_low_byte" -le "0x03" ]] && offer_compression=true
|
||||
[[ "$6" == "false" ]] && new_socket=false
|
||||
[[ "$5" == true ]] && [[ "0x$tls_low_byte" -le "0x03" ]] && offer_compression=true
|
||||
[[ "$6" == false ]] && new_socket=false
|
||||
|
||||
cipher_suites="$2" # we don't have the leading \x here so string length is two byte less, see next
|
||||
len_ciph_suites_byte=${#cipher_suites}
|
||||
|
@ -13564,8 +13601,8 @@ run_renego() {
|
|||
;;
|
||||
esac
|
||||
else
|
||||
prln_warning "handshake didn't succeed"
|
||||
fileout "$jsonID" "WARN" "handshake didn't succeed" "$cve" "$cwe"
|
||||
prln_warning "OpenSSL handshake didn't succeed"
|
||||
fileout "$jsonID" "WARN" "OpenSSL handshake didn't succeed" "$cve" "$cwe"
|
||||
fi
|
||||
|
||||
# see: https://community.qualys.com/blogs/securitylabs/2011/10/31/tls-renegotiation-and-denial-of-service-attacks
|
||||
|
@ -13752,7 +13789,7 @@ run_breach() {
|
|||
local hint=""
|
||||
local jsonID="BREACH"
|
||||
|
||||
[[ $SERVICE != "HTTP" ]] && ! "$CLIENT_AUTH" && return 7
|
||||
[[ $SERVICE != HTTP ]] && ! "$CLIENT_AUTH" && return 7
|
||||
|
||||
[[ $VULN_COUNT -le $VULN_THRESHLD ]] && outln && pr_headlineln " Testing for BREACH (HTTP compression) vulnerability " && outln
|
||||
pr_bold " BREACH"; out " ($cve) "
|
||||
|
@ -13761,15 +13798,20 @@ run_breach() {
|
|||
fileout "$jsonID" "INFO" "was not tested, server side requires x509 authentication" "$cve" "$cwe"
|
||||
fi
|
||||
|
||||
# if [[ $NR_HEADER_FAIL -ge $MAX_HEADER_FAIL ]]; then
|
||||
# pr_warning "Retrieving HTTP header failed before. Skipping."
|
||||
# fileout "$jsonID" "WARN" "HTTP response was wampty before" "$cve" "$cwe"
|
||||
# outln
|
||||
# return 1
|
||||
# fi
|
||||
|
||||
[[ -z "$url" ]] && url="/"
|
||||
disclaimer=" - only supplied \"$url\" tested"
|
||||
|
||||
referer="https://google.com/"
|
||||
[[ "$NODE" =~ google ]] && referer="https://yandex.ru/" # otherwise we have a false positive for google.com
|
||||
|
||||
useragent="$UA_STD"
|
||||
$SNEAKY && useragent="$UA_SNEAKY"
|
||||
|
||||
printf "GET $url HTTP/1.1\r\nHost: $NODE\r\nUser-Agent: $useragent\r\nReferer: $referer\r\nConnection: Close\r\nAccept-encoding: gzip,deflate,compress\r\nAccept: text/*\r\n\r\n" | $OPENSSL s_client $(s_client_options "$OPTIMAL_PROTO $BUGS -quiet -ign_eof -connect $NODEIP:$PORT $PROXY $SNI") 1>$TMPFILE 2>$ERRFILE &
|
||||
wait_kill $! $HEADER_MAXSLEEP
|
||||
was_killed=$? # !=0 was killed
|
||||
|
@ -13777,12 +13819,12 @@ run_breach() {
|
|||
result=$(strip_lf "$result")
|
||||
debugme grep '^Content-Encoding' $TMPFILE
|
||||
if [[ ! -s $TMPFILE ]]; then
|
||||
pr_warning "failed (HTTP header request stalled"
|
||||
pr_warning "failed (HTTP header request stalled or empty return"
|
||||
if [[ $was_killed -ne 0 ]]; then
|
||||
pr_warning " and was terminated"
|
||||
fileout "$jsonID" "WARN" "Test failed as HTTP request stalled and was terminated" "$cve" "$cwe"
|
||||
else
|
||||
fileout "$jsonID" "WARN" "Test failed as HTTP request stalled" "$cve" "$cwe"
|
||||
fileout "$jsonID" "WARN" "Test failed as HTTP response was empty" "$cve" "$cwe"
|
||||
fi
|
||||
prln_warning ") "
|
||||
ret=1
|
||||
|
@ -13828,7 +13870,7 @@ run_sweet32() {
|
|||
# Measurements show that there's little impact whether we use sockets or TLS here, so the default is sockets here
|
||||
if "$using_sockets"; then
|
||||
for proto in 03 02 01 00; do
|
||||
"$FAST" && [[ "$proto" != "03" ]] && break
|
||||
"$FAST" && [[ "$proto" != 03 ]] && break
|
||||
! "$FAST" && [[ $(has_server_protocol "$proto") -eq 1 ]] && continue
|
||||
tls_sockets "$proto" "${sweet32_ciphers_hex}, 00,ff"
|
||||
sclient_success=$?
|
||||
|
@ -13840,8 +13882,8 @@ run_sweet32() {
|
|||
nr_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $sweet32_ciphers))
|
||||
for proto in -no_ssl2 -tls1_1 -tls1 -ssl3; do
|
||||
[[ $nr_supported_ciphers -eq 0 ]] && break
|
||||
! "$HAS_SSL3" && [[ "$proto" == "-ssl3" ]] && continue
|
||||
if [[ "$proto" != "-no_ssl2" ]]; then
|
||||
! "$HAS_SSL3" && [[ "$proto" == -ssl3 ]] && continue
|
||||
if [[ "$proto" != -no_ssl2 ]]; then
|
||||
"$FAST" && break
|
||||
[[ $(has_server_protocol "${proto:1}") -eq 1 ]] && continue
|
||||
fi
|
||||
|
@ -16488,6 +16530,18 @@ ip_fatal() {
|
|||
return 0
|
||||
}
|
||||
|
||||
# This gneric function outputs an error onto the screen and handles logging.
|
||||
# arg1: string to print / to write to file, arg2 (optional): additional hint to write
|
||||
#
|
||||
generic_nonfatal() {
|
||||
prln_magenta "$1" >&2
|
||||
[[ -n $2 ]] && outln "$2"
|
||||
[[ -n "$LOGFILE" ]] && prln_magenta "$1" >>$LOGFILE && [[ -n $2 ]] && outln "$2" >>$LOGFILE
|
||||
outln
|
||||
fileout "scanProblem" "WARN" "$1"
|
||||
return 0
|
||||
}
|
||||
|
||||
initialize_engine(){
|
||||
# for now only GOST engine
|
||||
grep -q '^# testssl config file' "$OPENSSL_CONF" 2>/dev/null && \
|
||||
|
@ -17031,7 +17085,7 @@ sclient_auth() {
|
|||
}
|
||||
|
||||
|
||||
# this function determines OPTIMAL_PROTO. It is a workaround function as under certain circumstances
|
||||
# This function determines OPTIMAL_PROTO. It 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
|
||||
# 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
|
||||
|
@ -17039,8 +17093,12 @@ sclient_auth() {
|
|||
determine_optimal_proto() {
|
||||
local all_failed=true
|
||||
local tmp=""
|
||||
local proto=""
|
||||
local using_sockets=true
|
||||
|
||||
>$ERRFILE
|
||||
"$SSL_NATIVE" && using_sockets=false
|
||||
|
||||
if [[ -n "$1" ]]; then
|
||||
# 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
|
||||
|
@ -17050,6 +17108,7 @@ determine_optimal_proto() {
|
|||
-ssl2) "$HAS_SSL2" || continue ;;
|
||||
*) ;;
|
||||
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") </dev/null >$TMPFILE 2>>$ERRFILE
|
||||
if sclient_auth $? $TMPFILE; then
|
||||
all_failed=false
|
||||
|
@ -17060,32 +17119,90 @@ determine_optimal_proto() {
|
|||
"$all_failed" && STARTTLS_OPTIMAL_PROTO=""
|
||||
debugme echo "STARTTLS_OPTIMAL_PROTO: $STARTTLS_OPTIMAL_PROTO"
|
||||
else
|
||||
for OPTIMAL_PROTO in '' -tls1_2 -tls1 -tls1_3 -ssl3 -tls1_1 -ssl2; do
|
||||
case $OPTIMAL_PROTO in
|
||||
-tls1_3) "$HAS_TLS13" || continue ;;
|
||||
-ssl3) "$HAS_SSL3" || continue ;;
|
||||
-ssl2) "$HAS_SSL2" || continue ;;
|
||||
*) ;;
|
||||
esac
|
||||
$OPENSSL s_client $(s_client_options "$OPTIMAL_PROTO $BUGS -connect "$NODEIP:$PORT" -msg $PROXY $SNI") </dev/null >$TMPFILE 2>>$ERRFILE
|
||||
if sclient_auth $? $TMPFILE; then
|
||||
# we use the successful handshake at least to get one valid protocol supported -- it saves us time later
|
||||
if [[ -z "$OPTIMAL_PROTO" ]]; then
|
||||
# convert to openssl terminology
|
||||
tmp=$(get_protocol $TMPFILE)
|
||||
tmp=${tmp/\./_}
|
||||
tmp=${tmp/v/}
|
||||
tmp="$(tolower $tmp)"
|
||||
add_tls_offered "${tmp}" yes
|
||||
else
|
||||
add_tls_offered "${OPTIMAL_PROTO/-/}" yes
|
||||
if "$using_sockets"; then
|
||||
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 0 ]] && all_failed=false && add_tls_offered ssl2 yes && OPTIMAL_PROTO="-ssl2"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
cp $TEMPDIR/$NODEIP.parse_tls_serverhello.txt $TMPFILE
|
||||
debugme echo "proto: $proto"
|
||||
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 ;;
|
||||
-ssl3) "$HAS_SSL3" || continue ;;
|
||||
-ssl2) "$HAS_SSL2" || continue ;;
|
||||
*) ;;
|
||||
esac
|
||||
$OPENSSL s_client $(s_client_options "$OPTIMAL_PROTO $BUGS -connect "$NODEIP:$PORT" -msg $PROXY $SNI") </dev/null >$TMPFILE 2>>$ERRFILE
|
||||
if sclient_auth $? $TMPFILE; then
|
||||
# we use the successful handshake at least to get one valid protocol supported -- it saves us time later
|
||||
if [[ -z "$OPTIMAL_PROTO" ]]; then
|
||||
# convert to openssl terminology
|
||||
tmp=$(get_protocol $TMPFILE)
|
||||
tmp=${tmp/\./_}
|
||||
tmp=${tmp/v/}
|
||||
tmp="$(tolower $tmp)"
|
||||
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"
|
||||
all_failed=false
|
||||
break
|
||||
fi
|
||||
debugme echo "one proto determined: $tmp"
|
||||
all_failed=false
|
||||
break
|
||||
fi
|
||||
all_failed=true
|
||||
done
|
||||
all_failed=true
|
||||
done
|
||||
fi
|
||||
"$all_failed" && OPTIMAL_PROTO=""
|
||||
debugme echo "OPTIMAL_PROTO: $OPTIMAL_PROTO"
|
||||
if [[ "$OPTIMAL_PROTO" == -ssl2 ]]; then
|
||||
|
@ -17093,8 +17210,8 @@ determine_optimal_proto() {
|
|||
ignore_no_or_lame " Type \"yes\" to proceed and accept false negatives or positives" "yes"
|
||||
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
|
||||
fi
|
||||
grep -q '^Server Temp Key' $TMPFILE && HAS_DH_BITS=true # FIX #190
|
||||
fi
|
||||
grep -q '^Server Temp Key' $TMPFILE && HAS_DH_BITS=true # FIX #190
|
||||
|
||||
if "$all_failed"; then
|
||||
outln
|
||||
|
@ -18424,6 +18541,7 @@ nodeip_to_proper_ip6() {
|
|||
reset_hostdepended_vars() {
|
||||
TLS_EXTENSIONS=""
|
||||
PROTOS_OFFERED=""
|
||||
CURVES_OFFERED=""
|
||||
OPTIMAL_PROTO=""
|
||||
SERVER_SIZE_LIMIT_BUG=false
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue