Currently `compare_server_name_to_cert()` only indicates whether the server's host name matches a wildcard name in the certificate. So, it does not indicate if the certificate includes a wildcard name that does not match the server's host name. As a result, if a certificate includes the names "api.sub.example.tld" and "*.api.sub.example.tld," then a wildcard certificate warning will be issued for host names such as www.api.sub.example.tld, but not for api.sub.example.tld.

This commit changes `compare_server_name_to_cert()` to indicate whether the certificate is a wildcard certificate in addition to providing information about how the certificate matches the server's host name. Functions that use this function's response are then changed to extract the information they need (matching or wildcard) from the return value.
This commit is contained in:
David Cooper 2025-01-16 14:51:16 -08:00
parent daf0671878
commit 95b6258f82

View File

@ -8386,12 +8386,14 @@ wildcard_match()
# 8, if the server name provided is a wildcard match against the CN # 8, if the server name provided is a wildcard match against the CN
# 9, if the server name provided matches a name in the SAN AND is a wildcard match against the CN # 9, if the server name provided matches a name in the SAN AND is a wildcard match against the CN
# 10, if the server name provided is a wildcard match against the CN AND a name in the SAN # 10, if the server name provided is a wildcard match against the CN AND a name in the SAN
#
# Add 128 to the return value if the CN or a DNS name in the SAN is a wildcard.
compare_server_name_to_cert() { compare_server_name_to_cert() {
local cert="$1" local cert="$1"
local servername cns cn dns_sans ip_sans san dercert tag local servername cns cn dns_sans ip_sans san dercert tag
local srv_id="" xmppaddr="" local srv_id="" xmppaddr=""
local -i i len len1 cn_match=0 local -i i len len1 cn_match=0 wildcard_cert=0
local -i subret=0 # no error condition, passing results local -i subret=0 # no error condition, passing results
HAS_DNS_SANS=false HAS_DNS_SANS=false
@ -8536,10 +8538,16 @@ compare_server_name_to_cert() {
fi fi
# Check whether any of the DNS names in the certificate are wildcard names # Check whether any of the DNS names in the certificate are wildcard names
# that match the servername # and if they match the servername
if [[ $subret -eq 0 ]]; then if [[ $subret -eq 0 ]]; then
while read san; do while read san; do
[[ -n "$san" ]] || continue [[ -n "$san" ]] || continue
is_wildcard "$san"
if [[ $? -eq 0 ]]; then
wildcard_cert=128
else
continue
fi
wildcard_match "$servername" "$san" wildcard_match "$servername" "$san"
[[ $? -eq 0 ]] && subret=2 && break [[ $? -eq 0 ]] && subret=2 && break
done <<< "$dns_sans" done <<< "$dns_sans"
@ -8555,13 +8563,20 @@ compare_server_name_to_cert() {
# Check whether the CN matches the servername # Check whether the CN matches the servername
[[ $(toupper "$cn") == "$servername" ]] && cn_match=4 && break [[ $(toupper "$cn") == "$servername" ]] && cn_match=4 && break
# Check whether the CN is a wildcard name that matches the servername # Check whether the CN is a wildcard name and if it matches the servername
# NOTE: Don't stop loop on a wildcard match in case there is another CN # NOTE: Don't stop loop on a wildcard match in case there is another CN
# that is an exact match. # that is an exact match.
is_wildcard "$cn"
if [[ $? -eq 0 ]]; then
wildcard_cert=128
else
continue
fi
wildcard_match "$servername" "$cn" wildcard_match "$servername" "$cn"
[[ $? -eq 0 ]] && cn_match=8 [[ $? -eq 0 ]] && cn_match=8
done <<< "$cns" done <<< "$cns"
subret+=$cn_match subret+=$cn_match
subret+=$wildcard_cert
return $subret return $subret
} }
@ -9456,7 +9471,7 @@ certificate_info() {
# supported by the client. # supported by the client.
has_dns_sans=$HAS_DNS_SANS has_dns_sans=$HAS_DNS_SANS
case $trust_sni in case $((trust_sni%128)) in
0) trustfinding="certificate does not match supplied URI" 0) trustfinding="certificate does not match supplied URI"
set_grade_cap "M" "Domain name mismatch" set_grade_cap "M" "Domain name mismatch"
;; ;;
@ -9483,10 +9498,10 @@ certificate_info() {
;; ;;
esac esac
if [[ $trust_sni -eq 0 ]]; then if [[ $((trust_sni%128)) -eq 0 ]]; then
pr_svrty_high "$trustfinding" pr_svrty_high "$trustfinding"
trust_sni_finding="HIGH" trust_sni_finding="HIGH"
elif [[ $trust_sni -eq 4 ]] || [[ $trust_sni -eq 8 ]]; then elif [[ $((trust_sni%128)) -eq 4 ]] || [[ $((trust_sni%128)) -eq 8 ]]; then
if [[ $SERVICE == HTTP ]] || "$ASSUME_HTTP"; then if [[ $SERVICE == HTTP ]] || "$ASSUME_HTTP"; then
# https://bugs.chromium.org/p/chromium/issues/detail?id=308330 # https://bugs.chromium.org/p/chromium/issues/detail?id=308330
# https://bugzilla.mozilla.org/show_bug.cgi?id=1245280 # https://bugzilla.mozilla.org/show_bug.cgi?id=1245280
@ -9513,17 +9528,17 @@ certificate_info() {
# See issue #733. # See issue #733.
if [[ -z "$sni_used" ]]; then if [[ -z "$sni_used" ]]; then
trustfinding_nosni="" trustfinding_nosni=""
elif [[ $trust_sni -eq $trust_nosni && "$has_dns_sans" == "$has_dns_sans_nosni" ]] || \ elif [[ $((trust_sni%128)) -eq $((trust_nosni%128)) && "$has_dns_sans" == "$has_dns_sans_nosni" ]] || \
[[ $trust_sni -eq 0 && $trust_nosni -eq 0 ]]; then [[ $((trust_sni%128)) -eq 0 && $((trust_nosni%128)) -eq 0 ]]; then
trustfinding_nosni=" (same w/o SNI)" trustfinding_nosni=" (same w/o SNI)"
elif [[ $trust_nosni -eq 0 ]]; then elif [[ $((trust_nosni%128)) -eq 0 ]]; then
if [[ $trust_sni -eq 4 ]] || [[ $trust_sni -eq 8 ]]; then if [[ $((trust_sni%128)) -eq 4 ]] || [[ $((trust_sni%128)) -eq 8 ]]; then
trustfinding_nosni=" (w/o SNI: certificate does not match supplied URI)" trustfinding_nosni=" (w/o SNI: certificate does not match supplied URI)"
else else
trustfinding_nosni=" (SNI mandatory)" trustfinding_nosni=" (SNI mandatory)"
fi fi
elif [[ $trust_nosni -eq 4 ]] || [[ $trust_nosni -eq 8 ]] || [[ $trust_sni -eq 4 ]] || [[ $trust_sni -eq 8 ]]; then elif [[ $((trust_nosni%128)) -eq 4 ]] || [[ $((trust_nosni%128)) -eq 8 ]] || [[ $((trust_sni%128)) -eq 4 ]] || [[ $((trust_sni%128)) -eq 8 ]]; then
case $trust_nosni in case $((trust_nosni%128)) in
1) trustfinding_nosni=" (w/o SNI: Ok via SAN)" ;; 1) trustfinding_nosni=" (w/o SNI: Ok via SAN)" ;;
2) trustfinding_nosni=" (w/o SNI: Ok via SAN wildcard)" ;; 2) trustfinding_nosni=" (w/o SNI: Ok via SAN wildcard)" ;;
4) if "$has_dns_sans_nosni"; then 4) if "$has_dns_sans_nosni"; then
@ -9543,12 +9558,12 @@ certificate_info() {
9) trustfinding_nosni=" (w/o SNI: Ok via CN wildcard and SAN)" ;; 9) trustfinding_nosni=" (w/o SNI: Ok via CN wildcard and SAN)" ;;
10) trustfinding_nosni=" (w/o SNI: Ok via SAN wildcard and CN wildcard)" ;; 10) trustfinding_nosni=" (w/o SNI: Ok via SAN wildcard and CN wildcard)" ;;
esac esac
elif [[ $trust_sni -ne 0 ]]; then elif [[ $((trust_sni%128)) -ne 0 ]]; then
trustfinding_nosni=" (works w/o SNI)" trustfinding_nosni=" (works w/o SNI)"
else else
trustfinding_nosni=" (however, works w/o SNI)" trustfinding_nosni=" (however, works w/o SNI)"
fi fi
if [[ -n "$sni_used" ]] || [[ $trust_nosni -eq 0 ]] || [[ $trust_nosni -ne 4 && $trust_nosni -ne 8 ]]; then if [[ -n "$sni_used" ]] || [[ $((trust_nosni%128)) -eq 0 ]] || [[ $((trust_nosni%128)) -ne 4 && $((trust_nosni%128)) -ne 8 ]]; then
outln "$trustfinding_nosni" outln "$trustfinding_nosni"
elif [[ $SERVICE == HTTP ]] || "$ASSUME_HTTP"; then elif [[ $SERVICE == HTTP ]] || "$ASSUME_HTTP"; then
prln_svrty_high "$trustfinding_nosni" prln_svrty_high "$trustfinding_nosni"
@ -9558,7 +9573,7 @@ certificate_info() {
fileout "cert_trust${json_postfix}" "$trust_sni_finding" "${trustfinding}${trustfinding_nosni}" fileout "cert_trust${json_postfix}" "$trust_sni_finding" "${trustfinding}${trustfinding_nosni}"
if [[ "$trust_sni" =~ ^(2|6|8|9|10)$ ]] || [[ "$trust_nosni" =~ ^(2|6|8|9|10)$ ]]; then if [[ $((trust_sni&128)) -eq 128 ]] || [[ $((trust_nosni&128)) -eq 128 ]]; then
out "${spaces}" out "${spaces}"
pr_svrty_low "wildcard certificate" ; outln " could be problematic, see other hosts at" pr_svrty_low "wildcard certificate" ; outln " could be problematic, see other hosts at"
outln "${spaces}https://search.censys.io/search?resource=hosts&virtual_hosts=INCLUDE&q=$cert_fingerprint_sha2" outln "${spaces}https://search.censys.io/search?resource=hosts&virtual_hosts=INCLUDE&q=$cert_fingerprint_sha2"
@ -10164,7 +10179,7 @@ run_server_defaults() {
# $NODE being tested or if it has the same subject # $NODE being tested or if it has the same subject
# (CN and SAN) as other certificates for this host. # (CN and SAN) as other certificates for this host.
compare_server_name_to_cert "$HOSTCERT" compare_server_name_to_cert "$HOSTCERT"
[[ $? -ne 0 ]] && success[n]=0 || success[n]=1 [[ $(($?%128)) -ne 0 ]] && success[n]=0 || success[n]=1
if [[ ${success[n]} -ne 0 ]]; then if [[ ${success[n]} -ne 0 ]]; then
cn_nosni="$(toupper "$(get_cn_from_cert $HOSTCERT)")" cn_nosni="$(toupper "$(get_cn_from_cert $HOSTCERT)")"