Skip to content

Commit a30d054

Browse files
committed
Rework dns-01 CNAME handling
See issue #840.
1 parent 34cf75e commit a30d054

File tree

1 file changed

+25
-32
lines changed

1 file changed

+25
-32
lines changed

getssl

+25-32
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@
290290
# 2023-02-04 Create newline to ensure [SAN] section can be parsed (#792)(MRigal)
291291
# 2023-02-22 Remove cronie from deb package dependencies (2.48)
292292
# 2024-03-16 Use FTP_PORT when deleting ftp tokens. Delete tokens when using sftp, davfs, ftpes, ftps (#693,#839) (tlhackque)
293+
# 2024 03-16 Fix dns-01's CNAME processing. (#840) (tlhackque)
293294
# ----------------------------------------------------------------------------------------
294295

295296
case :$SHELLOPTS: in
@@ -594,26 +595,12 @@ check_challenge_completion_dns() { # perform validation via DNS challenge
594595
check_result=$(grep -i "^${rr}"<<<"${check_output}"|grep 'IN\WTXT'|awk -F'"' '{ print $2}')
595596
debug "check_result=\"$check_result\""
596597

597-
# Check if rr is a CNAME
598-
if [[ -z "$check_result" ]]; then
599-
rr_cname=$(grep -i "^${rr}"<<<"${check_output}"|grep 'IN\WCNAME'|awk '{ print $5}')
600-
debug "cname check=\"$rr_cname\""
601-
if [[ -n "$rr_cname" ]]; then
602-
# shellcheck disable=SC2086
603-
check_output=$($DNS_CHECK_FUNC $DNS_CHECK_OPTIONS TXT "${rr_cname}" "@${ns}")
604-
check_result=$(grep -i "^${rr_cname}"<<<"${check_output}"|grep 'IN\WTXT'|awk -F'"' '{ print $2}' | uniq)
605-
fi
606-
fi
598+
# No need to check if rr is a CNAME, because the CNAME is static and this is called
599+
# with the target of the CNAME, which is the record added for verification.
600+
# In theory, a chain of CNAMEs might exist. Not clear that an issuer would follow
601+
# more than one. The code previously present here only tried to handle one.
602+
# If there is no CMAME (the usual case), ${rr} is always in ${d}.
607603

608-
if [[ -z "$check_result" ]]; then
609-
# shellcheck disable=SC2086
610-
debug "$DNS_CHECK_FUNC" $DNS_CHECK_OPTIONS ANY "${rr}" "@${ns}"
611-
# shellcheck disable=SC2086
612-
check_result=$($DNS_CHECK_FUNC $DNS_CHECK_OPTIONS ANY "${rr}" "@${ns}" \
613-
| grep -i "^${rr}" \
614-
| grep 'IN\WTXT'|awk -F'"' '{ print $2}')
615-
debug "check_result=\"$check_result\""
616-
fi
617604
elif [[ "$DNS_CHECK_FUNC" == "host" ]]; then
618605
debug "$DNS_CHECK_FUNC" -t TXT "${rr}" "${ns}"
619606
check_result=$($DNS_CHECK_FUNC -t TXT "${rr}" "${ns}" \
@@ -1441,21 +1428,24 @@ for d in "${alldomains[@]}"; do
14411428
| sed -e 's:=*$::g' -e 'y:+/:-_:')
14421429
debug auth_key "$auth_key"
14431430

1444-
add_dns_rr "${d}" "${auth_key}" \
1445-
|| error_exit "DNS_ADD_COMMAND failed for domain $d"
1446-
14471431
# shellcheck disable=SC2018,SC2019
14481432
rr="_acme-challenge.$(printf '%s' "${d#\*.}" | tr 'A-Z' 'a-z')"
14491433

1450-
# find a primary / authoritative DNS server for the domain
1451-
if [[ -z "$AUTH_DNS_SERVER" ]]; then
1452-
# Find authorative dns server for _acme-challenge.{domain} (for CNAMES/acme-dns)
1453-
get_auth_dns "${rr}"
1454-
if test -n "${cname}"; then
1434+
# find a primary / authoritative DNS server for the domain & see if RR is a CNAME
1435+
# DNS add drivers will always prefix the domain with _acme-challenge for the TXT record.
1436+
# Therefore, the target of a CNAME must start with _acme-challenge.${d} (Not an RFC
1437+
# constraint.) Note that the target of a CNAME can be ANYWHERE on the web, including
1438+
# a different TLD or a subdomain of the domain being verified..
1439+
get_auth_dns "${rr}"
1440+
if [[ -n "${cname}" ]]; then
1441+
if ! [[ "${cname}" =~ ^"_acme-challenge.${d}.".. ]]; then
1442+
error_exit "${d}: $rr uses a CNAME to ${cname}, which does not start with '_acme-challenge.${d}', which is required by getssl"
1443+
fi
14551444
rr=${cname}
1456-
fi
1445+
fi
14571446

1458-
# If no authorative dns server found, try again for {domain}
1447+
if [[ -z "$AUTH_DNS_SERVER" ]]; then
1448+
# If no authoritative dns server defined and RR search failed, try again for {domain}
14591449
if [[ -z "$primary_ns" ]]; then
14601450
get_auth_dns "$d"
14611451
fi
@@ -1466,13 +1456,16 @@ for d in "${alldomains[@]}"; do
14661456
fi
14671457
debug set primary_ns = "$primary_ns"
14681458

1469-
# internal check
1470-
check_challenge_completion_dns "${d}" "${rr}" "${primary_ns}" "${auth_key}"
1459+
add_dns_rr "${rr/#_acme-challenge./}" "${auth_key}" \
1460+
|| error_exit "DNS_ADD_COMMAND failed to add _acme-challenge.${rr/#_acme-challenge./} for domain $d"
1461+
1462+
# internal check for visibility of the record just added.
1463+
check_challenge_completion_dns "${d}" "_acme-challenge.${rr/#_acme-challenge./}" "${primary_ns}" "${auth_key}"
14711464

14721465
# let Let's Encrypt check
14731466
check_challenge_completion "${uri}" "${d}" "${keyauthorization}"
14741467

1475-
del_dns_rr "${d}" "${auth_key}"
1468+
del_dns_rr "${rr/#_acme-challenge./}" "${auth_key}"
14761469
else # set up the correct http token for verification
14771470
if [[ $API -eq 1 ]]; then
14781471
# get the token from the http component

0 commit comments

Comments
 (0)