From bce6e1bc6db7476242558956834d608c9220a9a5 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Thu, 23 Jan 2014 22:02:19 +0000 Subject: [PATCH] RRSIGs in DS and DNSKEY cached answers. --- src/cache.c | 16 ++++---- src/rfc1035.c | 111 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 75 insertions(+), 52 deletions(-) diff --git a/src/cache.c b/src/cache.c index 71a3efc..c464b0d 100644 --- a/src/cache.c +++ b/src/cache.c @@ -722,7 +722,7 @@ static void add_hosts_cname(struct crec *target) if (hostname_isequal(cache_get_name(target), a->target) && (crec = whine_malloc(sizeof(struct crec)))) { - crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME | F_DNSSECOK; + crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME; crec->name.namep = a->alias; crec->addr.cname.target.cache = target; crec->addr.cname.uid = target->uid; @@ -859,14 +859,14 @@ static int read_hostsfile(char *filename, int index, int cache_size, struct crec if (inet_pton(AF_INET, token, &addr) > 0) { - flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_DNSSECOK; + flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4; addrlen = INADDRSZ; domain_suffix = get_domain(addr.addr.addr4); } #ifdef HAVE_IPV6 else if (inet_pton(AF_INET6, token, &addr) > 0) { - flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_DNSSECOK; + flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6; addrlen = IN6ADDRSZ; domain_suffix = get_domain6(&addr.addr.addr6); } @@ -984,7 +984,7 @@ void cache_reload(void) if (hostname_isequal(a->target, intr->name) && ((cache = whine_malloc(sizeof(struct crec))))) { - cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG | F_DNSSECOK; + cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG; cache->name.namep = a->alias; cache->addr.cname.target.int_name = intr; cache->addr.cname.uid = -1; @@ -1022,7 +1022,7 @@ void cache_reload(void) (cache = whine_malloc(sizeof(struct crec)))) { cache->name.namep = nl->name; - cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG | F_DNSSECOK; + cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG; add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, 0, (struct crec **)daemon->packet, revhashsz); } #ifdef HAVE_IPV6 @@ -1030,7 +1030,7 @@ void cache_reload(void) (cache = whine_malloc(sizeof(struct crec)))) { cache->name.namep = nl->name; - cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG | F_DNSSECOK; + cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG; add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, 0, (struct crec **)daemon->packet, revhashsz); } #endif @@ -1100,7 +1100,7 @@ static void add_dhcp_cname(struct crec *target, time_t ttd) if (aliasc) { - aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME | F_CONFIG | F_DNSSECOK; + aliasc->flags = F_FORWARD | F_NAMEP | F_DHCP | F_CNAME | F_CONFIG; if (ttd == 0) aliasc->flags |= F_IMMORTAL; else @@ -1188,7 +1188,7 @@ void cache_add_dhcp_entry(char *host_name, int prot, if (crec) /* malloc may fail */ { - crec->flags = flags | F_NAMEP | F_DHCP | F_FORWARD | F_DNSSECOK; + crec->flags = flags | F_NAMEP | F_DHCP | F_FORWARD; if (ttd == 0) crec->flags |= F_IMMORTAL; else diff --git a/src/rfc1035.c b/src/rfc1035.c index 75ba017..db98c62 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -1544,54 +1544,77 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, } #ifdef HAVE_DNSSEC - if ((qtype == T_DNSKEY || qtype == T_ANY) && (crecp = cache_find_by_name(NULL, name, now, F_DNSKEY))) + if (qtype == T_DNSKEY || qtype == T_DS || qtype == T_RRSIG) { - do { - char *keydata; - - if (crecp->uid == qclass && - (qtype == T_DNSKEY || (crecp->flags & F_CONFIG)) && - (keydata = blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, NULL))) - { - ans = 1; - if (!dryrun) - { - struct all_addr a; - a.addr.keytag = crecp->addr.key.keytag; - log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DNSKEY keytag %u"); - if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, - crec_ttl(crecp, now), &nameoffset, - T_DNSKEY, qclass, "sbbt", - crecp->addr.key.flags, 3, crecp->addr.key.algo, crecp->addr.key.keylen, keydata)) - anscount++; - } - } - } while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY))); - } + int gotone = 0; + struct blockdata *keydata; - if ((qtype == T_DS || qtype == T_ANY) && (crecp = cache_find_by_name(NULL, name, now, F_DS))) - { - do { - char *keydata; - - if (crecp->uid == qclass && - (qtype == T_DS || (crecp->flags & F_CONFIG)) && - (keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL))) - { - ans = 1; - if (!dryrun) + /* Do we have RRSIG? Can't do DS or DNSKEY otherwise. */ + crecp = NULL; + while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS))) + if (crecp->uid == qclass && (qtype == T_RRSIG || crecp->addr.sig.type_covered == qtype)) + break; + + if (crecp) + { + if (qtype == T_RRSIG) + ans = gotone = 1; + else if (qtype == T_DS) + { + crecp = NULL; + while ((crecp = cache_find_by_name(crecp, name, now, F_DS))) + if (crecp->uid == qclass) + { + ans = gotone = 1; + if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL))) + { + struct all_addr a; + a.addr.keytag = crecp->addr.ds.keytag; + log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DS keytag %u"); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + crec_ttl(crecp, now), &nameoffset, + T_DS, qclass, "sbbt", + crecp->addr.ds.keytag, crecp->addr.ds.algo, crecp->addr.ds.digest, crecp->addr.ds.keylen, keydata)) + anscount++; + + } + } + } + else if (qtype == T_DNSKEY) { - struct all_addr a; - a.addr.keytag = crecp->addr.ds.keytag; - log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DS keytag %u"); - if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, - crec_ttl(crecp, now), &nameoffset, - T_DS, qclass, "sbbt", - crecp->addr.ds.keytag, crecp->addr.ds.algo, crecp->addr.ds.digest, crecp->addr.ds.keylen, keydata)) - anscount++; + crecp = NULL; + while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY))) + if (crecp->uid == qclass) + { + ans = gotone = 1; + if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, NULL))) + { + struct all_addr a; + a.addr.keytag = crecp->addr.key.keytag; + log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DNSKEY keytag %u"); + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, + crec_ttl(crecp, now), &nameoffset, + T_DNSKEY, qclass, "sbbt", + crecp->addr.key.flags, 3, crecp->addr.key.algo, crecp->addr.key.keylen, keydata)) + anscount++; + } + } } - } - } while ((crecp = cache_find_by_name(crecp, name, now, F_DS))); + + /* Now do RRSIGs */ + if (gotone) + { + crecp = NULL; + while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS))) + if (crecp->uid == qclass && (qtype == T_RRSIG || (sec_reqd && crecp->addr.sig.type_covered == qtype)) && + !dryrun && + (keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)) && + add_resource_record(header, limit, &trunc, nameoffset, &ansp, + crec_ttl(crecp, now), &nameoffset, + T_RRSIG, qclass, "t", crecp->addr.sig.keylen, keydata)) + anscount++; + } + } } #endif