mirror of
https://github.com/drwetter/testssl.sh.git
synced 2025-01-03 23:39:45 +01:00
Certificate Transparency
This commit implements a check for Certificate Transparency support, as proposed in #771.
This commit is contained in:
parent
a81b99fd04
commit
3e179ad30d
108
testssl.sh
108
testssl.sh
@ -5348,6 +5348,12 @@ get_server_certificate() {
|
||||
GOST_STATUS_PROBLEM=true
|
||||
fi
|
||||
fi
|
||||
case "$proto" in
|
||||
"tls1_2") DETECTED_TLS_VERSION="0303" ;;
|
||||
"tls1_1") DETECTED_TLS_VERSION="0302" ;;
|
||||
"tls1") DETECTED_TLS_VERSION="0301" ;;
|
||||
"ssl3") DETECTED_TLS_VERSION="0300" ;;
|
||||
esac
|
||||
extract_new_tls_extensions $TMPFILE
|
||||
|
||||
# Place the server's certificate in $HOSTCERT and any intermediate
|
||||
@ -5563,6 +5569,69 @@ must_staple() {
|
||||
fi
|
||||
}
|
||||
|
||||
# TODO: This function checks for Certificate Transparency support based on RFC 6962.
|
||||
# It will need to be updated to add checks for Certificate Transparency support based on 6962bis.
|
||||
certificate_transparency() {
|
||||
local cert="$1"
|
||||
local ocsp_response="$2"
|
||||
local -i number_of_certificates=$3
|
||||
local cipher="$4"
|
||||
local sni_used="$5"
|
||||
local tls_version="$6"
|
||||
local sni=""
|
||||
local ciphers=""
|
||||
local hexc n ciph sslver kx auth enc mac export
|
||||
local -i success
|
||||
|
||||
# First check whether signed certificate timestamps (SCT) are included in the
|
||||
# server's certificate. If they aren't, check whether the server provided
|
||||
# a stapled OCSP response with SCTs. If no SCTs were found in the certificate
|
||||
# or OCSP response, check for an SCT TLS extension.
|
||||
if $OPENSSL x509 -noout -text 2>>$ERRFILE <<< "$cert" | egrep -q "CT Precertificate SCTs|1.3.6.1.4.1.11129.2.4.2" ; then
|
||||
tm_out "certificate extension"
|
||||
return 0
|
||||
fi
|
||||
if egrep -q "CT Certificate SCTs|1.3.6.1.4.1.11129.2.4.5" <<< "$ocsp_response"; then
|
||||
tm_out "OCSP extension"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If the server only has one certificate, then it is sufficient to check whether
|
||||
# determine_tls_extensions() discovered an SCT TLS extension. If the server has more than
|
||||
# one certificate, then it is possible that an SCT TLS extension is returned for some
|
||||
# certificates, but not for all of them.
|
||||
if [[ $number_of_certificates -eq 1 ]] && [[ "$TLS_EXTENSIONS" =~ "signed certificate timestamps" ]]; then
|
||||
tm_out "TLS extension"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ $number_of_certificates -gt 1 ]] && ! "$SSL_NATIVE"; then
|
||||
while read hexc n ciph sslver kx auth enc mac export; do
|
||||
if [[ ${#hexc} -eq 9 ]]; then
|
||||
ciphers+=", ${hexc:2:2},${hexc:7:2}"
|
||||
fi
|
||||
done < <($OPENSSL ciphers -V $cipher 2>>$ERRFILE)
|
||||
[[ -z "$sni_used" ]] && sni="$SNI" && SNI=""
|
||||
tls_sockets "${tls_version:2:2}" "${ciphers:2}" "all" "00,12,00,00"
|
||||
success=$?
|
||||
[[ -z "$sni_used" ]] && SNI="$sni"
|
||||
if ( [[ $success -eq 0 ]] || [[ $success -eq 2 ]] ) && \
|
||||
grep -a 'TLS server extension ' "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt" | \
|
||||
grep -aq "signed certificate timestamps"; then
|
||||
tm_out "TLS extension"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $SERVICE != "HTTP" ]]; then
|
||||
# At the moment Certificate Transparency only applies to HTTPS.
|
||||
tm_out "N/A"
|
||||
else
|
||||
tm_out "no"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
certificate_info() {
|
||||
local proto
|
||||
local -i certificate_number=$1
|
||||
@ -5572,6 +5641,7 @@ certificate_info() {
|
||||
local ocsp_response=$5
|
||||
local ocsp_response_status=$6
|
||||
local sni_used=$7
|
||||
local ct="$8"
|
||||
local cert_sig_algo cert_sig_hash_algo cert_key_algo
|
||||
local expire days2expire secs2warn ocsp_uri crl
|
||||
local startdate enddate issuer_CN issuer_C issuer_O issuer sans san all_san="" cn
|
||||
@ -6187,8 +6257,17 @@ certificate_info() {
|
||||
pr_svrty_low "--"
|
||||
fileout "${json_prefix}CAA_record" "LOW" "DNS Certification Authority Authorization (CAA) Resource Record / RFC6844 : not offered"
|
||||
fi
|
||||
outln
|
||||
|
||||
outln "\n"
|
||||
out "$indent"; pr_bold " Certificate Transparency ";
|
||||
if [[ "$ct" =~ extension ]]; then
|
||||
pr_done_good "yes"; outln " ($ct)"
|
||||
fileout "${json_prefix}certificate_transparency" "OK" "Certificate Transparency: yes ($ct)"
|
||||
else
|
||||
outln "$ct"
|
||||
fileout "${json_prefix}certificate_transparency" "INFO" "Certificate Transparency: $ct"
|
||||
fi
|
||||
outln
|
||||
return $ret
|
||||
}
|
||||
|
||||
@ -6199,7 +6278,7 @@ run_server_defaults() {
|
||||
local -i i n
|
||||
local -i certs_found=0
|
||||
local -a previous_hostcert previous_intermediates keysize cipher
|
||||
local -a ocsp_response ocsp_response_status sni_used
|
||||
local -a ocsp_response ocsp_response_status sni_used tls_version ct
|
||||
local -a ciphers_to_test
|
||||
local -a -i success
|
||||
local cn_nosni cn_sni sans_nosni sans_sni san tls_extensions
|
||||
@ -6308,11 +6387,19 @@ run_server_defaults() {
|
||||
certs_found=$(( certs_found + 1))
|
||||
cipher[certs_found]=${ciphers_to_test[n]}
|
||||
keysize[certs_found]=$(awk '/Server public key/ { print $(NF-1) }' $TMPFILE)
|
||||
ocsp_response[certs_found]=$(grep -aA 20 "OCSP response" $TMPFILE)
|
||||
# If an OCSP response was sent, then get the full
|
||||
# response so that certificate_info() can determine
|
||||
# whether it includes a certificate transparency extension.
|
||||
if grep -a "OCSP response:" $TMPFILE | grep -q "no response sent"; then
|
||||
ocsp_response[certs_found]="$(grep -a "OCSP response" $TMPFILE)"
|
||||
else
|
||||
ocsp_response[certs_found]="$(awk -v n=2 '/OCSP response:/ {start=1; inc=2} /======================================/ { if (start) {inc--} } inc' $TMPFILE)"
|
||||
fi
|
||||
ocsp_response_status[certs_found]=$(grep -a "OCSP Response Status" $TMPFILE)
|
||||
previous_hostcert[certs_found]=$newhostcert
|
||||
previous_intermediates[certs_found]=$(cat $TEMPDIR/intermediatecerts.pem)
|
||||
[[ $n -ge 8 ]] && sni_used[certs_found]="" || sni_used[certs_found]="$SNI"
|
||||
tls_version[certs_found]="$DETECTED_TLS_VERSION"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@ -6325,6 +6412,15 @@ run_server_defaults() {
|
||||
[[ -z "$sessticket_lifetime_hint" ]] && sessticket_lifetime_hint=$(grep -aw "session ticket" $TMPFILE | grep -a lifetime)
|
||||
fi
|
||||
|
||||
# Now that all of the server's certificates have been found, determine for
|
||||
# each certificate whether certificate transparency information is provided.
|
||||
for (( i=1; i <= certs_found; i++ )); do
|
||||
ct[i]="$(certificate_transparency "${previous_hostcert[i]}" "${ocsp_response[i]}" "$certs_found" "${cipher[i]}" "${sni_used[i]}" "${tls_version[i]}")"
|
||||
# If certificate_transparency() called tls_sockets() and found a "signed certificate timestamps" extension, then add it to $TLS_EXTENSIONS,
|
||||
# since it may not have been found by determine_tls_extensions().
|
||||
[[ $certs_found -gt 1 ]] && [[ "${ct[i]}" == "TLS extension" ]] && extract_new_tls_extensions "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt"
|
||||
done
|
||||
|
||||
outln
|
||||
pr_headlineln " Testing server defaults (Server Hello) "
|
||||
outln
|
||||
@ -6413,12 +6509,10 @@ run_server_defaults() {
|
||||
|
||||
tls_time
|
||||
|
||||
i=1
|
||||
while [[ $i -le $certs_found ]]; do
|
||||
for (( i=1; i <= certs_found; i++ )); do
|
||||
echo "${previous_hostcert[i]}" > $HOSTCERT
|
||||
echo "${previous_intermediates[i]}" > $TEMPDIR/intermediatecerts.pem
|
||||
certificate_info "$i" "$certs_found" "${cipher[i]}" "${keysize[i]}" "${ocsp_response[i]}" "${ocsp_response_status[i]}" "${sni_used[i]}"
|
||||
i=$((i + 1))
|
||||
certificate_info "$i" "$certs_found" "${cipher[i]}" "${keysize[i]}" "${ocsp_response[i]}" "${ocsp_response_status[i]}" "${sni_used[i]}" "${ct[i]}"
|
||||
done
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user