Skip to content

Commit 9e6866b

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 d6fb232 commit 9e6866b

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
@@ -10033,12 +10033,30 @@ code2network() {
1003310033
# sockets inspired by http://blog.chris007.de/?p=238
1003410034
# ARG1: hexbytes separated by commas, with a leading comma
1003510035
# ARG2: seconds to sleep
10036+
# ARG3: the size of the first message fragment to send
1003610037
socksend_clienthello() {
1003710038
local data=""
10038-
10039+
local -i i first_fragment_size=0
10040+
local first_fragment
10041+
10042+
[[ -n "$3" ]] && first_fragment_size="$3"
1003910043
code2network "$1"
1004010044
data="$NW_STR"
1004110045
[[ "$DEBUG" -ge 4 ]] && echo && echo "\"$data\""
10046+
if [[ $first_fragment_size -ne 0 ]]; then
10047+
for (( i=1; i < ${#data}; i++ )); do
10048+
[[ "${data:i:1}" == '\' ]] && first_fragment_size=$first_fragment_size-1
10049+
[[ $first_fragment_size -eq 0 ]] && break
10050+
done
10051+
first_fragment="${data:0:i}"
10052+
data="${data:i}"
10053+
if [[ -z "$PRINTF" ]] ;then
10054+
# We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower
10055+
printf -- "$first_fragment" | cat >&5 2>/dev/null &
10056+
else
10057+
$PRINTF -- "$first_fragment" 2>/dev/null >&5 2>/dev/null &
10058+
fi
10059+
fi
1004210060
if [[ -z "$PRINTF" ]] ;then
1004310061
# We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower
1004410062
printf -- "$data" | cat >&5 2>/dev/null &
@@ -12526,7 +12544,7 @@ generate_key_share_extension() {
1252612544
# ARG4: (optional) additional request extensions
1252712545
# ARG5: (optional): "true" if ClientHello should advertise compression methods other than "NULL"
1252812546
# ARG6: (optional): "false" if prepare_tls_clienthello() should not open a new socket
12529-
#
12547+
# ARG7: (optional): the size of the first message fragment to send.
1253012548
prepare_tls_clienthello() {
1253112549
local tls_low_byte="$1" tls_legacy_version="$1"
1253212550
local process_full="$3"
@@ -12547,6 +12565,7 @@ prepare_tls_clienthello() {
1254712565
local extensions_key_share="" extn_type supported_groups_c2n="" extn_psk_mode=""
1254812566
local extra_extensions extra_extensions_list="" extension_supported_versions=""
1254912567
local offer_compression=false compression_methods
12568+
local first_fragment_size="$7"
1255012569

1255112570
# TLSv1.3 ClientHello messages MUST specify only the NULL compression method.
1255212571
[[ "$5" == true ]] && [[ "0x$tls_low_byte" -le "0x03" ]] && offer_compression=true
@@ -12925,7 +12944,7 @@ prepare_tls_clienthello() {
1292512944
fi
1292612945

1292712946
debugme echo -n "sending client hello... "
12928-
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND
12947+
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND $first_fragment_size
1292912948

1293012949
if [[ "$tls_low_byte" -gt 0x03 ]]; then
1293112950
TLS_CLIENT_HELLO="$(tolower "$NW_STR")"
@@ -13143,6 +13162,7 @@ resend_if_hello_retry_request() {
1314313162
# arg4: (optional) additional request extensions
1314413163
# arg5: (optional) "true" if ClientHello should advertise compression methods other than "NULL"
1314513164
# arg6: (optional) "false" if the connection should not be closed before the function returns.
13165+
# arg7: (optional) the size of the first message fragment to send.
1314613166
# return: 0: successful connect | 1: protocol or cipher not available | 2: as (0) but downgraded
1314713167
# 6: couldn't open socket | 7: couldn't open temp file
1314813168
tls_sockets() {
@@ -13175,7 +13195,7 @@ tls_sockets() {
1317513195
cipher_list_2send="$NW_STR"
1317613196

1317713197
debugme echo -en "\nsending client hello... "
13178-
prepare_tls_clienthello "$tls_low_byte" "$cipher_list_2send" "$process_full" "$4" "$offer_compression"
13198+
prepare_tls_clienthello "$tls_low_byte" "$cipher_list_2send" "$process_full" "$4" "$offer_compression" "" "$7"
1317913199
ret=$? # 6 means opening socket didn't succeed, e.g. timeout
1318013200

1318113201
# if sending didn't succeed we don't bother
@@ -15794,6 +15814,21 @@ run_grease() {
1579415814
fi
1579515815
fi
1579615816

15817+
if "$normal_hello_ok"; then
15818+
for i in 5 6 7 8 5 6 7 8; do
15819+
debugme echo -e "\nSending ClientHello with first message fragment of length $i bytes."
15820+
tls_sockets "$proto" "$cipher_list" "" "" "" "" $i
15821+
success=$?
15822+
[[ $success -eq 0 ]] || [[ $success -eq 2 ]] && break
15823+
debugme tm_svrty_low "\nConnection failed on ClientHello with first message fragment of length $i bytes."
15824+
done
15825+
if [[ $success -ne 0 ]] && [[ $success -ne 2 ]]; then
15826+
prln_svrty_low " Server fails if ClientHello sent with first message fragment less than 9 bytes."
15827+
fileout "$jsonID" "LOW" "Server fails if ClientHello sent with first message fragment less than 9 bytes."
15828+
bug_found=true
15829+
fi
15830+
fi
15831+
1579715832
# Check that server ignores unrecognized cipher suite values
1579815833
# see https://datatracker.ietf.org/doc/draft-ietf-tls-grease
1579915834
if "$normal_hello_ok"; then

0 commit comments

Comments
 (0)