From c8ff119316785f6014da4b23f566d4407caed2af Mon Sep 17 00:00:00 2001 From: David Cooper Date: Tue, 25 Oct 2016 11:04:23 -0400 Subject: [PATCH] Add option to retrieve entire server response In some cases the server's response to a ClientHello spans more than one packet. If the goal is just to determine whether the connection was successful and to extract a few pieces of information from the ServerHello message, then this is unlikely to be a problem. However, if there is a desire to extract the server's certificate chain (Certificate message) or to determine the type and size of the server's ephemeral public key (ServerKeyExchange message), then the entire response needs to be obtained, even if it spans multiple packets. This PR adds a new function, `check_tls_serverhellodone()`, that checks whether the entire response has been received (e.g., whether the ServerHelloDone message has been received). If the response indicates that the response is incomplete, then `tls_sockets()` requests more data from the server until the response is complete or until the server doesn't provide any more data in response. The PR only changes the behavior of `tls_sockets()` if the caller indicates that it wants to extract the ephemeral key or that it wants the entire response to be parsed. Otherwise, only the first packet returned by the server is sent to `parse_tls_serverhello()`. [The value of `$process_full` is not used at the moment, but will be in a subsequent PR that modifies `parse_tls_serverhello()`.] This PR also changes `tls_sockets()` to send a close_notify to the server if the connection was successfully established. --- testssl.sh | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 151 insertions(+), 4 deletions(-) diff --git a/testssl.sh b/testssl.sh index a0573f8..ec9d224 100755 --- a/testssl.sh +++ b/testssl.sh @@ -5643,10 +5643,98 @@ parse_sslv2_serverhello() { return $ret } +# Return 0 if arg1 contains the entire server response, 1 if it does not, and 2 if the response is malformed. +# Return 3 if the response version is TLS 1.3 and the entire ServerHello has been received, since any remaining +# portion of the response will be encrypted. +# arg1: ASCII-HEX encoded reply +check_tls_serverhellodone() { + local tls_hello_ascii="$1" + local tls_handshake_ascii="" tls_alert_ascii="" + local -i i tls_hello_ascii_len tls_handshake_ascii_len tls_alert_ascii_len + local -i msg_len remaining + local tls_content_type tls_protocol tls_handshake_type tls_msg_type + local tls_err_level -# arg1: name of file with socket reply + DETECTED_TLS_VERSION="" + + if [[ -z "$tls_hello_ascii" ]]; then + return 0 # no server hello received + fi + + tls_hello_ascii_len=${#tls_hello_ascii} + for (( i=0; i> "$SOCK_REPLY_FILE" + rm "$sock_reply_file3" + + check_tls_serverhellodone "$tls_hello_ascii" + hello_done=$? + [[ "$hello_done" -eq 3 ]] && process_full="ephemeralkey" + fi + done + debugme outln "reading server hello..." if [[ "$DEBUG" -ge 4 ]]; then hexdump -C $SOCK_REPLY_FILE | head -6 echo fi - parse_tls_serverhello "$SOCK_REPLY_FILE" + parse_tls_serverhello "$tls_hello_ascii" "$process_full" save=$? + if [[ $save == 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 lines=$(count_lines "$(hexdump -C "$SOCK_REPLY_FILE" 2>$ERRFILE)") debugme out " (returned $lines lines) " @@ -9338,7 +9485,7 @@ lets_roll() { determine_service "$1" # any starttls service goes here $do_tls_sockets && [[ $TLS_LOW_BYTE -eq 22 ]] && { sslv2_sockets "" "true"; echo "$?" ; exit 0; } - $do_tls_sockets && [[ $TLS_LOW_BYTE -ne 22 ]] && { tls_sockets "$TLS_LOW_BYTE" "$HEX_CIPHER"; echo "$?" ; exit 0; } + $do_tls_sockets && [[ $TLS_LOW_BYTE -ne 22 ]] && { tls_sockets "$TLS_LOW_BYTE" "$HEX_CIPHER" "all"; echo "$?" ; exit 0; } $do_test_just_one && test_just_one ${single_cipher} # all top level functions now following have the prefix "run_"