diff options
Diffstat (limited to 'contrib/unbound/util/data')
-rw-r--r-- | contrib/unbound/util/data/dname.c | 2 | ||||
-rw-r--r-- | contrib/unbound/util/data/msgencode.c | 4 | ||||
-rw-r--r-- | contrib/unbound/util/data/msgparse.c | 8 | ||||
-rw-r--r-- | contrib/unbound/util/data/msgparse.h | 6 | ||||
-rw-r--r-- | contrib/unbound/util/data/msgreply.c | 46 | ||||
-rw-r--r-- | contrib/unbound/util/data/msgreply.h | 3 | ||||
-rw-r--r-- | contrib/unbound/util/data/packed_rrset.c | 6 | ||||
-rw-r--r-- | contrib/unbound/util/data/packed_rrset.h | 6 |
8 files changed, 59 insertions, 22 deletions
diff --git a/contrib/unbound/util/data/dname.c b/contrib/unbound/util/data/dname.c index d43bbf6..79bf52a 100644 --- a/contrib/unbound/util/data/dname.c +++ b/contrib/unbound/util/data/dname.c @@ -45,7 +45,7 @@ #include "util/data/msgparse.h" #include "util/log.h" #include "util/storage/lookup3.h" -#include "ldns/sbuffer.h" +#include "sldns/sbuffer.h" /* determine length of a dname in buffer, no compression pointers allowed */ size_t diff --git a/contrib/unbound/util/data/msgencode.c b/contrib/unbound/util/data/msgencode.c index 26b5dea..43464e9 100644 --- a/contrib/unbound/util/data/msgencode.c +++ b/contrib/unbound/util/data/msgencode.c @@ -47,7 +47,7 @@ #include "util/log.h" #include "util/regional.h" #include "util/net_help.h" -#include "ldns/sbuffer.h" +#include "sldns/sbuffer.h" /** return code that means the function ran out of memory. negative so it does * not conflict with DNS rcodes. */ @@ -283,7 +283,7 @@ compress_owner(struct ub_packed_rrset_key* key, sldns_buffer* pkt, size_t owner_pos, uint16_t* owner_ptr, int owner_labs) { struct compress_tree_node* p; - struct compress_tree_node** insertpt; + struct compress_tree_node** insertpt = NULL; if(!*owner_ptr) { /* compress first time dname */ if((p = compress_tree_lookup(tree, key->rk.dname, diff --git a/contrib/unbound/util/data/msgparse.c b/contrib/unbound/util/data/msgparse.c index abe778a..108c9da 100644 --- a/contrib/unbound/util/data/msgparse.c +++ b/contrib/unbound/util/data/msgparse.c @@ -42,10 +42,10 @@ #include "util/data/packed_rrset.h" #include "util/storage/lookup3.h" #include "util/regional.h" -#include "ldns/rrdef.h" -#include "ldns/sbuffer.h" -#include "ldns/parseutil.h" -#include "ldns/wire2str.h" +#include "sldns/rrdef.h" +#include "sldns/sbuffer.h" +#include "sldns/parseutil.h" +#include "sldns/wire2str.h" /** smart comparison of (compressed, valid) dnames from packet */ static int diff --git a/contrib/unbound/util/data/msgparse.h b/contrib/unbound/util/data/msgparse.h index 221a45a..44497c8 100644 --- a/contrib/unbound/util/data/msgparse.h +++ b/contrib/unbound/util/data/msgparse.h @@ -63,8 +63,8 @@ #ifndef UTIL_DATA_MSGPARSE_H #define UTIL_DATA_MSGPARSE_H #include "util/storage/lruhash.h" -#include "ldns/pkthdr.h" -#include "ldns/rrdef.h" +#include "sldns/pkthdr.h" +#include "sldns/rrdef.h" struct sldns_buffer; struct rrset_parse; struct rr_parse; @@ -76,6 +76,8 @@ struct regional; extern time_t MAX_TTL; /** Minimum TTL that is allowed. */ extern time_t MIN_TTL; +/** Maximum Negative TTL that is allowed */ +extern time_t MAX_NEG_TTL; /** Negative cache time (for entries without any RRs.) */ #define NORR_TTL 5 /* seconds */ diff --git a/contrib/unbound/util/data/msgreply.c b/contrib/unbound/util/data/msgreply.c index 68bcfd0..06593ff 100644 --- a/contrib/unbound/util/data/msgreply.c +++ b/contrib/unbound/util/data/msgreply.c @@ -50,13 +50,15 @@ #include "util/regional.h" #include "util/data/msgparse.h" #include "util/data/msgencode.h" -#include "ldns/sbuffer.h" -#include "ldns/wire2str.h" +#include "sldns/sbuffer.h" +#include "sldns/wire2str.h" /** MAX TTL default for messages and rrsets */ time_t MAX_TTL = 3600 * 24 * 10; /* ten days */ /** MIN TTL default for messages and rrsets */ time_t MIN_TTL = 0; +/** MAX Negative TTL, for SOA records in authority section */ +time_t MAX_NEG_TTL = 3600; /* one hour */ /** allocate qinfo, return 0 on error */ static int @@ -87,6 +89,7 @@ construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd, /* rrset_count-1 because the first ref is part of the struct. */ size_t s = sizeof(struct reply_info) - sizeof(struct rrset_ref) + sizeof(struct ub_packed_rrset_key*) * total; + if(total >= RR_COUNT_MAX) return NULL; /* sanity check on numRRS*/ if(region) rep = (struct reply_info*)regional_alloc(region, s); else rep = (struct reply_info*)malloc(s + @@ -152,10 +155,23 @@ repinfo_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc, return 1; } +/** find the minimumttl in the rdata of SOA record */ +static time_t +soa_find_minttl(struct rr_parse* rr) +{ + uint16_t rlen = sldns_read_uint16(rr->ttl_data+4); + if(rlen < 20) + return 0; /* rdata too small for SOA (dname, dname, 5*32bit) */ + /* minimum TTL is the last 32bit value in the rdata of the record */ + /* at position ttl_data + 4(ttl) + 2(rdatalen) + rdatalen - 4(timeval)*/ + return (time_t)sldns_read_uint32(rr->ttl_data+6+rlen-4); +} + /** do the rdata copy */ static int rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, - struct rr_parse* rr, time_t* rr_ttl, uint16_t type) + struct rr_parse* rr, time_t* rr_ttl, uint16_t type, + sldns_pkt_section section) { uint16_t pkt_len; const sldns_rr_descriptor* desc; @@ -164,6 +180,14 @@ rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */ if(*rr_ttl & 0x80000000U) *rr_ttl = 0; + if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) { + /* negative response. see if TTL of SOA record larger than the + * minimum-ttl in the rdata of the SOA record */ + if(*rr_ttl > soa_find_minttl(rr)) + *rr_ttl = soa_find_minttl(rr); + if(*rr_ttl > MAX_NEG_TTL) + *rr_ttl = MAX_NEG_TTL; + } if(*rr_ttl < MIN_TTL) *rr_ttl = MIN_TTL; if(*rr_ttl < data->ttl) @@ -253,7 +277,7 @@ parse_rr_copy(sldns_buffer* pkt, struct rrset_parse* pset, data->rr_data[i] = nextrdata; nextrdata += rr->size; if(!rdata_copy(pkt, data, data->rr_data[i], rr, - &data->rr_ttl[i], pset->type)) + &data->rr_ttl[i], pset->type, pset->section)) return 0; rr = rr->next; } @@ -264,7 +288,7 @@ parse_rr_copy(sldns_buffer* pkt, struct rrset_parse* pset, data->rr_data[i] = nextrdata; nextrdata += rr->size; if(!rdata_copy(pkt, data, data->rr_data[i], rr, - &data->rr_ttl[i], LDNS_RR_TYPE_RRSIG)) + &data->rr_ttl[i], LDNS_RR_TYPE_RRSIG, pset->section)) return 0; rr = rr->next; } @@ -277,7 +301,11 @@ parse_create_rrset(sldns_buffer* pkt, struct rrset_parse* pset, struct packed_rrset_data** data, struct regional* region) { /* allocate */ - size_t s = sizeof(struct packed_rrset_data) + + size_t s; + if(pset->rr_count > RR_COUNT_MAX || pset->rrsig_count > RR_COUNT_MAX || + pset->size > RR_COUNT_MAX) + return 0; /* protect against integer overflow */ + s = sizeof(struct packed_rrset_data) + (pset->rr_count + pset->rrsig_count) * (sizeof(size_t)+sizeof(uint8_t*)+sizeof(time_t)) + pset->size; @@ -794,13 +822,13 @@ log_query_info(enum verbosity_value v, const char* str, } int -reply_check_cname_chain(struct reply_info* rep) +reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep) { /* check only answer section rrs for matching cname chain. * the cache may return changed rdata, but owner names are untouched.*/ size_t i; - uint8_t* sname = rep->rrsets[0]->rk.dname; - size_t snamelen = rep->rrsets[0]->rk.dname_len; + uint8_t* sname = qinfo->qname; + size_t snamelen = qinfo->qname_len; for(i=0; i<rep->an_numrrsets; i++) { uint16_t t = ntohs(rep->rrsets[i]->rk.type); if(t == LDNS_RR_TYPE_DNAME) diff --git a/contrib/unbound/util/data/msgreply.h b/contrib/unbound/util/data/msgreply.h index e8d6d76..7088979 100644 --- a/contrib/unbound/util/data/msgreply.h +++ b/contrib/unbound/util/data/msgreply.h @@ -359,10 +359,11 @@ uint8_t* reply_find_final_cname_target(struct query_info* qinfo, /** * Check if cname chain in cached reply is still valid. + * @param qinfo: query info with query name. * @param rep: reply to check. * @return: true if valid, false if invalid. */ -int reply_check_cname_chain(struct reply_info* rep); +int reply_check_cname_chain(struct query_info* qinfo, struct reply_info* rep); /** * Check security status of all RRs in the message. diff --git a/contrib/unbound/util/data/packed_rrset.c b/contrib/unbound/util/data/packed_rrset.c index 8074685..0a5c9d3 100644 --- a/contrib/unbound/util/data/packed_rrset.c +++ b/contrib/unbound/util/data/packed_rrset.c @@ -47,9 +47,9 @@ #include "util/alloc.h" #include "util/regional.h" #include "util/net_help.h" -#include "ldns/rrdef.h" -#include "ldns/sbuffer.h" -#include "ldns/wire2str.h" +#include "sldns/rrdef.h" +#include "sldns/sbuffer.h" +#include "sldns/wire2str.h" void ub_packed_rrset_parsedelete(struct ub_packed_rrset_key* pkey, diff --git a/contrib/unbound/util/data/packed_rrset.h b/contrib/unbound/util/data/packed_rrset.h index 5d7990a..6039aef 100644 --- a/contrib/unbound/util/data/packed_rrset.h +++ b/contrib/unbound/util/data/packed_rrset.h @@ -58,6 +58,12 @@ typedef uint64_t rrset_id_t; * from the SOA in the answer section from a direct SOA query or ANY query. */ #define PACKED_RRSET_SOA_NEG 0x4 +/** number of rrs and rrsets for integer overflow protection. More than + * this is not really possible (64K packet has much less RRs and RRsets) in + * a message. And this is small enough that also multiplied there is no + * integer overflow. */ +#define RR_COUNT_MAX 0xffffff + /** * The identifying information for an RRset. */ |