Skip to content

Commit 64292aa

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 7b2a217 commit 64292aa

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
@@ -9934,12 +9934,30 @@ code2network() {
99349934
# sockets inspired by http://blog.chris007.de/?p=238
99359935
# ARG1: hexbytes separated by commas, with a leading comma
99369936
# ARG2: seconds to sleep
9937+
# ARG3: the size of the first message fragment to send
99379938
socksend_clienthello() {
99389939
local data=""
9939-
9940+
local -i i first_fragment_size=0
9941+
local first_fragment
9942+
9943+
[[ -n "$3" ]] && first_fragment_size="$3"
99409944
code2network "$1"
99419945
data="$NW_STR"
99429946
[[ "$DEBUG" -ge 4 ]] && echo && echo "\"$data\""
9947+
if [[ $first_fragment_size -ne 0 ]]; then
9948+
for (( i=1; i < ${#data}; i++ )); do
9949+
[[ "${data:i:1}" == '\' ]] && first_fragment_size=$first_fragment_size-1
9950+
[[ $first_fragment_size -eq 0 ]] && break
9951+
done
9952+
first_fragment="${data:0:i}"
9953+
data="${data:i}"
9954+
if [[ -z "$PRINTF" ]] ;then
9955+
# We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower
9956+
printf -- "$first_fragment" | cat >&5 2>/dev/null &
9957+
else
9958+
$PRINTF -- "$first_fragment" 2>/dev/null >&5 2>/dev/null &
9959+
fi
9960+
fi
99439961
if [[ -z "$PRINTF" ]] ;then
99449962
# We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower
99459963
printf -- "$data" | cat >&5 2>/dev/null &
@@ -12426,7 +12444,7 @@ generate_key_share_extension() {
1242612444
# ARG4: (optional) additional request extensions
1242712445
# ARG5: (optional): "true" if ClientHello should advertise compression methods other than "NULL"
1242812446
# ARG6: (optional): "false" if prepare_tls_clienthello() should not open a new socket
12429-
#
12447+
# ARG7: (optional): the size of the first message fragment to send.
1243012448
prepare_tls_clienthello() {
1243112449
local tls_low_byte="$1" tls_legacy_version="$1"
1243212450
local process_full="$3"
@@ -12447,6 +12465,7 @@ prepare_tls_clienthello() {
1244712465
local extensions_key_share="" extn_type supported_groups_c2n="" extn_psk_mode=""
1244812466
local extra_extensions extra_extensions_list="" extension_supported_versions=""
1244912467
local offer_compression=false compression_methods
12468+
local first_fragment_size="$7"
1245012469

1245112470
# TLSv1.3 ClientHello messages MUST specify only the NULL compression method.
1245212471
[[ "$5" == true ]] && [[ "0x$tls_low_byte" -le "0x03" ]] && offer_compression=true
@@ -12825,7 +12844,7 @@ prepare_tls_clienthello() {
1282512844
fi
1282612845

1282712846
debugme echo -n "sending client hello... "
12828-
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND
12847+
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND $first_fragment_size
1282912848

1283012849
if [[ "$tls_low_byte" -gt 0x03 ]]; then
1283112850
TLS_CLIENT_HELLO="$(tolower "$NW_STR")"
@@ -13043,6 +13062,7 @@ resend_if_hello_retry_request() {
1304313062
# arg4: (optional) additional request extensions
1304413063
# arg5: (optional) "true" if ClientHello should advertise compression methods other than "NULL"
1304513064
# arg6: (optional) "false" if the connection should not be closed before the function returns.
13065+
# arg7: (optional) the size of the first message fragment to send.
1304613066
# return: 0: successful connect | 1: protocol or cipher not available | 2: as (0) but downgraded
1304713067
# 6: couldn't open socket | 7: couldn't open temp file
1304813068
tls_sockets() {
@@ -13075,7 +13095,7 @@ tls_sockets() {
1307513095
cipher_list_2send="$NW_STR"
1307613096

1307713097
debugme echo -en "\nsending client hello... "
13078-
prepare_tls_clienthello "$tls_low_byte" "$cipher_list_2send" "$process_full" "$4" "$offer_compression"
13098+
prepare_tls_clienthello "$tls_low_byte" "$cipher_list_2send" "$process_full" "$4" "$offer_compression" "" "$7"
1307913099
ret=$? # 6 means opening socket didn't succeed, e.g. timeout
1308013100

1308113101
# if sending didn't succeed we don't bother
@@ -15677,6 +15697,21 @@ run_grease() {
1567715697
fi
1567815698
fi
1567915699

15700+
if "$normal_hello_ok"; then
15701+
for i in 5 6 7 8 5 6 7 8; do
15702+
debugme echo -e "\nSending ClientHello with first message fragment of length $i bytes."
15703+
tls_sockets "$proto" "$cipher_list" "" "" "" "" $i
15704+
success=$?
15705+
[[ $success -eq 0 ]] || [[ $success -eq 2 ]] && break
15706+
debugme tm_svrty_low "\nConnection failed on ClientHello with first message fragment of length $i bytes."
15707+
done
15708+
if [[ $success -ne 0 ]] && [[ $success -ne 2 ]]; then
15709+
prln_svrty_low " Server fails if ClientHello sent with first message fragment less than 9 bytes."
15710+
fileout "$jsonID" "LOW" "Server fails if ClientHello sent with first message fragment less than 9 bytes."
15711+
bug_found=true
15712+
fi
15713+
fi
15714+
1568015715
# Check that server ignores unrecognized cipher suite values
1568115716
# see https://datatracker.ietf.org/doc/draft-ietf-tls-grease
1568215717
if "$normal_hello_ok"; then

0 commit comments

Comments
 (0)