Broken handling of DS/NSEC records in signed, wildcard+CNAME-sourced delegations
When answering a query requires wildcard expansion, the AUTHORITY section of the response needs to include NSEC(3) record(s) proving that the QNAME does not exist.
When a response to a query is an insecure delegation, the AUTHORITY section needs to include an NSEC(3) proof that no DS record exists at the parent side of the zone cut.
These two conditions combined trip up the NSEC part of the logic contained in query_addds(), which expects the NS RRset to be owned by the first name found in the AUTHORITY section of a delegation response. This may not always be true, for example if wildcard expansion causes an NSEC record proving QNAME nonexistence to be added to the AUTHORITY section before the delegation is added to the response. In such a case, named incorrectly omits the NSEC record proving nonexistence of QNAME from the AUTHORITY section.
The same block of code is affected by another flaw: if the same NSEC record proves nonexistence of both the QNAME and the DS record at the parent side of the zone cut, this NSEC record will be added to the AUTHORITY section twice.
This issue was originally reported by @libchap.