Skip to content

Commit 75b78bc

Browse files
author
David Cooper
authored
Sort TLS extensions
This commit modifies testssl.sh so that run_server_defaults() prints the server's supported TLS extensions sorted by extension number rather than listing them in the order in which they were found. In order to simplify the sorting of the extensions, this commit changes $TLS_EXTENSIONS from a string to an array. In February 2017 comments were added (925e106) saying that it would be $TLS_EXTENSIONS were an array. So, this commit addresses those comments. However, it is possible that the reason for those comments no longer apply.
1 parent f34b81e commit 75b78bc

1 file changed

Lines changed: 37 additions & 22 deletions

File tree

testssl.sh

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ KNOWN_OSSL_PROB=false # We need OpenSSL a few times. This vari
277277
DETECTED_TLS_VERSION="" # .. as hex string, e.g. 0300 or 0303
278278
APP_TRAF_KEY_INFO="" # Information about the application traffic keys for a TLS 1.3 connection.
279279
TLS13_ONLY=false # Does the server support TLS 1.3 ONLY?
280-
TLS_EXTENSIONS=""
280+
declare -a TLS_EXTENSIONS=()
281281
TLS13_CERT_COMPRESS_METHODS=""
282282
CERTIFICATE_TRANSPARENCY_SOURCE=""
283283
V2_HELLO_CIPHERSPEC_LENGTH=0
@@ -7884,6 +7884,7 @@ sclient_connect_successful() {
78847884

78857885
extract_new_tls_extensions() {
78867886
local tls_extensions
7887+
local -i i
78877888

78887889
# this is not beautiful (grep+sed)
78897890
# but maybe we should just get the ids and do a private matching, according to
@@ -7897,12 +7898,15 @@ extract_new_tls_extensions() {
78977898
if [[ -n "$tls_extensions" ]]; then
78987899
# check to see if any new TLS extensions were returned and add any new ones to TLS_EXTENSIONS
78997900
while read -d "\"" -r line; do
7900-
if [[ $line != "" ]] && [[ ! "$TLS_EXTENSIONS" =~ "$line" ]]; then
7901-
#FIXME: This is a string of quoted strings, so this seems to determine the output format already. Better e.g. would be an array
7902-
TLS_EXTENSIONS+=" \"${line}\""
7901+
if [[ $line != "" ]] && [[ ! "${TLS_EXTENSIONS[*]}" =~ "$line" ]]; then
7902+
i=${#TLS_EXTENSIONS[*]}
7903+
while [[ $i -gt 0 ]] && [[ ${TLS_EXTENSIONS[i-1]#*/#} -gt ${line#*/#} ]]; do
7904+
TLS_EXTENSIONS[i]="${TLS_EXTENSIONS[i-1]}"
7905+
i=$((i-1))
7906+
done
7907+
TLS_EXTENSIONS[i]="$line"
79037908
fi
79047909
done <<<$tls_extensions
7905-
[[ "${TLS_EXTENSIONS:0:1}" == " " ]] && TLS_EXTENSIONS="${TLS_EXTENSIONS:1}"
79067910
fi
79077911
}
79087912

@@ -7918,7 +7922,7 @@ extract_new_tls_extensions() {
79187922
determine_tls_extensions() {
79197923
local addcmd
79207924
local -i success=1
7921-
local line params="" tls_extensions=""
7925+
local line params="" tls_extensions="" extn
79227926
local alpn_proto alpn="" alpn_list_len_hex alpn_extn_len_hex
79237927
local -i alpn_list_len alpn_extn_len
79247928
local cbc_cipher_list="ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DH-RSA-AES256-SHA256:DH-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DH-RSA-AES256-SHA:DH-DSS-AES256-SHA:ECDHE-RSA-CAMELLIA256-SHA384:ECDHE-ECDSA-CAMELLIA256-SHA384:DHE-RSA-CAMELLIA256-SHA256:DHE-DSS-CAMELLIA256-SHA256:DH-RSA-CAMELLIA256-SHA256:DH-DSS-CAMELLIA256-SHA256:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:DH-RSA-CAMELLIA256-SHA:DH-DSS-CAMELLIA256-SHA:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:ECDH-RSA-CAMELLIA256-SHA384:ECDH-ECDSA-CAMELLIA256-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA256:CAMELLIA256-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DH-RSA-AES128-SHA256:DH-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:DH-RSA-AES128-SHA:DH-DSS-AES128-SHA:ECDHE-RSA-CAMELLIA128-SHA256:ECDHE-ECDSA-CAMELLIA128-SHA256:DHE-RSA-CAMELLIA128-SHA256:DHE-DSS-CAMELLIA128-SHA256:DH-RSA-CAMELLIA128-SHA256:DH-DSS-CAMELLIA128-SHA256:DHE-RSA-SEED-SHA:DHE-DSS-SEED-SHA:DH-RSA-SEED-SHA:DH-DSS-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:DH-RSA-CAMELLIA128-SHA:DH-DSS-CAMELLIA128-SHA:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:ECDH-RSA-CAMELLIA128-SHA256:ECDH-ECDSA-CAMELLIA128-SHA256:AES128-SHA256:AES128-SHA:CAMELLIA128-SHA256:SEED-SHA:CAMELLIA128-SHA:IDEA-CBC-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DH-RSA-DES-CBC3-SHA:DH-DSS-DES-CBC3-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:DES-CBC3-SHA:EXP1024-DHE-DSS-DES-CBC-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DH-RSA-DES-CBC-SHA:DH-DSS-DES-CBC-SHA:EXP1024-DES-CBC-SHA:DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-DH-DSS-DES-CBC-SHA:EXP-DH-RSA-DES-CBC-SHA"
@@ -7940,7 +7944,7 @@ determine_tls_extensions() {
79407944
alpn_extn_len_hex=$(printf "%04x" $alpn_extn_len)
79417945
tls_extensions+=", 00,10,${alpn_extn_len_hex:0:2},${alpn_extn_len_hex:2:2},${alpn_list_len_hex:0:2},${alpn_list_len_hex:2:2}$alpn"
79427946
fi
7943-
if [[ ! "$TLS_EXTENSIONS" =~ encrypt-then-mac ]]; then
7947+
if [[ ! "${TLS_EXTENSIONS[*]}" =~ encrypt-then-mac ]]; then
79447948
tls_sockets "03" "$cbc_cipher_list_hex, 00,ff" "all" "$tls_extensions"
79457949
success=$?
79467950
fi
@@ -7965,7 +7969,7 @@ determine_tls_extensions() {
79657969
else
79667970
addcmd="$SNI"
79677971
fi
7968-
if [[ ! "$TLS_EXTENSIONS" =~ encrypt-then-mac ]]; then
7972+
if [[ ! "${TLS_EXTENSIONS[*]}" =~ encrypt-then-mac ]]; then
79697973
$OPENSSL s_client $(s_client_options "$STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $addcmd $OPTIMAL_PROTO -tlsextdebug $params -cipher $cbc_cipher_list") </dev/null 2>$ERRFILE >$TMPFILE
79707974
sclient_connect_successful $? $TMPFILE
79717975
success=$?
@@ -7980,7 +7984,13 @@ determine_tls_extensions() {
79807984
fi
79817985

79827986
# Keep it "on file" for debugging purposes
7983-
[[ "$DEBUG" -ge 1 ]] && safe_echo "$TLS_EXTENSIONS" >"$TEMPDIR/$NODE.$NODEIP.tls_extensions.txt"
7987+
if [[ "$DEBUG" -ge 1 ]]; then
7988+
tls_extensions=""
7989+
for extn in "${TLS_EXTENSIONS[@]}"; do
7990+
tls_extensions+=" \"${extn}\""
7991+
done
7992+
safe_echo "${tls_extensions:1}" >"$TEMPDIR/$NODE.$NODEIP.tls_extensions.txt"
7993+
fi
79847994

79857995
return $success
79867996
}
@@ -8865,7 +8875,7 @@ certificate_transparency() {
88658875
# determine_tls_extensions() discovered an SCT TLS extension. If the server has more than
88668876
# one certificate, then it is possible that an SCT TLS extension is returned for some
88678877
# certificates, but not for all of them.
8868-
if [[ $number_of_certificates -eq 1 ]] && [[ "$TLS_EXTENSIONS" =~ signed\ certificate\ timestamps ]]; then
8878+
if [[ $number_of_certificates -eq 1 ]] && [[ "${TLS_EXTENSIONS[*]}" =~ signed\ certificate\ timestamps ]]; then
88698879
CERTIFICATE_TRANSPARENCY_SOURCE="TLS extension"
88708880
return 0
88718881
fi
@@ -10076,7 +10086,7 @@ run_server_defaults() {
1007610086
local -a ocsp_response_binary ocsp_response ocsp_response_status sni_used tls_version ct
1007710087
local -a ciphers_to_test certificate_type
1007810088
local -a -i success
10079-
local cn_nosni cn_sni sans_nosni sans_sni san tls_extensions client_auth_ca
10089+
local cn_nosni cn_sni sans_nosni sans_sni san tls_extensions extn client_auth_ca
1008010090
local using_sockets=true
1008110091

1008210092
"$SSL_NATIVE" && using_sockets=false
@@ -10328,7 +10338,7 @@ run_server_defaults() {
1032810338
outln
1032910339

1033010340
pr_bold " TLS extensions (standard) "
10331-
if [[ -z "$TLS_EXTENSIONS" ]]; then
10341+
if [[ ${#TLS_EXTENSIONS[*]} -eq 0 ]]; then
1033210342
outln "(none)"
1033310343
fileout "TLS_extensions" "INFO" "(none)"
1033410344
else
@@ -10339,12 +10349,17 @@ run_server_defaults() {
1033910349
# across lines, temporarily replace space characters within the text
1034010350
# of an extension with "}", and then convert the "}" back to space in
1034110351
# the output of out_row_aligned_max_width().
10342-
tls_extensions="${TLS_EXTENSIONS// /{}"
10352+
tls_extensions=""
10353+
for extn in "${TLS_EXTENSIONS[@]}"; do
10354+
tls_extensions+=" \"${extn}\""
10355+
done
10356+
tls_extensions="${tls_extensions:1}"
10357+
fileout "TLS_extensions" "INFO" "$tls_extensions"
10358+
tls_extensions="${tls_extensions// /{}"
1034310359
tls_extensions="${tls_extensions//\"{\"/\" \"}"
1034410360
tls_extensions="$(out_row_aligned_max_width "$tls_extensions" " " $TERM_WIDTH)"
1034510361
tls_extensions="${tls_extensions//{/ }"
1034610362
outln "$tls_extensions"
10347-
fileout "TLS_extensions" "INFO" "$TLS_EXTENSIONS"
1034810363
fi
1034910364

1035010365
pr_bold " Session Ticket RFC 5077 hint "
@@ -16712,8 +16727,8 @@ run_heartbleed(){
1671216727
return 1
1671316728
fi
1671416729

16715-
[[ -z "$TLS_EXTENSIONS" ]] && determine_tls_extensions
16716-
if [[ ! "${TLS_EXTENSIONS}" =~ heartbeat ]]; then
16730+
[[ ${#TLS_EXTENSIONS[*]} -eq 0 ]] && determine_tls_extensions
16731+
if [[ ! "${TLS_EXTENSIONS[*]}" =~ heartbeat ]]; then
1671716732
pr_svrty_best "not vulnerable (OK)"
1671816733
outln ", no heartbeat extension"
1671916734
fileout "$jsonID" "OK" "not vulnerable, no heartbeat extension" "$cve" "$cwe"
@@ -17017,8 +17032,8 @@ run_ticketbleed() {
1701717032
fi
1701817033

1701917034
# highly unlikely that it is NOT supported. We may loose time here but it's more solid
17020-
[[ -z "$TLS_EXTENSIONS" ]] && determine_tls_extensions
17021-
if [[ ! "${TLS_EXTENSIONS}" =~ "session ticket" ]]; then
17035+
[[ ${#TLS_EXTENSIONS[*]} -eq 0 ]] && determine_tls_extensions
17036+
if [[ ! "${TLS_EXTENSIONS[*]}" =~ "session ticket" ]]; then
1702217037
pr_svrty_best "not vulnerable (OK)"
1702317038
outln ", no session ticket extension"
1702417039
fileout "$jsonID" "OK" "no session ticket extension" "$cve" "$cwe"
@@ -19120,7 +19135,7 @@ run_winshock() {
1912019135
# (~ sub_check_curves) which is some work. But also for the sake of clean code this needs to be done.
1912119136

1912219137

19123-
[[ -z "$TLS_EXTENSIONS" ]] && determine_tls_extensions
19138+
[[ ${#TLS_EXTENSIONS[*]} -eq 0 ]] && determine_tls_extensions
1912419139
# Basis of the following https://en.wikipedia.org/wiki/Comparison_of_TLS_implementations#Extensions
1912519140
# Our standard: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
1912619141

@@ -19134,9 +19149,9 @@ run_winshock() {
1913419149
local -a forbidden_tls_ext=("encrypt-then-mac" "max fragment length")
1913519150
# Open whether ec_point_formats, supported_groups(=elliptic_curves), heartbeat are supported under windows <=2012
1913619151
# key_share and supported_versions are extensions which came with TLS 1.3. We checked the protocol before.
19137-
if [[ -n "$TLS_EXTENSIONS" ]]; then
19152+
if [[ ${#TLS_EXTENSIONS[*]} -gt 0 ]]; then
1913819153
# Check whether there are any TLS extension which should not be available under <= Windows 2012 R2
19139-
for tls_ext in $TLS_EXTENSIONS; do
19154+
for tls_ext in "${TLS_EXTENSIONS[@]}"; do
1914019155
# We use the whole array, got to be careful when the array becomes bigger (unintended match)
1914119156
if [[ ${forbidden_tls_ext[@]} =~ $tls_ext ]]; then
1914219157
pr_svrty_best "not vulnerable (OK)"; outln " - TLS extension $tls_ext detected"
@@ -24378,7 +24393,7 @@ reset_hostdepended_vars() {
2437824393
NR_OSSL_FAIL=0
2437924394
NR_STARTTLS_FAIL=0
2438024395
NR_HEADER_FAIL=0
24381-
TLS_EXTENSIONS=""
24396+
TLS_EXTENSIONS=()
2438224397
TLS13_CERT_COMPRESS_METHODS=""
2438324398
CERTIFICATE_TRANSPARENCY_SOURCE=""
2438424399
PROTOS_OFFERED=""

0 commit comments

Comments
 (0)