Skip to content

Commit

Permalink
ClientHello with small first TCP fragment
Browse files Browse the repository at this point in the history
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 drwetter#1113 would have reported a problem.
  • Loading branch information
dcooper16 committed Nov 27, 2024
1 parent 701c606 commit 7778bed
Showing 1 changed file with 38 additions and 3 deletions.
41 changes: 38 additions & 3 deletions testssl.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11872,12 +11872,30 @@ code2network() {
# sockets inspired by https://blog.chris007.de/using-bash-for-network-socket-operation/
# ARG1: hexbytes separated by commas, with a leading comma
# ARG2: seconds to sleep
# ARG3: the size of the first message fragment to send
socksend_clienthello() {
local data=""
local -i i first_fragment_size=0
local first_fragment

[[ -n "$3" ]] && first_fragment_size="$3"
code2network "$1"
data="$NW_STR"
[[ "$DEBUG" -ge 4 ]] && echo && echo "\"$data\""
if [[ $first_fragment_size -ne 0 ]]; then
for (( i=1; i < ${#data}; i++ )); do
[[ "${data:i:1}" == '\' ]] && first_fragment_size=$first_fragment_size-1
[[ $first_fragment_size -eq 0 ]] && break
done
first_fragment="${data:0:i}"
data="${data:i}"
if [[ -z "$PRINTF" ]] ;then
# We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower
printf -- "$first_fragment" | cat >&5 2>/dev/null &
else
$PRINTF -- "$first_fragment" 2>/dev/null >&5 2>/dev/null &
fi
fi
if [[ -z "$PRINTF" ]] ;then
# We could also use "dd ibs=1M obs=1M" here but is seems to be at max 3% slower
printf -- "$data" | cat >&5 2>/dev/null &
Expand Down Expand Up @@ -15482,7 +15500,7 @@ generate_key_share_extension() {
# ARG4: (optional) additional request extensions
# ARG5: (optional): "true" if ClientHello should advertise compression methods other than "NULL"
# ARG6: (optional): "false" if prepare_tls_clienthello() should not open a new socket
#
# ARG7: (optional): the size of the first message fragment to send.
prepare_tls_clienthello() {
local tls_low_byte="$1" tls_legacy_version="$1"
local process_full="$3"
Expand All @@ -15504,6 +15522,7 @@ prepare_tls_clienthello() {
local extra_extensions extra_extensions_list="" extension_supported_versions=""
local offer_compression=false compression_methods
local padding_bytes="\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"
local first_fragment_size="$7"

# TLSv1.3 ClientHello messages MUST specify only the NULL compression method.
[[ "$5" == true ]] && [[ "0x$tls_low_byte" -le "0x03" ]] && offer_compression=true
Expand Down Expand Up @@ -15897,7 +15916,7 @@ prepare_tls_clienthello() {
fi

debugme echo -n "sending client hello... "
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND
socksend_clienthello "$TLS_CLIENT_HELLO$all_extensions" $USLEEP_SND $first_fragment_size

if [[ "$tls_low_byte" -gt 0x03 ]]; then
TLS_CLIENT_HELLO="$(tolower "$NW_STR")"
Expand Down Expand Up @@ -16116,6 +16135,7 @@ resend_if_hello_retry_request() {
# arg4: (optional) additional request extensions
# arg5: (optional) "true" if ClientHello should advertise compression methods other than "NULL"
# arg6: (optional) "false" if the connection should not be closed before the function returns.
# arg7: (optional) the size of the first message fragment to send.
# return: 0: successful connect | 1: protocol or cipher not available | 2: as (0) but downgraded
# 6: couldn't open socket | 7: couldn't open temp file
tls_sockets() {
Expand Down Expand Up @@ -16155,7 +16175,7 @@ tls_sockets() {
cipher_list_2send="$NW_STR"

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

# if sending didn't succeed we don't bother
Expand Down Expand Up @@ -19686,6 +19706,21 @@ run_grease() {
fi
fi

if "$normal_hello_ok"; then
for i in 5 6 7 8 5 6 7 8; do
debugme echo -e "\nSending ClientHello with first message fragment of length $i bytes."
tls_sockets "$proto" "$cipher_list" "" "" "" "" $i
success=$?
[[ $success -eq 0 ]] || [[ $success -eq 2 ]] && break
debugme tm_svrty_low "\nConnection failed on ClientHello with first message fragment of length $i bytes."
done
if [[ $success -ne 0 ]] && [[ $success -ne 2 ]]; then
prln_svrty_low " Server fails if ClientHello sent with first message fragment less than 9 bytes."
fileout "$jsonID" "LOW" "Server fails if ClientHello sent with first message fragment less than 9 bytes."
bug_found=true
fi
fi

# Check that server ignores unrecognized cipher suite values
# see RFC 8701
if "$normal_hello_ok"; then
Expand Down

0 comments on commit 7778bed

Please sign in to comment.