Skip to content

Commit 51c99b2

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 4b05e39 commit 51c99b2

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 &
@@ -12450,7 +12468,7 @@ generate_key_share_extension() {
1245012468
# ARG4: (optional) additional request extensions
1245112469
# ARG5: (optional): "true" if ClientHello should advertise compression methods other than "NULL"
1245212470
# ARG6: (optional): "false" if prepare_tls_clienthello() should not open a new socket
12453-
#
12471+
# ARG7: (optional): the size of the first message fragment to send.
1245412472
prepare_tls_clienthello() {
1245512473
local tls_low_byte="$1" tls_legacy_version="$1"
1245612474
local process_full="$3"
@@ -12471,6 +12489,7 @@ prepare_tls_clienthello() {
1247112489
local extensions_key_share="" extn_type supported_groups_c2n="" extn_psk_mode=""
1247212490
local extra_extensions extra_extensions_list="" extension_supported_versions=""
1247312491
local offer_compression=false compression_methods
12492+
local first_fragment_size="$7"
1247412493

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

1285112870
debugme echo -n "sending client hello... "
12852-
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND
12871+
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND $first_fragment_size
1285312872

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

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

1310513125
# if sending didn't succeed we don't bother
@@ -15699,6 +15719,21 @@ run_grease() {
1569915719
fi
1570015720
fi
1570115721

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

0 commit comments

Comments
 (0)