Bug 2022

Summary: ssh segfaults when using ldns, SSHFP, a DNSSEC-enabled resolver and a CNAME
Product: Portable OpenSSH Reporter: gregdlg+mr
Component: sshAssignee: Assigned to nobody <unassigned-bugs>
Status: CLOSED FIXED    
Severity: normal CC: dtucker
Priority: P2    
Version: 6.0p1   
Hardware: All   
OS: All   
Bug Depends on:    
Bug Blocks: 1986    
Attachments:
Description Flags
Short example
none
A short patch to solve the problem none

Description gregdlg+mr 2012-06-26 14:03:32 AEST
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.
Comment 1 gregdlg+mr 2012-06-26 14:07:24 AEST
Created attachment 2167 [details]
A short patch to solve the problem
Comment 2 Darren Tucker 2012-06-29 18:00:03 AEST
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?
Comment 3 gregdlg+mr 2012-06-29 19:56:12 AEST
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);
        //...
    }
Comment 4 Darren Tucker 2012-07-20 10:14:37 AEST
OK, makes sense.  Thanks, the patch will be in the next release.
Comment 5 Damien Miller 2015-08-11 23:03:42 AEST
Set all RESOLVED bugs to CLOSED with release of OpenSSH 7.1