Skip to content

Commit 9db3ba4

Browse files
author
David Cooper
committed
ClientHello with small first TCP fragment
Some servers will reject a ClientHello if when sent the first TCP fragment is less than 9 bytes. This commit adds a test for that problem by sending ClientHello messages such such short TCP fragments. It tries initial fragments lengths of 5, 6, 7, and 8 bytes, and tries each of these lengths twice, and reports a problem only if the connection fails only every attempt. The reason for the repeated attempts is that some servers will occasionally fail these tests, and the goal is to only report a problem if testssl#1113 would have reported a problem.
1 parent 742e01e commit 9db3ba4

1 file changed

Lines changed: 39 additions & 4 deletions

File tree

testssl.sh

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9957,12 +9957,30 @@ code2network() {
99579957
# sockets inspired by http://blog.chris007.de/?p=238
99589958
# ARG1: hexbytes separated by commas, with a leading comma
99599959
# ARG2: seconds to sleep
9960+
# ARG3: the size of the first message fragment to send
99609961
socksend_clienthello() {
99619962
local data=""
9962-
9963+
local -i i first_fragment_size=0
9964+
local first_fragment
9965+
9966+
[[ -n "$3" ]] && first_fragment_size="$3"
99639967
code2network "$1"
99649968
data="$NW_STR"
99659969
[[ "$DEBUG" -ge 4 ]] && echo && echo "\"$data\""
9970+
if [[ $first_fragment_size -ne 0 ]]; then
9971+
for (( i=1; i < ${#data}; i++ )); do
9972+
[[ "${data:i:1}" == '\' ]] && first_fragment_size=$first_fragment_size-1
9973+
[[ $first_fragment_size -eq 0 ]] && break
9974+
done
9975+
first_fragment="${data:0:i}"
9976+
data="${data:i}"
9977+
if [[ -z "$PRINTF" ]] ;then
9978+
# We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower
9979+
printf -- "$first_fragment" | cat >&5 2>/dev/null &
9980+
else
9981+
$PRINTF -- "$first_fragment" 2>/dev/null >&5 2>/dev/null &
9982+
fi
9983+
fi
99669984
if [[ -z "$PRINTF" ]] ;then
99679985
# We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower
99689986
printf -- "$data" | cat >&5 2>/dev/null &
@@ -12449,7 +12467,7 @@ generate_key_share_extension() {
1244912467
# ARG4: (optional) additional request extensions
1245012468
# ARG5: (optional): "true" if ClientHello should advertise compression methods other than "NULL"
1245112469
# ARG6: (optional): "false" if prepare_tls_clienthello() should not open a new socket
12452-
#
12470+
# ARG7: (optional): the size of the first message fragment to send.
1245312471
prepare_tls_clienthello() {
1245412472
local tls_low_byte="$1" tls_legacy_version="$1"
1245512473
local process_full="$3"
@@ -12470,6 +12488,7 @@ prepare_tls_clienthello() {
1247012488
local extensions_key_share="" extn_type supported_groups_c2n="" extn_psk_mode=""
1247112489
local extra_extensions extra_extensions_list="" extension_supported_versions=""
1247212490
local offer_compression=false compression_methods
12491+
local first_fragment_size="$7"
1247312492

1247412493
# TLSv1.3 ClientHello messages MUST specify only the NULL compression method.
1247512494
[[ "$5" == true ]] && [[ "0x$tls_low_byte" -le "0x03" ]] && offer_compression=true
@@ -12848,7 +12867,7 @@ prepare_tls_clienthello() {
1284812867
fi
1284912868

1285012869
debugme echo -n "sending client hello... "
12851-
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND
12870+
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND $first_fragment_size
1285212871

1285312872
if [[ "$tls_low_byte" -gt 0x03 ]]; then
1285412873
TLS_CLIENT_HELLO="$(tolower "$NW_STR")"
@@ -13066,6 +13085,7 @@ resend_if_hello_retry_request() {
1306613085
# arg4: (optional) additional request extensions
1306713086
# arg5: (optional) "true" if ClientHello should advertise compression methods other than "NULL"
1306813087
# arg6: (optional) "false" if the connection should not be closed before the function returns.
13088+
# arg7: (optional) the size of the first message fragment to send.
1306913089
# return: 0: successful connect | 1: protocol or cipher not available | 2: as (0) but downgraded
1307013090
# 6: couldn't open socket | 7: couldn't open temp file
1307113091
tls_sockets() {
@@ -13098,7 +13118,7 @@ tls_sockets() {
1309813118
cipher_list_2send="$NW_STR"
1309913119

1310013120
debugme echo -en "\nsending client hello... "
13101-
prepare_tls_clienthello "$tls_low_byte" "$cipher_list_2send" "$process_full" "$4" "$offer_compression"
13121+
prepare_tls_clienthello "$tls_low_byte" "$cipher_list_2send" "$process_full" "$4" "$offer_compression" "" "$7"
1310213122
ret=$? # 6 means opening socket didn't succeed, e.g. timeout
1310313123

1310413124
# if sending didn't succeed we don't bother
@@ -15698,6 +15718,21 @@ run_grease() {
1569815718
fi
1569915719
fi
1570015720

15721+
if "$normal_hello_ok"; then
15722+
for i in 5 6 7 8 5 6 7 8; do
15723+
debugme echo -e "\nSending ClientHello with first message fragment of length $i bytes."
15724+
tls_sockets "$proto" "$cipher_list" "" "" "" "" $i
15725+
success=$?
15726+
[[ $success -eq 0 ]] || [[ $success -eq 2 ]] && break
15727+
debugme tm_svrty_low "\nConnection failed on ClientHello with first message fragment of length $i bytes."
15728+
done
15729+
if [[ $success -ne 0 ]] && [[ $success -ne 2 ]]; then
15730+
prln_svrty_low " Server fails if ClientHello sent with first message fragment less than 9 bytes."
15731+
fileout "$jsonID" "LOW" "Server fails if ClientHello sent with first message fragment less than 9 bytes."
15732+
bug_found=true
15733+
fi
15734+
fi
15735+
1570115736
# Check that server ignores unrecognized cipher suite values
1570215737
# see https://datatracker.ietf.org/doc/draft-ietf-tls-grease
1570315738
if "$normal_hello_ok"; then

0 commit comments

Comments
 (0)