Skip to content

Commit 00febbb

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 53ecacf commit 00febbb

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
@@ -10149,12 +10149,30 @@ code2network() {
1014910149
# sockets inspired by http://blog.chris007.de/?p=238
1015010150
# ARG1: hexbytes separated by commas, with a leading comma
1015110151
# ARG2: seconds to sleep
10152+
# ARG3: the size of the first message fragment to send
1015210153
socksend_clienthello() {
1015310154
local data=""
10154-
10155+
local -i i first_fragment_size=0
10156+
local first_fragment
10157+
10158+
[[ -n "$3" ]] && first_fragment_size="$3"
1015510159
code2network "$1"
1015610160
data="$NW_STR"
1015710161
[[ "$DEBUG" -ge 4 ]] && echo && echo "\"$data\""
10162+
if [[ $first_fragment_size -ne 0 ]]; then
10163+
for (( i=1; i < ${#data}; i++ )); do
10164+
[[ "${data:i:1}" == '\' ]] && first_fragment_size=$first_fragment_size-1
10165+
[[ $first_fragment_size -eq 0 ]] && break
10166+
done
10167+
first_fragment="${data:0:i}"
10168+
data="${data:i}"
10169+
if [[ -z "$PRINTF" ]] ;then
10170+
# We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower
10171+
printf -- "$first_fragment" | cat >&5 2>/dev/null &
10172+
else
10173+
$PRINTF -- "$first_fragment" 2>/dev/null >&5 2>/dev/null &
10174+
fi
10175+
fi
1015810176
if [[ -z "$PRINTF" ]] ;then
1015910177
# We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower
1016010178
printf -- "$data" | cat >&5 2>/dev/null &
@@ -12673,7 +12691,7 @@ generate_key_share_extension() {
1267312691
# ARG4: (optional) additional request extensions
1267412692
# ARG5: (optional): "true" if ClientHello should advertise compression methods other than "NULL"
1267512693
# ARG6: (optional): "false" if prepare_tls_clienthello() should not open a new socket
12676-
#
12694+
# ARG7: (optional): the size of the first message fragment to send.
1267712695
prepare_tls_clienthello() {
1267812696
local tls_low_byte="$1" tls_legacy_version="$1"
1267912697
local process_full="$3"
@@ -12694,6 +12712,7 @@ prepare_tls_clienthello() {
1269412712
local extensions_key_share="" extn_type supported_groups_c2n="" extn_psk_mode=""
1269512713
local extra_extensions extra_extensions_list="" extension_supported_versions=""
1269612714
local offer_compression=false compression_methods
12715+
local first_fragment_size="$7"
1269712716

1269812717
# TLSv1.3 ClientHello messages MUST specify only the NULL compression method.
1269912718
[[ "$5" == true ]] && [[ "0x$tls_low_byte" -le "0x03" ]] && offer_compression=true
@@ -13072,7 +13091,7 @@ prepare_tls_clienthello() {
1307213091
fi
1307313092

1307413093
debugme echo -n "sending client hello... "
13075-
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND
13094+
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND $first_fragment_size
1307613095

1307713096
if [[ "$tls_low_byte" -gt 0x03 ]]; then
1307813097
TLS_CLIENT_HELLO="$(tolower "$NW_STR")"
@@ -13290,6 +13309,7 @@ resend_if_hello_retry_request() {
1329013309
# arg4: (optional) additional request extensions
1329113310
# arg5: (optional) "true" if ClientHello should advertise compression methods other than "NULL"
1329213311
# arg6: (optional) "false" if the connection should not be closed before the function returns.
13312+
# arg7: (optional) the size of the first message fragment to send.
1329313313
# return: 0: successful connect | 1: protocol or cipher not available | 2: as (0) but downgraded
1329413314
# 6: couldn't open socket | 7: couldn't open temp file
1329513315
tls_sockets() {
@@ -13322,7 +13342,7 @@ tls_sockets() {
1332213342
cipher_list_2send="$NW_STR"
1332313343

1332413344
debugme echo -en "\nsending client hello... "
13325-
prepare_tls_clienthello "$tls_low_byte" "$cipher_list_2send" "$process_full" "$4" "$offer_compression"
13345+
prepare_tls_clienthello "$tls_low_byte" "$cipher_list_2send" "$process_full" "$4" "$offer_compression" "" "$7"
1332613346
ret=$? # 6 means opening socket didn't succeed, e.g. timeout
1332713347

1332813348
# if sending didn't succeed we don't bother
@@ -15941,6 +15961,21 @@ run_grease() {
1594115961
fi
1594215962
fi
1594315963

15964+
if "$normal_hello_ok"; then
15965+
for i in 5 6 7 8 5 6 7 8; do
15966+
debugme echo -e "\nSending ClientHello with first message fragment of length $i bytes."
15967+
tls_sockets "$proto" "$cipher_list" "" "" "" "" $i
15968+
success=$?
15969+
[[ $success -eq 0 ]] || [[ $success -eq 2 ]] && break
15970+
debugme tm_svrty_low "\nConnection failed on ClientHello with first message fragment of length $i bytes."
15971+
done
15972+
if [[ $success -ne 0 ]] && [[ $success -ne 2 ]]; then
15973+
prln_svrty_low " Server fails if ClientHello sent with first message fragment less than 9 bytes."
15974+
fileout "$jsonID" "LOW" "Server fails if ClientHello sent with first message fragment less than 9 bytes."
15975+
bug_found=true
15976+
fi
15977+
fi
15978+
1594415979
# Check that server ignores unrecognized cipher suite values
1594515980
# see https://datatracker.ietf.org/doc/draft-ietf-tls-grease
1594615981
if "$normal_hello_ok"; then

0 commit comments

Comments
 (0)