Exemple #1
0
mDNSexport CacheRecord *NSECRecordIsDelegation(mDNS *const m, domainname *name, mDNSu16 qtype)
{
    CacheGroup *cg;
    CacheRecord *cr;
    mDNSu32 slot, namehash;

    slot = HashSlot(name);
    namehash = DomainNameHashValue(name);

    cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, name);
    if (!cg)
    {
        LogDNSSEC("NSECRecordForName: cg NULL for %##s", name);
        return mDNSNULL;
    }
    for (cr = cg->members; cr; cr = cr->next)
    {
        if (cr->resrec.RecordType == kDNSRecordTypePacketNegative && cr->resrec.rrtype == qtype)
        {
            CacheRecord *ncr;
            for (ncr = cr->nsec; ncr; ncr = ncr->next)
            {
                if (ncr->resrec.rrtype == kDNSType_NSEC &&
                    SameDomainName(ncr->resrec.name, name))
                {
                    // See the Insecure Delegation Proof section in dnssec-bis: DS bit and SOA bit
                    // should be absent
                    if (RRAssertsExistence(&ncr->resrec, kDNSType_SOA) ||
                        RRAssertsExistence(&ncr->resrec, kDNSType_DS))
                    {
                        LogDNSSEC("NSECRecordForName: found record %s for %##s (%s), but DS or SOA bit set", CRDisplayString(m, ncr), name,
                            DNSTypeName(qtype));
                        return mDNSNULL;
                    }
                    // Section 2.3 of RFC 4035 states that:
                    //
                    // Each owner name in the zone that has authoritative data or a delegation point NS RRset MUST
                    // have an NSEC resource record. 
                    //
                    // So, if we have an NSEC record matching the question name with the NS bit set,
                    // then this is a delegation.
                    //
                    if (RRAssertsExistence(&ncr->resrec, kDNSType_NS))
                    {
                        LogDNSSEC("NSECRecordForName: found record %s for %##s (%s)", CRDisplayString(m, ncr), name, DNSTypeName(qtype));
                        return ncr;
                    }
                    else
                    {
                        LogDNSSEC("NSECRecordForName: found record %s for %##s (%s), but NS bit is not set", CRDisplayString(m, ncr), name,
                            DNSTypeName(qtype));
                        return mDNSNULL;
                    }
                }
            }
        }
    }
    return mDNSNULL;
}
Exemple #2
0
mDNSlocal CacheRecord *NSECParentForQuestion(mDNS *const m, DNSQuestion *q)
{
    CacheGroup *cg;
    CacheRecord *cr;
    mDNSu32 slot;
    mDNSu32 namehash;

    slot = HashSlot(&q->qname);
    namehash = DomainNameHashValue(&q->qname);
    cg = CacheGroupForName(m, slot, namehash, &q->qname);
    if (!cg)
    {
        LogDNSSEC("NSECParentForQuestion: Cannot find cg for %##s (%s)", q->qname.c, DNSTypeName(q->qtype));
        return mDNSNULL;
    }
    for (cr = cg->members; cr; cr = cr->next)
        if (SameNameRecordAnswersQuestion(&cr->resrec, q))
            return cr;
    return mDNSNULL;
}
mDNSexport CacheRecord *NSEC3RecordIsDelegation(mDNS *const m, domainname *name, mDNSu16 qtype)
{
    CacheGroup *cg;
    CacheRecord *cr;
    CacheRecord *ncr;
    mDNSu32 slot, namehash;

    slot = HashSlot(name);
    namehash = DomainNameHashValue(name);

    cg = CacheGroupForName(m, (const mDNSu32)slot, namehash, name);
    if (!cg)
    {
        LogDNSSEC("NSEC3RecordForName: cg NULL for %##s", name);
        return mDNSNULL;
    }
    for (ncr = cg->members; ncr; ncr = ncr->next)
    {
        if (ncr->resrec.RecordType != kDNSRecordTypePacketNegative ||
            ncr->resrec.rrtype != qtype)
        {
            continue;
        }
        for (cr = ncr->nsec; cr; cr = cr->next)
        {
            int hlen, b32len;
            const mDNSu8 hashName[NSEC3_MAX_HASH_LEN];
            const mDNSu8 b32Name[NSEC3_MAX_B32_LEN+1];
            const RDataBody2 *const rdb = (RDataBody2 *)cr->resrec.rdata->u.data;
            rdataNSEC3 *nsec3;

            if (cr->resrec.rrtype != kDNSType_NSEC3)
                continue;

            nsec3 = (rdataNSEC3 *)rdb->data;

            if (!NSEC3HashName(name, nsec3, mDNSNULL, 0, hashName, &hlen))
            {
                LogMsg("NSEC3RecordIsDelegation: NSEC3HashName failed for ##s", name->c);
                return mDNSNULL;
            }

            b32len = baseEncode((char *)b32Name, sizeof(b32Name), (mDNSu8 *)hashName, hlen, ENC_BASE32);
            if (!b32len)
            {
                LogMsg("NSEC3RecordIsDelegation: baseEncode of name %##s failed", name->c);
                return mDNSNULL;
            }
            // Section 2.3 of RFC 4035 states that:
            //
            // Each owner name in the zone that has authoritative data or a delegation point NS RRset MUST
            // have an NSEC resource record. 
            //
            // This applies to NSEC3 record. So, if we have an NSEC3 record matching the question name with the
            // NS bit set, then this is a delegation.
            //
            if (!NSEC3SameName(&cr->resrec.name->c[1], cr->resrec.name->c[0], (const mDNSu8 *)b32Name, b32len))
            {
                int bmaplen;
                mDNSu8 *bmap;
                
                LogDNSSEC("NSEC3RecordIsDelegation: CacheRecord %s matches name %##s, b32name %s", CRDisplayString(m, cr), name->c, b32Name);
                NSEC3Parse(&cr->resrec, mDNSNULL, mDNSNULL, mDNSNULL, &bmaplen, &bmap);

                // See the Insecure Delegation Proof section in dnssec-bis: DS bit and SOA bit
                // should be absent
                if (BitmapTypeCheck(bmap, bmaplen, kDNSType_SOA) ||
                    BitmapTypeCheck(bmap, bmaplen, kDNSType_DS))
                {
                    LogDNSSEC("NSEC3RecordIsDelegation: CacheRecord %s has DS or SOA bit set, ignoring", CRDisplayString(m, cr));
                    return mDNSNULL;
                }
                if (BitmapTypeCheck(bmap, bmaplen, kDNSType_NS))
                    return cr;
                else
                    return mDNSNULL;
            }
            // If opt-out is not set, then it does not cover any delegations
            if (!(nsec3->flags & NSEC3_FLAGS_OPTOUT))
                continue;
            // Opt-out allows insecure delegations to exist without the NSEC3 RR at the
            // hashed owner name (see RFC 5155 section 6.0).
            if (NSEC3CoversName(m, cr, hashName, hlen, b32Name, b32len))
            {
                LogDNSSEC("NSEC3RecordIsDelegation: CacheRecord %s covers name %##s with optout", CRDisplayString(m, cr), name->c);
                return cr;
            }
        }
    }
    return mDNSNULL;
}