Use ephemeral public key in client simulations
This PR makes similar changes to `run_client_simulation()` as were made to `tls_sockets()`, so that `run_client_simulation()` retrieves the entire server response, even if it is split across multiple packets, and it has `parse_tls_serverhello()` extract information about the server's ephemeral public key, if present. The PR also changes `run_client_simulation()` to use information about the ephemeral public key. It includes the length of the public key in the output and, if it is a DH public key, checks that the size is within the acceptable range (`${minDhBits[i]} <= dh_bits <= ${maxDhBits[i]}`).
This commit is contained in:
parent
e8d7e16a9d
commit
765b1bdf5d
71
testssl.sh
71
testssl.sh
|
@ -2348,7 +2348,8 @@ client_simulation_sockets() {
|
||||||
local -i save=0
|
local -i save=0
|
||||||
local lines clienthello data=""
|
local lines clienthello data=""
|
||||||
local cipher_list_2send
|
local cipher_list_2send
|
||||||
local tls_hello_ascii
|
local sock_reply_file2 sock_reply_file3
|
||||||
|
local tls_hello_ascii next_packet hello_done=0
|
||||||
|
|
||||||
if [[ "${1:0:4}" == "1603" ]]; then
|
if [[ "${1:0:4}" == "1603" ]]; then
|
||||||
clienthello="$(create_client_simulation_tls_clienthello "$1")"
|
clienthello="$(create_client_simulation_tls_clienthello "$1")"
|
||||||
|
@ -2357,7 +2358,7 @@ client_simulation_sockets() {
|
||||||
fi
|
fi
|
||||||
len=${#clienthello}
|
len=${#clienthello}
|
||||||
for (( i=0; i < len; i=i+2 )); do
|
for (( i=0; i < len; i=i+2 )); do
|
||||||
data+=", ${clienthello:i:2}"
|
data+=", ${clienthello:i:2}"
|
||||||
done
|
done
|
||||||
debugme echo "sending client hello..."
|
debugme echo "sending client hello..."
|
||||||
code2network "${data}"
|
code2network "${data}"
|
||||||
|
@ -2373,15 +2374,58 @@ client_simulation_sockets() {
|
||||||
tls_hello_ascii=$(hexdump -v -e '16/1 "%02X"' "$SOCK_REPLY_FILE")
|
tls_hello_ascii=$(hexdump -v -e '16/1 "%02X"' "$SOCK_REPLY_FILE")
|
||||||
tls_hello_ascii="${tls_hello_ascii%%[!0-9A-F]*}"
|
tls_hello_ascii="${tls_hello_ascii%%[!0-9A-F]*}"
|
||||||
|
|
||||||
|
check_tls_serverhellodone "$tls_hello_ascii"
|
||||||
|
hello_done=$?
|
||||||
|
|
||||||
|
for(( 1 ; hello_done==1; 1 )); do
|
||||||
|
sock_reply_file2=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7
|
||||||
|
mv "$SOCK_REPLY_FILE" "$sock_reply_file2"
|
||||||
|
|
||||||
|
debugme echo "requesting more server hello data..."
|
||||||
|
socksend "" $USLEEP_SND
|
||||||
|
sockread_serverhello 32768
|
||||||
|
|
||||||
|
next_packet=$(hexdump -v -e '16/1 "%02X"' "$SOCK_REPLY_FILE")
|
||||||
|
next_packet="${next_packet%%[!0-9A-F]*}"
|
||||||
|
if [[ ${#next_packet} -eq 0 ]]; then
|
||||||
|
# This shouldn't be necessary. However, it protects against
|
||||||
|
# getting into an infinite loop if the server has nothing
|
||||||
|
# left to send and check_tls_serverhellodone doesn't
|
||||||
|
# correctly catch it.
|
||||||
|
mv "$sock_reply_file2" "$SOCK_REPLY_FILE"
|
||||||
|
hello_done=0
|
||||||
|
else
|
||||||
|
tls_hello_ascii+="$next_packet"
|
||||||
|
|
||||||
|
sock_reply_file3=$(mktemp $TEMPDIR/ddreply.XXXXXX) || return 7
|
||||||
|
mv "$SOCK_REPLY_FILE" "$sock_reply_file3"
|
||||||
|
mv "$sock_reply_file2" "$SOCK_REPLY_FILE"
|
||||||
|
cat "$sock_reply_file3" >> "$SOCK_REPLY_FILE"
|
||||||
|
rm "$sock_reply_file3"
|
||||||
|
|
||||||
|
check_tls_serverhellodone "$tls_hello_ascii"
|
||||||
|
hello_done=$?
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
debugme outln "reading server hello..."
|
debugme outln "reading server hello..."
|
||||||
if [[ "$DEBUG" -ge 4 ]]; then
|
if [[ "$DEBUG" -ge 4 ]]; then
|
||||||
hexdump -C $SOCK_REPLY_FILE | head -6
|
hexdump -C $SOCK_REPLY_FILE | head -6
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
|
||||||
parse_tls_serverhello "$tls_hello_ascii"
|
parse_tls_serverhello "$tls_hello_ascii" "ephemeralkey"
|
||||||
save=$?
|
save=$?
|
||||||
|
|
||||||
|
if [[ $save -eq 0 ]]; then
|
||||||
|
debugme echo "sending close_notify..."
|
||||||
|
if [[ "$DETECTED_TLS_VERSION" == "0300" ]]; then
|
||||||
|
socksend ",x15, x03, x00, x00, x02, x02, x00" 0
|
||||||
|
else
|
||||||
|
socksend ",x15, x03, x01, x00, x02, x02, x00" 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# see https://secure.wand.net.nz/trac/libprotoident/wiki/SSL
|
# see https://secure.wand.net.nz/trac/libprotoident/wiki/SSL
|
||||||
lines=$(count_lines "$(hexdump -C "$SOCK_REPLY_FILE" 2>$ERRFILE)")
|
lines=$(count_lines "$(hexdump -C "$SOCK_REPLY_FILE" 2>$ERRFILE)")
|
||||||
debugme out " (returned $lines lines) "
|
debugme out " (returned $lines lines) "
|
||||||
|
@ -2421,7 +2465,7 @@ run_client_simulation() {
|
||||||
local minEcdsaBits=()
|
local minEcdsaBits=()
|
||||||
local requiresSha2=()
|
local requiresSha2=()
|
||||||
local i=0
|
local i=0
|
||||||
local name tls proto cipher
|
local name tls proto cipher temp what_dh bits has_dh_bits
|
||||||
local using_sockets=true
|
local using_sockets=true
|
||||||
|
|
||||||
if "$SSL_NATIVE" || [[ -n "$STARTTLS" ]]; then
|
if "$SSL_NATIVE" || [[ -n "$STARTTLS" ]]; then
|
||||||
|
@ -3183,6 +3227,18 @@ run_client_simulation() {
|
||||||
sclient_connect_successful $? $TMPFILE
|
sclient_connect_successful $? $TMPFILE
|
||||||
sclient_success=$?
|
sclient_success=$?
|
||||||
fi
|
fi
|
||||||
|
if [[ $sclient_success -eq 0 ]]; then
|
||||||
|
# If an ephemeral DH key was used, check that the number of bits is within range.
|
||||||
|
temp=$(awk -F': ' '/^Server Temp Key/ { print $2 }' "$TMPFILE") # extract line
|
||||||
|
what_dh=$(awk -F',' '{ print $1 }' <<< $temp)
|
||||||
|
bits=$(awk -F',' '{ print $3 }' <<< $temp)
|
||||||
|
grep -q bits <<< $bits || bits=$(awk -F',' '{ print $2 }' <<< $temp)
|
||||||
|
bits=$(tr -d ' bits' <<< $bits)
|
||||||
|
if [[ "$what_dh" == "DH" ]]; then
|
||||||
|
[[ ${minDhBits[i]} -ne -1 ]] && [[ $bits -lt ${minDhBits[i]} ]] && sclient_success=1
|
||||||
|
[[ ${maxDhBits[i]} -ne -1 ]] && [[ $bits -gt ${maxDhBits[i]} ]] && sclient_success=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if [[ $sclient_success -ne 0 ]]; then
|
if [[ $sclient_success -ne 0 ]]; then
|
||||||
outln "No connection"
|
outln "No connection"
|
||||||
fileout "client_${short[i]}" "INFO" "$(strip_spaces "${names[i]}") client simulation: No connection"
|
fileout "client_${short[i]}" "INFO" "$(strip_spaces "${names[i]}") client simulation: No connection"
|
||||||
|
@ -3217,7 +3273,12 @@ run_client_simulation() {
|
||||||
#FiXME: awk
|
#FiXME: awk
|
||||||
cipher=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/ //g' -e 's/^Cipher://')
|
cipher=$(grep -wa Cipher $TMPFILE | egrep -avw "New|is" | sed -e 's/ //g' -e 's/^Cipher://')
|
||||||
"$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && cipher="$(rfc2openssl "$cipher")"
|
"$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && cipher="$(rfc2openssl "$cipher")"
|
||||||
outln "$proto $cipher"
|
out "$proto $cipher"
|
||||||
|
"$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && has_dh_bits=$HAS_DH_BITS && HAS_DH_BITS=true
|
||||||
|
"$HAS_DH_BITS" && read_dhbits_from_file $TMPFILE
|
||||||
|
"$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && HAS_DH_BITS=$has_dh_bits
|
||||||
|
[[ ":${ROBUST_PFS_CIPHERS}:" =~ ":${cipher}:" ]] && out ", " && pr_done_good "FS"
|
||||||
|
outln
|
||||||
if [[ -n "${warning[i]}" ]]; then
|
if [[ -n "${warning[i]}" ]]; then
|
||||||
out " "
|
out " "
|
||||||
outln "${warning[i]}"
|
outln "${warning[i]}"
|
||||||
|
|
Loading…
Reference in New Issue