Bug 2022 - ssh segfaults when using ldns, SSHFP, a DNSSEC-enabled resolver and a CNAME
Summary: ssh segfaults when using ldns, SSHFP, a DNSSEC-enabled resolver and a CNAME
Status: CLOSED FIXED
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: ssh (show other bugs)
Version: 6.0p1
Hardware: All All
: P2 normal
Assignee: Assigned to nobody
URL:
Keywords:
Depends on:
Blocks: V_6_1
  Show dependency treegraph
 
Reported: 2012-06-26 14:03 AEST by gregdlg+mr
Modified: 2015-08-11 23:03 AEST (History)
1 user (show)

See Also:


Attachments
Short example (2.77 KB, text/plain)
2012-06-26 14:03 AEST, gregdlg+mr
no flags Details
A short patch to solve the problem (540 bytes, patch)
2012-06-26 14:07 AEST, gregdlg+mr
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
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