mirror of
https://github.com/drwetter/testssl.sh.git
synced 2025-09-06 03:52:54 +02:00
First try for QUIC (OpenSSL only)
This is an implementation for QUIC (RFC 9000, RFC 9114). It's purely OpenSSL based for now. As some distros support newer (>= 3.2) versions this works on some distros now and will work on more as time goes by. It has been tested with MacOS and Linux. If there's an OpenSSL version in /usr/bin/ it will automagically use that version. A new short sub function named sub_quic() was introduced for handling this as run_protocols() is already "full". It appears below TLS 1.3. A check against HTTPS RR #2484 is planned but not implemented yet. PR #2484 has to be worked on and merged before. New variables were introduces (HAS_QUIC/ +HAS2_QUIC). Also there's QUIC_WAIT as we run the connect in the background and we need a wait time. HAS_UDS2 was renamed to HAS2_UDS as HAS2 should signal this is for OPENSSL2 and UDS2 doesn't make sense. To clarify: - check for a proxy and then don't do the check? - short unit test (t/31_isJSON_valid.t cjecks cloudflare but ...)
This commit is contained in:
82
testssl.sh
82
testssl.sh
@ -205,6 +205,7 @@ MAX_OSSL_FAIL=${MAX_OSSL_FAIL:-2} # If this many failures for s_client con
|
|||||||
MAX_STARTTLS_FAIL=${MAX_STARTTLS_FAIL:-2} # max number of STARTTLS handshake failures in plaintext phase
|
MAX_STARTTLS_FAIL=${MAX_STARTTLS_FAIL:-2} # max number of STARTTLS handshake failures in plaintext phase
|
||||||
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_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.
|
MAX_WAITSOCK=${MAX_WAITSOCK:-10} # waiting at max 10 seconds for socket reply. There shouldn't be any reason to change this.
|
||||||
|
QUIC_WAIT=${QUIC_WAIT:-3} # QUIC is UDP. Thus we run the connect in the background. This is how long to wait
|
||||||
CCS_MAX_WAITSOCK=${CCS_MAX_WAITSOCK:-5} # for the two CCS payload (each). 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.
|
HEARTBLEED_MAX_WAITSOCK=${HEARTBLEED_MAX_WAITSOCK:-8} # for the heartbleed payload. There shouldn't be any reason to change this.
|
||||||
STARTTLS_SLEEP=${STARTTLS_SLEEP:-10} # max time wait on a socket for STARTTLS. MySQL has a fixed value of 1 which can't be overwritten (#914)
|
STARTTLS_SLEEP=${STARTTLS_SLEEP:-10} # max time wait on a socket for STARTTLS. MySQL has a fixed value of 1 which can't be overwritten (#914)
|
||||||
@ -339,6 +340,8 @@ HAS_TLS1=false
|
|||||||
HAS_TLS11=false
|
HAS_TLS11=false
|
||||||
HAS_TLS12=false
|
HAS_TLS12=false
|
||||||
HAS_TLS13=false
|
HAS_TLS13=false
|
||||||
|
HAS_QUIC=false
|
||||||
|
HAS2_QUIC=false # for automagically determined second OPENSSL version
|
||||||
HAS_X448=false
|
HAS_X448=false
|
||||||
HAS_X25519=false
|
HAS_X25519=false
|
||||||
HAS_SIGALGS=false
|
HAS_SIGALGS=false
|
||||||
@ -367,7 +370,7 @@ HAS_AES128_GCM=false
|
|||||||
HAS_AES256_GCM=false
|
HAS_AES256_GCM=false
|
||||||
HAS_ZLIB=false
|
HAS_ZLIB=false
|
||||||
HAS_UDS=false
|
HAS_UDS=false
|
||||||
HAS_UDS2=false
|
HAS2_UDS=false
|
||||||
HAS_ENABLE_PHA=false
|
HAS_ENABLE_PHA=false
|
||||||
HAS_DIG=false
|
HAS_DIG=false
|
||||||
HAS_DIG_R=true
|
HAS_DIG_R=true
|
||||||
@ -5468,6 +5471,7 @@ add_proto_offered() {
|
|||||||
# arg1: protocol string or hex code for TLS protocol
|
# arg1: protocol string or hex code for TLS protocol
|
||||||
# echos: 0 if proto known being offered, 1: known not being offered, 2: we don't know yet whether proto is being offered
|
# echos: 0 if proto known being offered, 1: known not being offered, 2: we don't know yet whether proto is being offered
|
||||||
# return value is always zero
|
# return value is always zero
|
||||||
|
#
|
||||||
has_server_protocol() {
|
has_server_protocol() {
|
||||||
local proto
|
local proto
|
||||||
local proto_val_pair
|
local proto_val_pair
|
||||||
@ -5502,6 +5506,7 @@ has_server_protocol() {
|
|||||||
|
|
||||||
|
|
||||||
# the protocol check needs to be revamped. It sucks, see above
|
# the protocol check needs to be revamped. It sucks, see above
|
||||||
|
#
|
||||||
run_protocols() {
|
run_protocols() {
|
||||||
local using_sockets=true
|
local using_sockets=true
|
||||||
local supported_no_ciph1="supported but couldn't detect a cipher (may need debugging)"
|
local supported_no_ciph1="supported but couldn't detect a cipher (may need debugging)"
|
||||||
@ -6125,10 +6130,55 @@ run_protocols() {
|
|||||||
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
|
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
sub_quic
|
||||||
|
|
||||||
return $ret
|
return $ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# We do QUIC check first purely via OpenSSL, supposed it is supported by openssl
|
||||||
|
#
|
||||||
|
sub_quic() {
|
||||||
|
local alpn=""
|
||||||
|
local use_openssl=""
|
||||||
|
local sclient_outfile="$TEMPDIR/$NODEIP.quic_connect.txt"
|
||||||
|
local sclient_errfile="$TEMPDIR/$NODEIP.quic_connect_err.txt"
|
||||||
|
local jsonID="QUIC"
|
||||||
|
|
||||||
|
pr_bold " QUIC ";
|
||||||
|
|
||||||
|
[[ $DEBUG -ne 0 ]] && sclient_errfile=/dev/null
|
||||||
|
|
||||||
|
if "$HAS2_QUIC" || "$HAS_QUIC"; then
|
||||||
|
# Be aware: A proxy is not supported at all
|
||||||
|
# The s_client call would block if either the remote side doesn't support QUIC or outbound traffic is blocked
|
||||||
|
if "$HAS2_QUIC"; then
|
||||||
|
use_openssl="$OPENSSL2"
|
||||||
|
else
|
||||||
|
use_openssl="$OPENSSL"
|
||||||
|
fi
|
||||||
|
OPENSSL_CONF='' $use_openssl s_client -quic -alpn h3 -connect $NODEIP:$PORT -servername $NODE </dev/null \
|
||||||
|
2>$sclient_errfile >$sclient_outfile &
|
||||||
|
wait_kill $! $QUIC_WAIT
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
outln "not offered"
|
||||||
|
fileout "$jsonID" "INFO" "not offered"
|
||||||
|
else
|
||||||
|
pr_svrty_best "offered (OK)"
|
||||||
|
fileout "$jsonID" "OK" "offered"
|
||||||
|
alpn="$(awk -F':' '/^ALPN protocol/ { print $2 }' < $sclient_outfile)"
|
||||||
|
alpn="$(strip_spaces $alpn)"
|
||||||
|
outln ": $(awk '/^Protocol:/ { print $2 }' < $sclient_outfile) ($alpn)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
prln_local_problem "No OpenSSL QUIC support"
|
||||||
|
fileout "$jsonID" "WARN" "not tested due to lack of local OpenSSL support"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# list ciphers (and makes sure you have them locally configured)
|
# list ciphers (and makes sure you have them locally configured)
|
||||||
# arg[1]: non-TLSv1.3 cipher list (or anything else)
|
# arg[1]: non-TLSv1.3 cipher list (or anything else)
|
||||||
# arg[2]: TLSv1.3 cipher list
|
# arg[2]: TLSv1.3 cipher list
|
||||||
@ -19900,7 +19950,7 @@ run_starttls_injection() {
|
|||||||
outln "Need socat for this check"
|
outln "Need socat for this check"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
if ! "$HAS_UDS2" && ! "$HAS_UDS"; then
|
if ! "$HAS2_UDS" && ! "$HAS_UDS"; then
|
||||||
fileout "$jsonID" "WARN" "Need OpenSSL with Unix-domain socket s_client support for this check" "$cve" "$cwe" "$hint"
|
fileout "$jsonID" "WARN" "Need OpenSSL with Unix-domain socket s_client support for this check" "$cve" "$cwe" "$hint"
|
||||||
outln "Need an OpenSSL with Unix-domain socket s_client support for this check"
|
outln "Need an OpenSSL with Unix-domain socket s_client support for this check"
|
||||||
return 1
|
return 1
|
||||||
@ -19926,7 +19976,7 @@ run_starttls_injection() {
|
|||||||
|
|
||||||
if "$HAS_UDS"; then
|
if "$HAS_UDS"; then
|
||||||
openssl_bin="$OPENSSL"
|
openssl_bin="$OPENSSL"
|
||||||
elif "$HAS_UDS2"; then
|
elif "$HAS2_UDS"; then
|
||||||
openssl_bin="$OPENSSL2"
|
openssl_bin="$OPENSSL2"
|
||||||
fi
|
fi
|
||||||
# normally the interesting fallback we grep later for is in fd2 but we'll catch also stdout here
|
# normally the interesting fallback we grep later for is in fd2 but we'll catch also stdout here
|
||||||
@ -20684,7 +20734,7 @@ find_openssl_binary() {
|
|||||||
local s_client_has=$TEMPDIR/s_client_has.txt
|
local s_client_has=$TEMPDIR/s_client_has.txt
|
||||||
local s_client_has2=$TEMPDIR/s_client_has2.txt
|
local s_client_has2=$TEMPDIR/s_client_has2.txt
|
||||||
local s_client_starttls_has=$TEMPDIR/s_client_starttls_has.txt
|
local s_client_starttls_has=$TEMPDIR/s_client_starttls_has.txt
|
||||||
local s_client_starttls_has2=$TEMPDIR/s_client_starttls_has2
|
local s_client2_starttls_has=$TEMPDIR/s_client2_starttls_has
|
||||||
local openssl_location="" cwd=""
|
local openssl_location="" cwd=""
|
||||||
local curve="" ossl_tls13_supported_curves
|
local curve="" ossl_tls13_supported_curves
|
||||||
local ossl_line1="" yr=""
|
local ossl_line1="" yr=""
|
||||||
@ -20831,7 +20881,7 @@ find_openssl_binary() {
|
|||||||
HAS_AES256_GCM=false
|
HAS_AES256_GCM=false
|
||||||
HAS_ZLIB=false
|
HAS_ZLIB=false
|
||||||
HAS_UDS=false
|
HAS_UDS=false
|
||||||
HAS_UDS2=false
|
HAS2_UDS=false
|
||||||
TRUSTED1ST=""
|
TRUSTED1ST=""
|
||||||
HAS_ENABLE_PHA=false
|
HAS_ENABLE_PHA=false
|
||||||
|
|
||||||
@ -20868,16 +20918,20 @@ find_openssl_binary() {
|
|||||||
$OPENSSL s_client -tls1_3 -sigalgs PSS+SHA256:PSS+SHA384 $NXCONNECT </dev/null 2>&1 | grep -aiq "unknown option" || HAS_SIGALGS=true
|
$OPENSSL s_client -tls1_3 -sigalgs PSS+SHA256:PSS+SHA384 $NXCONNECT </dev/null 2>&1 | grep -aiq "unknown option" || HAS_SIGALGS=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -x $OPENSSL2 ]] && OPENSSL_CONF='' $OPENSSL2 s_client -quic 2>&1 | grep -qi 'QUIC requires ALPN'; then
|
||||||
|
HAS2_QUIC="true"
|
||||||
|
elif OPENSSL_CONF='' $OPENSSL s_client -quic 2>&1 | grep -qi 'QUIC requires ALPN'; then
|
||||||
|
HAS_QUIC="true"
|
||||||
|
fi
|
||||||
|
|
||||||
$OPENSSL s_client -noservername </dev/null 2>&1 | grep -aiq "unknown option" || HAS_NOSERVERNAME=true
|
$OPENSSL s_client -noservername </dev/null 2>&1 | grep -aiq "unknown option" || HAS_NOSERVERNAME=true
|
||||||
$OPENSSL s_client -ciphersuites </dev/null 2>&1 | grep -aiq "unknown option" || HAS_CIPHERSUITES=true
|
$OPENSSL s_client -ciphersuites </dev/null 2>&1 | grep -aiq "unknown option" || HAS_CIPHERSUITES=true
|
||||||
|
|
||||||
$OPENSSL ciphers @SECLEVEL=0:ALL > /dev/null 2> /dev/null && HAS_SECLEVEL=true
|
|
||||||
|
|
||||||
$OPENSSL s_client -comp </dev/null 2>&1 | grep -aiq "unknown option" || HAS_COMP=true
|
$OPENSSL s_client -comp </dev/null 2>&1 | grep -aiq "unknown option" || HAS_COMP=true
|
||||||
$OPENSSL s_client -no_comp </dev/null 2>&1 | grep -aiq "unknown option" || HAS_NO_COMP=true
|
$OPENSSL s_client -no_comp </dev/null 2>&1 | grep -aiq "unknown option" || HAS_NO_COMP=true
|
||||||
|
|
||||||
OPENSSL_NR_CIPHERS=$(count_ciphers "$(actually_supported_osslciphers 'ALL:COMPLEMENTOFALL' 'ALL')")
|
$OPENSSL ciphers @SECLEVEL=0:ALL > /dev/null 2> /dev/null && HAS_SECLEVEL=true
|
||||||
|
|
||||||
|
OPENSSL_NR_CIPHERS=$(count_ciphers "$(actually_supported_osslciphers 'ALL:COMPLEMENTOFALL' 'ALL')")
|
||||||
if [[ $OPENSSL_NR_CIPHERS -le 140 ]]; then
|
if [[ $OPENSSL_NR_CIPHERS -le 140 ]]; then
|
||||||
[[ "$OSSL_NAME" =~ LibreSSL ]] && [[ ${OSSL_VER//./} -ge 210 ]] && HAS_DH_BITS=true
|
[[ "$OSSL_NAME" =~ LibreSSL ]] && [[ ${OSSL_VER//./} -ge 210 ]] && HAS_DH_BITS=true
|
||||||
if "$SSL_NATIVE"; then
|
if "$SSL_NATIVE"; then
|
||||||
@ -20981,9 +21035,9 @@ find_openssl_binary() {
|
|||||||
# We also check, whether there's $OPENSSL2 which has TLS 1.3
|
# We also check, whether there's $OPENSSL2 which has TLS 1.3
|
||||||
if [[ ! "$OSSL_NAME" =~ LibreSSL ]] && [[ ! $OSSL_VER =~ 1.1.1 ]] && [[ $OSSL_VER_MAJOR -lt 3 ]]; then
|
if [[ ! "$OSSL_NAME" =~ LibreSSL ]] && [[ ! $OSSL_VER =~ 1.1.1 ]] && [[ $OSSL_VER_MAJOR -lt 3 ]]; then
|
||||||
OPENSSL_CONF='' $OPENSSL2 s_client -help 2>$s_client_has2
|
OPENSSL_CONF='' $OPENSSL2 s_client -help 2>$s_client_has2
|
||||||
OPENSSL_CONF='' $OPENSSL2 s_client -starttls foo 2>$s_client_starttls_has2
|
OPENSSL_CONF='' $OPENSSL2 s_client -starttls foo 2>$s_client2_starttls_has
|
||||||
grep -q 'Unix-domain socket' $s_client_has2 && HAS_UDS2=true
|
grep -q 'Unix-domain socket' $s_client_has2 && HAS2_UDS=true
|
||||||
grep -q 'xmpp-server' $s_client_starttls_has2 && HAS_XMPP_SERVER2=true
|
grep -q 'xmpp-server' $s_client2_starttls_has && HAS_XMPP_SERVER2=true
|
||||||
# Likely we don't need the following second check here, see 6 lines above
|
# Likely we don't need the following second check here, see 6 lines above
|
||||||
if grep -wq 'tls1_3' $s_client_has2; then
|
if grep -wq 'tls1_3' $s_client_has2; then
|
||||||
OPENSSL_CONF='' OPENSSL2_HAS_TLS_1_3=true
|
OPENSSL_CONF='' OPENSSL2_HAS_TLS_1_3=true
|
||||||
@ -21339,6 +21393,8 @@ HAS_TLS1: $HAS_TLS1
|
|||||||
HAS_TLS11: $HAS_TLS11
|
HAS_TLS11: $HAS_TLS11
|
||||||
HAS_TLS12: $HAS_TLS12
|
HAS_TLS12: $HAS_TLS12
|
||||||
HAS_TLS13: $HAS_TLS13
|
HAS_TLS13: $HAS_TLS13
|
||||||
|
HAS_QUIC: $HAS_QUIC
|
||||||
|
HAS2_QUIC: $HAS2_QUIC
|
||||||
HAS_X448: $HAS_X448
|
HAS_X448: $HAS_X448
|
||||||
HAS_X25519: $HAS_X25519
|
HAS_X25519: $HAS_X25519
|
||||||
HAS_SIGALGS: $HAS_SIGALGS
|
HAS_SIGALGS: $HAS_SIGALGS
|
||||||
@ -21363,7 +21419,7 @@ HAS_SIEVE: $HAS_SIEVE
|
|||||||
HAS_NNTP: $HAS_NNTP
|
HAS_NNTP: $HAS_NNTP
|
||||||
HAS_IRC: $HAS_IRC
|
HAS_IRC: $HAS_IRC
|
||||||
HAS_UDS: $HAS_UDS
|
HAS_UDS: $HAS_UDS
|
||||||
HAS_UDS2: $HAS_UDS2
|
HAS2_UDS: $HAS2_UDS
|
||||||
HAS_ENABLE_PHA: $HAS_ENABLE_PHA
|
HAS_ENABLE_PHA: $HAS_ENABLE_PHA
|
||||||
|
|
||||||
HAS_DIG: $HAS_DIG
|
HAS_DIG: $HAS_DIG
|
||||||
|
Reference in New Issue
Block a user