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
295296case :$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