Пример #1
0
mDNSlocal mDNSBool VerifyNSEC3(mDNS *const m, DNSSECVerifier *dv, CacheRecord *ncr, CacheRecord *closestEncloser,
    CacheRecord *closerEncloser, CacheRecord *wildcard, DNSSECVerifierCallback callback)
{
    mStatus status;
    RRVerifier *r;

    // We have three NSEC3s. If any of two are same, we should just prove one of them.
    // This is just not an optimization; DNSSECNegativeValidationCB does not handle
    // identical NSEC3s very well.

    if (closestEncloser == closerEncloser)
        closestEncloser = mDNSNULL;
    if (closerEncloser == wildcard)
        closerEncloser = mDNSNULL;
    if (closestEncloser == wildcard)
        closestEncloser = mDNSNULL;

    dv->pendingNSEC = mDNSNULL;
    if (closestEncloser)
    {
        r = AllocateRRVerifier(&closestEncloser->resrec, &status);
        if (!r)
            return mDNSfalse;
        r->next = dv->pendingNSEC;
        dv->pendingNSEC = r;
    }
    if (closerEncloser)
    {
        r = AllocateRRVerifier(&closerEncloser->resrec, &status);
        if (!r)
            return mDNSfalse;
        r->next = dv->pendingNSEC;
        dv->pendingNSEC = r;
    }
    if (wildcard)
    {
        r = AllocateRRVerifier(&wildcard->resrec, &status);
        if (!r)
            return mDNSfalse;
        r->next = dv->pendingNSEC;
        dv->pendingNSEC = r;
    }
    if (!dv->pendingNSEC)
    {
        LogMsg("VerifyNSEC3: ERROR!! pending NSEC null");
        return mDNSfalse;
    }
    r = dv->pendingNSEC;
    dv->pendingNSEC = r->next;
    r->next = mDNSNULL;

    LogDNSSEC("VerifyNSEC3: Verifying %##s (%s)", r->name.c, DNSTypeName(r->rrtype));
    if (!dv->pendingNSEC)
        VerifyNSEC(m, mDNSNULL, r, dv, ncr, mDNSNULL);
    else
        VerifyNSEC(m, mDNSNULL, r, dv, ncr, callback);
    return mDNStrue;
}
Пример #2
0
// We get a NXDOMAIN error with no records in answer section. This proves
// that qname does not exist.
mDNSlocal void NameErrorProof(mDNS *const m, DNSSECVerifier *dv, CacheRecord *ncr)
{
    CacheRecord **rp;
    ResourceRecord *nsec_wild = mDNSNULL;
    ResourceRecord *nsec_noname = mDNSNULL;
    mStatus status;

    // NXDOMAIN Error. We need to prove that the qname does not exist and there
    // is no wildcard that can be used to answer the question.

    rp = &(ncr->nsec);
    while (*rp)
    {
        if ((*rp)->resrec.rrtype == kDNSType_NSEC)
        {
            CacheRecord *cr = *rp;
            if (!NSECNameExists(m, &cr->resrec, &dv->q.qname, dv->q.qtype))
            {
                LogDNSSEC("NameErrorProof: NSEC %s proves name does not exist for %##s (%s)",
                          RRDisplayString(m, &(*rp)->resrec), dv->q.qname.c, DNSTypeName(dv->q.qtype));
                // If we have a wildcard, then we should check to see if the closest
                // encloser is the same as the wildcard.
                dv->flags |= NSEC_PROVES_NONAME_EXISTS;
                nsec_noname = &cr->resrec;
            }
            if (NSECNoWildcard(m, &cr->resrec, &dv->q.qname, dv->q.qtype))
            {
                dv->flags |= WILDCARD_PROVES_NONAME_EXISTS;
                nsec_wild = &cr->resrec;
                LogDNSSEC("NameErrorProof: NSEC %s proves wildcard cannot answer question for %##s (%s)",
                          RRDisplayString(m, &(*rp)->resrec), dv->q.qname.c, DNSTypeName(dv->q.qtype));
            }
        }
        rp=&(*rp)->next;
    }
    if (!nsec_noname || !nsec_wild)
    {
        LogMsg("NameErrorProof: Proof failed for %##s (%s) noname %p, wild %p", dv->q.qname.c, DNSTypeName(dv->q.qtype), nsec_noname, nsec_wild);
        goto error;
    }

    // First verify wildcard NSEC and then when we are done, we will verify the noname nsec.
    // Sometimes a single NSEC can prove both that the "qname" does not exist and a wildcard
    // could not have produced qname. These are a few examples where this can happen.
    //
    // 1. If the zone is example.com and you look up *.example.com and if there are no wildcards,
    //    you will get a NSEC back "example.com NSEC a.example.com". This proves that both the
    //    name does not exist and *.example.com also does not exist
    //
    // 2. If the zone is example.com and it has a record like this:
    //
    //					example.com NSEC d.example.com
    //
    // any name you lookup in between like a.example.com,b.example.com etc. you will get a single
    // NSEC back. In that case we just have to verify only once.
    //
    if (nsec_wild != nsec_noname)
    {
        RRVerifier *r = AllocateRRVerifier(nsec_noname, &status);
        if (!r) goto error;
        dv->pendingNSEC = r;
        LogDNSSEC("NoDataProof: Verifying wild %s", RRDisplayString(m, nsec_wild));
        VerifyNSEC(m, nsec_wild, mDNSNULL, dv, ncr, NameErrorNSECCallback);
    }
    else
    {
        LogDNSSEC("NoDataProof: Verifying only one %s", RRDisplayString(m, nsec_wild));
        VerifyNSEC(m, nsec_wild, mDNSNULL, dv, ncr, mDNSNULL);
    }
    return;
error:
    dv->DVCallback(m, dv, DNSSEC_Bogus);
}
Пример #3
0
// We get a NODATA error with no records in answer section. This proves
// that qname does not exist.
mDNSlocal void NoDataProof(mDNS *const m, DNSSECVerifier *dv, CacheRecord *ncr)
{
    CacheRecord **rp;
    domainname *wildcard = mDNSNULL;
    const domainname *ce = mDNSNULL;
    ResourceRecord *nsec_wild = mDNSNULL;
    ResourceRecord *nsec_noname = mDNSNULL;

    // NODATA Error could mean two things. The name exists with no type or there is a
    // wildcard that matches the name but no type. This is done by NSECNoDataError.
    //
    // If it is the case of wildcard, there are two NSECs. One is the wildcard NSEC and
    // the other NSEC to prove that there is no other closer match.

    wildcard = mDNSNULL;
    rp = &(ncr->nsec);
    while (*rp)
    {
        if ((*rp)->resrec.rrtype == kDNSType_NSEC)
        {
            CacheRecord *cr = *rp;
            if (NSECNoDataError(m, &cr->resrec, &dv->q.qname, dv->q.qtype, &wildcard))
            {
                if (wildcard)
                {
                    dv->flags |= WILDCARD_PROVES_NONAME_EXISTS;
                    LogDNSSEC("NoDataProof: NSEC %s proves NODATA error for %##s (%s)",
                              RRDisplayString(m, &(*rp)->resrec), dv->q.qname.c, DNSTypeName(dv->q.qtype));
                }
                else
                {
                    dv->flags |= NSEC_PROVES_NOTYPE_EXISTS;
                    LogDNSSEC("NoDataProof: NSEC %s proves NOTYPE error for %##s (%s)",
                              RRDisplayString(m, &(*rp)->resrec), dv->q.qname.c, DNSTypeName(dv->q.qtype));
                }
                nsec_wild = &cr->resrec;
            }
            if (!NSECNameExists(m, &cr->resrec, &dv->q.qname, dv->q.qtype))
            {
                LogDNSSEC("NoDataProof: NSEC %s proves that  name %##s (%s) does not exist",
                          RRDisplayString(m, &(*rp)->resrec), dv->q.qname.c, DNSTypeName(dv->q.qtype));
                // If we have a wildcard, then we should check to see if the closest
                // encloser is the same as the wildcard.
                ce = NSECClosestEncloser(&cr->resrec, &dv->q.qname);
                dv->flags |= NSEC_PROVES_NONAME_EXISTS;
                nsec_noname = &cr->resrec;
            }
        }
        rp=&(*rp)->next;
    }
    if (!nsec_noname && !nsec_wild)
    {
        LogDNSSEC("NoDataProof: No valid NSECs for %##s (%s)", dv->q.qname.c, DNSTypeName(dv->q.qtype));
        goto error;
    }
    // If the type exists, then we have to verify just that NSEC
    if (!(dv->flags & NSEC_PROVES_NOTYPE_EXISTS))
    {
        // If we have a wildcard, then we should have a "ce" which matches the wildcard
        // If we don't have a wildcard, then we should have proven that the name does not
        // exist which means we would have set the "ce".
        if (wildcard && !ce)
        {
            LogMsg("NoDataProof: Cannot prove that the name %##s (%s) does not exist", dv->q.qname.c, DNSTypeName(dv->q.qtype));
            goto error;
        }
        if (wildcard && !SameDomainName(wildcard, ce))
        {
            LogMsg("NoDataProof: wildcard %##s does not match closest encloser %##s", wildcard->c, ce->c);
            goto error;
        }
        // If a single NSEC can prove both, then we just have validate that one NSEC.
        if (nsec_wild == nsec_noname)
        {
            nsec_noname = mDNSNULL;
            dv->flags &= ~NSEC_PROVES_NONAME_EXISTS;
        }
    }

    if ((dv->flags & (WILDCARD_PROVES_NONAME_EXISTS|NSEC_PROVES_NONAME_EXISTS)) ==
        (WILDCARD_PROVES_NONAME_EXISTS|NSEC_PROVES_NONAME_EXISTS))
    {
        mStatus status;
        RRVerifier *r = AllocateRRVerifier(nsec_noname, &status);
        if (!r) goto error;
        // First verify wildcard NSEC and then when we are done, we
        // will verify the noname nsec
        dv->pendingNSEC = r;
        LogDNSSEC("NoDataProof: Verifying wild and noname %s", RRDisplayString(m, nsec_wild));
        VerifyNSEC(m, nsec_wild, mDNSNULL, dv, ncr, NoDataNSECCallback);
    }
    else if ((dv->flags & WILDCARD_PROVES_NONAME_EXISTS) ||
             (dv->flags & NSEC_PROVES_NOTYPE_EXISTS))
    {
        LogDNSSEC("NoDataProof: Verifying wild %s", RRDisplayString(m, nsec_wild));
        VerifyNSEC(m, nsec_wild, mDNSNULL, dv, ncr, mDNSNULL);
    }
    else if (dv->flags & NSEC_PROVES_NONAME_EXISTS)
    {
        LogDNSSEC("NoDataProof: Verifying noname %s", RRDisplayString(m, nsec_noname));
        VerifyNSEC(m, nsec_noname, mDNSNULL, dv, ncr, mDNSNULL);
    }
    return;
error:
    LogDNSSEC("NoDataProof: Error return");
    dv->DVCallback(m, dv, DNSSEC_Bogus);
}