Skip to content

Commit 49dcd5b

Browse files
committed
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 ...)
1 parent 6173d80 commit 49dcd5b

1 file changed

Lines changed: 69 additions & 13 deletions

File tree

testssl.sh

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ MAX_OSSL_FAIL=${MAX_OSSL_FAIL:-2} # If this many failures for s_client con
205205
MAX_STARTTLS_FAIL=${MAX_STARTTLS_FAIL:-2} # max number of STARTTLS handshake failures in plaintext phase
206206
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
207207
MAX_WAITSOCK=${MAX_WAITSOCK:-10} # waiting at max 10 seconds for socket reply. There shouldn't be any reason to change this.
208+
QUIC_WAIT=${QUIC_WAIT:-3} # QUIC is UDP. Thus we run the connect in the background. This is how long to wait
208209
CCS_MAX_WAITSOCK=${CCS_MAX_WAITSOCK:-5} # for the two CCS payload (each). There shouldn't be any reason to change this.
209210
HEARTBLEED_MAX_WAITSOCK=${HEARTBLEED_MAX_WAITSOCK:-8} # for the heartbleed payload. There shouldn't be any reason to change this.
210211
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
339340
HAS_TLS11=false
340341
HAS_TLS12=false
341342
HAS_TLS13=false
343+
HAS_QUIC=false
344+
HAS2_QUIC=false # for automagically determined second OPENSSL version
342345
HAS_X448=false
343346
HAS_X25519=false
344347
HAS_SIGALGS=false
@@ -367,7 +370,7 @@ HAS_AES128_GCM=false
367370
HAS_AES256_GCM=false
368371
HAS_ZLIB=false
369372
HAS_UDS=false
370-
HAS_UDS2=false
373+
HAS2_UDS=false
371374
HAS_ENABLE_PHA=false
372375
HAS_DIG=false
373376
HAS_DIG_R=true
@@ -5468,6 +5471,7 @@ add_proto_offered() {
54685471
# arg1: protocol string or hex code for TLS protocol
54695472
# echos: 0 if proto known being offered, 1: known not being offered, 2: we don't know yet whether proto is being offered
54705473
# return value is always zero
5474+
#
54715475
has_server_protocol() {
54725476
local proto
54735477
local proto_val_pair
@@ -5502,6 +5506,7 @@ has_server_protocol() {
55025506

55035507

55045508
# the protocol check needs to be revamped. It sucks, see above
5509+
#
55055510
run_protocols() {
55065511
local using_sockets=true
55075512
local supported_no_ciph1="supported but couldn't detect a cipher (may need debugging)"
@@ -6125,10 +6130,55 @@ run_protocols() {
61256130
[[ $? -ne 0 ]] && exit $ERR_CLUELESS
61266131
fi
61276132

6133+
sub_quic
6134+
61286135
return $ret
61296136
}
61306137

61316138

6139+
# We do QUIC check first purely via OpenSSL, supposed it is supported by openssl
6140+
#
6141+
sub_quic() {
6142+
local alpn=""
6143+
local use_openssl=""
6144+
local sclient_outfile="$TEMPDIR/$NODEIP.quic_connect.txt"
6145+
local sclient_errfile="$TEMPDIR/$NODEIP.quic_connect_err.txt"
6146+
local jsonID="QUIC"
6147+
6148+
pr_bold " QUIC ";
6149+
6150+
[[ $DEBUG -ne 0 ]] && sclient_errfile=/dev/null
6151+
6152+
if "$HAS2_QUIC" || "$HAS_QUIC"; then
6153+
# Be aware: A proxy is not supported at all
6154+
# The s_client call would block if either the remote side doesn't support QUIC or outbound traffic is blocked
6155+
if "$HAS2_QUIC"; then
6156+
use_openssl="$OPENSSL2"
6157+
else
6158+
use_openssl="$OPENSSL"
6159+
fi
6160+
OPENSSL_CONF='' $use_openssl s_client -quic -alpn h3 -connect $NODEIP:$PORT -servername $NODE </dev/null \
6161+
2>$sclient_errfile >$sclient_outfile &
6162+
wait_kill $! $QUIC_WAIT
6163+
if [[ $? -ne 0 ]]; then
6164+
outln "not offered"
6165+
fileout "$jsonID" "INFO" "not offered"
6166+
else
6167+
pr_svrty_best "offered (OK)"
6168+
fileout "$jsonID" "OK" "offered"
6169+
alpn="$(awk -F':' '/^ALPN protocol/ { print $2 }' < $sclient_outfile)"
6170+
alpn="$(strip_spaces $alpn)"
6171+
outln ": $(awk '/^Protocol:/ { print $2 }' < $sclient_outfile) ($alpn)"
6172+
fi
6173+
else
6174+
prln_local_problem "No OpenSSL QUIC support"
6175+
fileout "$jsonID" "WARN" "not tested due to lack of local OpenSSL support"
6176+
fi
6177+
6178+
return 0
6179+
}
6180+
6181+
61326182
# list ciphers (and makes sure you have them locally configured)
61336183
# arg[1]: non-TLSv1.3 cipher list (or anything else)
61346184
# arg[2]: TLSv1.3 cipher list
@@ -19900,7 +19950,7 @@ run_starttls_injection() {
1990019950
outln "Need socat for this check"
1990119951
return 1
1990219952
fi
19903-
if ! "$HAS_UDS2" && ! "$HAS_UDS"; then
19953+
if ! "$HAS2_UDS" && ! "$HAS_UDS"; then
1990419954
fileout "$jsonID" "WARN" "Need OpenSSL with Unix-domain socket s_client support for this check" "$cve" "$cwe" "$hint"
1990519955
outln "Need an OpenSSL with Unix-domain socket s_client support for this check"
1990619956
return 1
@@ -19926,7 +19976,7 @@ run_starttls_injection() {
1992619976

1992719977
if "$HAS_UDS"; then
1992819978
openssl_bin="$OPENSSL"
19929-
elif "$HAS_UDS2"; then
19979+
elif "$HAS2_UDS"; then
1993019980
openssl_bin="$OPENSSL2"
1993119981
fi
1993219982
# 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() {
2068420734
local s_client_has=$TEMPDIR/s_client_has.txt
2068520735
local s_client_has2=$TEMPDIR/s_client_has2.txt
2068620736
local s_client_starttls_has=$TEMPDIR/s_client_starttls_has.txt
20687-
local s_client_starttls_has2=$TEMPDIR/s_client_starttls_has2
20737+
local s_client2_starttls_has=$TEMPDIR/s_client2_starttls_has
2068820738
local openssl_location="" cwd=""
2068920739
local curve="" ossl_tls13_supported_curves
2069020740
local ossl_line1="" yr=""
@@ -20831,7 +20881,7 @@ find_openssl_binary() {
2083120881
HAS_AES256_GCM=false
2083220882
HAS_ZLIB=false
2083320883
HAS_UDS=false
20834-
HAS_UDS2=false
20884+
HAS2_UDS=false
2083520885
TRUSTED1ST=""
2083620886
HAS_ENABLE_PHA=false
2083720887

@@ -20868,16 +20918,20 @@ find_openssl_binary() {
2086820918
$OPENSSL s_client -tls1_3 -sigalgs PSS+SHA256:PSS+SHA384 $NXCONNECT </dev/null 2>&1 | grep -aiq "unknown option" || HAS_SIGALGS=true
2086920919
fi
2087020920

20921+
if [[ -x $OPENSSL2 ]] && OPENSSL_CONF='' $OPENSSL2 s_client -quic 2>&1 | grep -qi 'QUIC requires ALPN'; then
20922+
HAS2_QUIC="true"
20923+
elif OPENSSL_CONF='' $OPENSSL s_client -quic 2>&1 | grep -qi 'QUIC requires ALPN'; then
20924+
HAS_QUIC="true"
20925+
fi
20926+
2087120927
$OPENSSL s_client -noservername </dev/null 2>&1 | grep -aiq "unknown option" || HAS_NOSERVERNAME=true
2087220928
$OPENSSL s_client -ciphersuites </dev/null 2>&1 | grep -aiq "unknown option" || HAS_CIPHERSUITES=true
20873-
20874-
$OPENSSL ciphers @SECLEVEL=0:ALL > /dev/null 2> /dev/null && HAS_SECLEVEL=true
20875-
2087620929
$OPENSSL s_client -comp </dev/null 2>&1 | grep -aiq "unknown option" || HAS_COMP=true
2087720930
$OPENSSL s_client -no_comp </dev/null 2>&1 | grep -aiq "unknown option" || HAS_NO_COMP=true
2087820931

20879-
OPENSSL_NR_CIPHERS=$(count_ciphers "$(actually_supported_osslciphers 'ALL:COMPLEMENTOFALL' 'ALL')")
20932+
$OPENSSL ciphers @SECLEVEL=0:ALL > /dev/null 2> /dev/null && HAS_SECLEVEL=true
2088020933

20934+
OPENSSL_NR_CIPHERS=$(count_ciphers "$(actually_supported_osslciphers 'ALL:COMPLEMENTOFALL' 'ALL')")
2088120935
if [[ $OPENSSL_NR_CIPHERS -le 140 ]]; then
2088220936
[[ "$OSSL_NAME" =~ LibreSSL ]] && [[ ${OSSL_VER//./} -ge 210 ]] && HAS_DH_BITS=true
2088320937
if "$SSL_NATIVE"; then
@@ -20981,9 +21035,9 @@ find_openssl_binary() {
2098121035
# We also check, whether there's $OPENSSL2 which has TLS 1.3
2098221036
if [[ ! "$OSSL_NAME" =~ LibreSSL ]] && [[ ! $OSSL_VER =~ 1.1.1 ]] && [[ $OSSL_VER_MAJOR -lt 3 ]]; then
2098321037
OPENSSL_CONF='' $OPENSSL2 s_client -help 2>$s_client_has2
20984-
OPENSSL_CONF='' $OPENSSL2 s_client -starttls foo 2>$s_client_starttls_has2
20985-
grep -q 'Unix-domain socket' $s_client_has2 && HAS_UDS2=true
20986-
grep -q 'xmpp-server' $s_client_starttls_has2 && HAS_XMPP_SERVER2=true
21038+
OPENSSL_CONF='' $OPENSSL2 s_client -starttls foo 2>$s_client2_starttls_has
21039+
grep -q 'Unix-domain socket' $s_client_has2 && HAS2_UDS=true
21040+
grep -q 'xmpp-server' $s_client2_starttls_has && HAS_XMPP_SERVER2=true
2098721041
# Likely we don't need the following second check here, see 6 lines above
2098821042
if grep -wq 'tls1_3' $s_client_has2; then
2098921043
OPENSSL_CONF='' OPENSSL2_HAS_TLS_1_3=true
@@ -21339,6 +21393,8 @@ HAS_TLS1: $HAS_TLS1
2133921393
HAS_TLS11: $HAS_TLS11
2134021394
HAS_TLS12: $HAS_TLS12
2134121395
HAS_TLS13: $HAS_TLS13
21396+
HAS_QUIC: $HAS_QUIC
21397+
HAS2_QUIC: $HAS2_QUIC
2134221398
HAS_X448: $HAS_X448
2134321399
HAS_X25519: $HAS_X25519
2134421400
HAS_SIGALGS: $HAS_SIGALGS
@@ -21363,7 +21419,7 @@ HAS_SIEVE: $HAS_SIEVE
2136321419
HAS_NNTP: $HAS_NNTP
2136421420
HAS_IRC: $HAS_IRC
2136521421
HAS_UDS: $HAS_UDS
21366-
HAS_UDS2: $HAS_UDS2
21422+
HAS2_UDS: $HAS2_UDS
2136721423
HAS_ENABLE_PHA: $HAS_ENABLE_PHA
2136821424

2136921425
HAS_DIG: $HAS_DIG

0 commit comments

Comments
 (0)