Created attachment 2166 [details] Short example Hello, Under the following conditions, SSH crash: - SSH is compiled with ldns for DNS support - You use a DNS resolver with DNSSEC enabled - You have SSHFP keys - You attempt to connect through a CNAME (instead of the host name, see attachment) I have tracked the problem down to the file openbsd-compat/getrrsetbyname-ldns.c In function getrrsetbyname, when the DNS resolver sets the ad flags, ssh doesn't allocate memory to contain RRSIG signatures. However it still attempts to copy those signatures from the DNS answer. If rrset->rri_sigs is null, rdata = &rrset->rri_sigs[0] is still null and the signature is ignored later in the code. Luckily, most of the time, you only have one signature and there is no problem. If you have a CNAME, you got two signatures and &rrset->rri_sigs[1] is no not null hence the segfault.
Created attachment 2167 [details] A short patch to solve the problem
Patch applied, thanks. I still don't understand how it gets into this state since the space should be allocated immediately beforehand: if (rrset->rri_nsigs > 0) { rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo)); What's rrset->rri_nsigs in the failure case?
The failure case happens when your DNS resolver does the DNSSEC validation for you and sets the ad flag (but RRSIG are still included DNS answer). Then SSH trusts the resolver, skip the DNSSEC validation and does not initialize rrset->rri_nsig, hence rrset->rri_nsig is 0 and the memory is not allocated. /* Check for authenticated data */ if (ldns_pkt_ad(pkt)) { rrset->rri_flags |= RRSET_VALIDATED; } else { /* AD is not set, try autonomous validation */ //... rrset->rri_nsigs = ldns_rr_list_rr_count(rrsigs); debug2("ldns: got %u signature(s) (RRTYPE %u) from DNS", rrset->rri_nsigs, LDNS_RR_TYPE_RRSIG); //... }
OK, makes sense. Thanks, the patch will be in the next release.
Set all RESOLVED bugs to CLOSED with release of OpenSSH 7.1