Skip to content

Commit f8d3df7

Browse files
committed
Make QUIC protocol detction more reliable
The site from that billioniare who made nazi gestures delivers a UDP response without proper TLS handshake. This led to a false positive as if the site supports QUIC via h3. This PR makes the detection of QUIC more robust by adding a certificate check and also take better the return values from `wait_kill()` into account. It also introduces a function to remove any non printable chars (depending on the LC_ALL var): `filter_printable()` Also `sanitze_http_header()` doesn't operate anymore on a global variable which is kind of not best practise as it is easily to avoid here.
1 parent b375755 commit f8d3df7

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

testssl.sh

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -877,14 +877,20 @@ strip_spaces() {
877877
echo "${1// /}"
878878
}
879879

880-
# https://web.archive.org/web/20121022051228/http://codesnippets.joyent.com/posts/show/1816
881880
strip_leading_space() {
881+
# https://web.archive.org/web/20121022051228/http://codesnippets.joyent.com/posts/show/1816
882882
printf "%s" "${1#"${1%%[![:space:]]*}"}"
883883
}
884+
884885
strip_trailing_space() {
885886
printf "%s" "${1%"${1##*[![:space:]]}"}"
886887
}
887888

889+
filter_printable() {
890+
# redir of stderr as Mac's sed might throw an error
891+
sed -i 's/[^[:print:]]//g' $1 2>/dev/null
892+
}
893+
888894
is_number() {
889895
[[ "$1" =~ ^[1-9][0-9]*$ ]] && \
890896
return 0 || \
@@ -904,8 +910,8 @@ strip_quote() (
904910
)"
905911
)
906912

907-
# Converts a string containing PEM encoded data to one line.
908913
pem_to_one_line() {
914+
# Converts a string containing PEM encoded data to one line.
909915
local pem="$1"
910916
local header="" footer=""
911917

@@ -2570,18 +2576,20 @@ connectivity_problem() {
25702576
fi
25712577
}
25722578

2579+
25732580
sanitze_http_header() {
2574-
# sed implementations tested were sometime not fine with header containing x0d x0a (CRLF) which is the usual
2575-
# case. Also we use tr here to remove any crtl chars which the server side offers --> possible security problem
2576-
# Only allowed now is LF + CR. See #2337. awk, see above, doesn't seem to care -- but not under MacOS.
2577-
sed -e '/^$/q' -e '/^[^a-zA-Z_0-9]$/q' $HEADERFILE | tr -d '\000-\011\013\014\016-\037' >$HEADERFILE.tmp
2578-
# Now to be more sure we delete from '<' or '{' maybe with a leading blank until the end
2579-
sed -e '/^ *<.*$/d' -e '/^ *{.*$/d' $HEADERFILE.tmp >$HEADERFILE
2580-
debugme echo -e "---\n $(< $HEADERFILE) \n---"
2581+
# sp,e sed implementations tested were sometime not fine with HTTP headers containing x0d x0a (CRLF) which is
2582+
# usuallly the case. Also we use tr here to remove any crtl chars which the server side offers --> possible
2583+
# security problem. Only allowed now is LF + CR. See #2337. awk, see above, doesn't seem to care -- not under MacOS.
2584+
sed -e '/^$/q' -e '/^[^a-zA-Z_0-9]$/q' $1 | tr -d '\000-\011\013\014\016-\037' >$1.tmp
2585+
# Now to be more sure we delete from '<' or '{' maybe with a leading blank until the end (HTTP body)
2586+
sed -e '/^ *<.*$/d' -e '/^ *{.*$/d' $1.tmp >$1
2587+
debugme echo -e "---\n $(< $1) \n---"
25812588
}
25822589

25832590

25842591
#problems not handled: chunked
2592+
#
25852593
run_http_header() {
25862594
local header
25872595
local referer useragent
@@ -2611,9 +2619,9 @@ run_http_header() {
26112619
tm_out "$GET_REQ11" | $OPENSSL s_client $(s_client_options "$OPTIMAL_PROTO $BUGS -quiet -ign_eof -connect $NODEIP:$PORT $PROXY $SNI") >$HEADERFILE 2>$ERRFILE
26122620
NOW_TIME=$(date "+%s")
26132621
HAD_SLEPT=0
2614-
sanitze_http_header
2622+
sanitze_http_header $HEADERFILE
26152623
else
2616-
sanitze_http_header
2624+
sanitze_http_header $HEADERFILE
26172625
# 1st GET request hung and needed to be killed. Check whether it succeeded anyway:
26182626
if grep -Eiaq "XML|HTML|DOCTYPE|HTTP|Connection" $HEADERFILE; then
26192627
# correct by seconds we slept, HAD_SLEPT comes from wait_kill()
@@ -6216,6 +6224,7 @@ sub_quic() {
62166224
local alpn=""
62176225
local use_openssl=""
62186226
local proxy_hint_str=""
6227+
local ret=""
62196228
local sclient_outfile="$TEMPDIR/$NODEIP.quic_connect.txt"
62206229
local sclient_errfile="$TEMPDIR/$NODEIP.quic_connect_err.txt"
62216230
local jsonID="QUIC"
@@ -6226,7 +6235,7 @@ sub_quic() {
62266235
pr_bold " QUIC ";
62276236

62286237
if "$HAS2_QUIC" || "$HAS_QUIC"; then
6229-
# Proxying QUIC is not supported
6238+
# Proxying QUIC seems not supported
62306239
# The s_client call would block if either the remote side doesn't support QUIC or outbound traffic is blocked
62316240
if "$HAS2_QUIC"; then
62326241
use_openssl="$OPENSSL2"
@@ -6236,18 +6245,30 @@ sub_quic() {
62366245
OPENSSL_CONF='' $use_openssl s_client -quic -alpn h3 -connect $NODEIP:$PORT -servername $NODE </dev/null \
62376246
2>$sclient_errfile >$sclient_outfile &
62386247
wait_kill $! $QUIC_WAIT
6239-
if [[ $? -ne 0 ]]; then
6248+
ret=$?
6249+
if [[ $ret -eq 3 ]]; then
6250+
# process was killed
62406251
if [[ -n "$PROXY" ]]; then
6241-
proxy_hint_str="(tried directly, is not proxyable): "
6252+
proxy_hint_str="(QUIC is not proxyable, tried directly): "
62426253
fi
62436254
outln "${proxy_hint_str}not offered or timed out"
62446255
fileout "$jsonID" "INFO" "$proxy_hint_str not offered"
62456256
else
6246-
pr_svrty_best "offered (OK)"
6247-
fileout "$jsonID" "OK" "offered"
6248-
alpn="$(awk -F':' '/^ALPN protocol/ { print $2 }' < $sclient_outfile)"
6249-
alpn="$(strip_spaces $alpn)"
6250-
outln ": $(awk '/^Protocol:/ { print $2 }' < $sclient_outfile) ($alpn)"
6257+
# 0 would be process terminated before be killed. Now findout what happened...
6258+
filter_printable $sclient_outfile
6259+
if [[ $(< $sclient_outfile) =~ CERTIFICATE----- ]]; then
6260+
pr_svrty_best "offered (OK)"
6261+
fileout "$jsonID" "OK" "offered"
6262+
alpn="$(awk -F':' '/^ALPN protocol/ { print $2 }' < $sclient_outfile)"
6263+
alpn="$(strip_spaces $alpn)"
6264+
outln ": $(awk '/^Protocol:/ { print $2 }' 2>/dev/null < $sclient_outfile) ($alpn)"
6265+
elif [[ $(< $sclient_outfile) =~ ^CONNECTED\( ]]; then
6266+
outln "not offered (but UDP connection succeeded)"
6267+
fileout "$jsonID" "INFO" "not offered (but UDP connection succeeded)"
6268+
else
6269+
outln "not offered"
6270+
fileout "$jsonID" "INFO" "not offered"
6271+
fi
62516272
fi
62526273
else
62536274
prln_local_problem "No OpenSSL QUIC support"

0 commit comments

Comments
 (0)