X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Ftypes.c;h=59e9502e2f60f7072d4281479f8c69a14df1c576;hb=fc440c64836370db9d8cb1a25f09c9df0786f865;hp=aa34c0ab9945ab43b6256437fa25bded7df8b0b6;hpb=79d4d86add26e3ed27828e1ed4e069b6109607ed;p=adns.git diff --git a/src/types.c b/src/types.c index aa34c0a..59e9502 100644 --- a/src/types.c +++ b/src/types.c @@ -4,14 +4,15 @@ */ /* * This file is part of adns, which is - * Copyright (C) 1997-2000,2003,2006 Ian Jackson + * Copyright (C) 1997-2000,2003,2006,2014-2016,2020 Ian Jackson + * Copyright (C) 2014 Mark Wooding * Copyright (C) 1999-2000,2003,2006 Tony Finch * Copyright (C) 1991 Massachusetts Institute of Technology * (See the file INSTALL for full details.) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) + * the Free Software Foundation; either version 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, @@ -20,8 +21,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * along with this program; if not, write to the Free Software Foundation. */ #include @@ -221,7 +221,7 @@ static adns_status pa_txt(const parseinfo *pai, int cbyte, return adns_s_ok; } -static adns_status cs_txt(vbuf *vb, const void *datap) { +static adns_status cs_txt(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_intstr *const *rrp= datap; const adns_rr_intstr *current; adns_status st; @@ -238,7 +238,7 @@ static adns_status cs_txt(vbuf *vb, const void *datap) { * _hinfo (cs) */ -static adns_status cs_hinfo(vbuf *vb, const void *datap) { +static adns_status cs_hinfo(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_intstrpair *rrp= datap; adns_status st; @@ -316,7 +316,7 @@ static adns_status csp_genaddr(vbuf *vb, int af, const void *p) { return adns_s_ok; } -static adns_status cs_inaddr(vbuf *vb, const void *datap) { +static adns_status cs_inaddr(vbuf *vb, adns_rrtype rrt, const void *datap) { return csp_genaddr(vb, AF_INET,datap); } @@ -338,7 +338,7 @@ static int di_in6addr(adns_state ads, return dip_genaddr(ads,AF_INET6,datap_a,datap_b); } -static adns_status cs_in6addr(vbuf *vb, const void *datap) { +static adns_status cs_in6addr(vbuf *vb, adns_rrtype rrt, const void *datap) { return csp_genaddr(vb,AF_INET6,datap); } @@ -400,50 +400,46 @@ static unsigned addr_rrtypeflag(adns_rrtype type) { * adns__qf_addr_cname set so that we know that we're in the fixup state. */ -static adns_status pap_addr(const parseinfo *pai, int rrty, size_t rrsz, - int *cbyte_io, int max, adns_rr_addr *storeto) { - const byte *dgram= pai->dgram; - int af, addrlen, salen; +static adns_status pap_addr(const parseinfo *pai, int in_rrty, size_t out_rrsz, + int *cbyte_io, int cbyte_max, adns_rr_addr *out) { + int in_addrlen; + int out_af, out_salen; struct in6_addr v6map; - const void *oaddr= dgram + *cbyte_io; - int avail= max - *cbyte_io; - int step= -1; - void *addrp= 0; - - switch (rrty) { - case adns_r_a: - if ((pai->qu->flags & adns_qf_ipv6_mapv4) && - (pai->qu->answer->type & adns__qtf_bigaddr)) { - if (avail < 4) return adns_s_invaliddata; - memset(v6map.s6_addr + 0, 0x00, 10); - memset(v6map.s6_addr + 10, 0xff, 2); - memcpy(v6map.s6_addr + 12, oaddr, 4); - oaddr= v6map.s6_addr; avail= sizeof(v6map.s6_addr); - if (step < 0) step= 4; - goto aaaa; - } - af= AF_INET; addrlen= 4; - addrp= &storeto->addr.inet.sin_addr; - salen= sizeof(storeto->addr.inet); - break; - case adns_r_aaaa: - aaaa: - af= AF_INET6; addrlen= 16; - addrp= storeto->addr.inet6.sin6_addr.s6_addr; - salen= sizeof(storeto->addr.inet6); - break; + + const void *use_addr= pai->dgram + *cbyte_io; + + switch (in_rrty) { + case adns_r_a: in_addrlen= 4; out_af= AF_INET; break; + case adns_r_aaaa: in_addrlen= 16; out_af= AF_INET6; break; + default: abort(); } - assert(addrp); - assert(offsetof(adns_rr_addr, addr) + salen <= rrsz); - if (addrlen < avail) return adns_s_invaliddata; - if (step < 0) step= addrlen; - *cbyte_io += step; - memset(&storeto->addr, 0, salen); - storeto->len= salen; - storeto->addr.sa.sa_family= af; - memcpy(addrp, oaddr, addrlen); + if ((*cbyte_io + in_addrlen) != cbyte_max) return adns_s_invaliddata; + if (out_af==AF_INET && + (pai->qu->flags & adns_qf_ipv6_mapv4) && + (pai->qu->answer->type & adns__qtf_bigaddr)) { + memset(v6map.s6_addr + 0, 0x00, 10); + memset(v6map.s6_addr + 10, 0xff, 2); + memcpy(v6map.s6_addr + 12, use_addr, 4); + use_addr= v6map.s6_addr; + out_af= AF_INET6; + } + + switch (out_af) { + case AF_INET: out_salen= sizeof(out->addr.inet); break; + case AF_INET6: out_salen= sizeof(out->addr.inet6); break; + default: abort(); + } + + assert(offsetof(adns_rr_addr, addr) + out_salen <= out_rrsz); + + memset(&out->addr, 0, out_salen); + out->len= out_salen; + out->addr.sa.sa_family= out_af; + adns__addr_inject(use_addr, &out->addr); + + *cbyte_io += in_addrlen; return adns_s_ok; } @@ -503,7 +499,7 @@ static adns_status csp_addr(vbuf *vb, const adns_rr_addr *rrp) { return adns_s_ok; } -static adns_status cs_addr(vbuf *vb, const void *datap) { +static adns_status cs_addr(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_addr *rrp= datap; return csp_addr(vb,rrp); @@ -583,11 +579,11 @@ static adns_status addr_submit(adns_query parent, adns_query *query_r, * available record types. The memory management and callback rules are * the same as for adns__internal_submit. * - * Some differences: the query is linked onto the parent's children list - * before exit (though the parent's state is not changed, and it is not - * linked into the childw list queue); and we fiddle with the `tinfo' - * portion of the context structure (yes, modifying *ctx), since this is, - * in fact, the main purpose of this function. + * Some differences: the query is linked onto the parent's children + * list before exit (though the parent's state is not changed, and + * it is not linked into the childw list queue); and we set the + * `tinfo' portion of the context structure (yes, modifying *ctx), + * since this is, in fact, the main purpose of this function. */ adns_state ads= parent->ads; @@ -789,7 +785,7 @@ static adns_status csp_domain(vbuf *vb, const char *domain) { return adns_s_ok; } -static adns_status cs_domain(vbuf *vb, const void *datap) { +static adns_status cs_domain(vbuf *vb, adns_rrtype rrt, const void *datap) { const char *const *domainp= datap; return csp_domain(vb,*domainp); } @@ -842,6 +838,7 @@ static adns_status pap_findaddrs(const parseinfo *pai, adns_rr_hostaddr *ha, &type, &class, &ttl, &rdlen, &rdstart, pai->dgram, pai->dglen, dmstart, &ownermatched); if (st) return st; + if (type==-1) continue; if (!ownermatched || class != DNS_CLASS_IN) continue; typef= addr_rrtypeflag(type); if (!(want & typef)) continue; @@ -896,6 +893,7 @@ static void icb_hostaddr(adns_query parent, adns_query child) { done: if (st) { adns__free_interim(parent, rrp->addrs); + rrp->addrs = 0; rrp->naddrs= (st>0 && st<=adns_s_max_tempfail) ? -1 : 0; } @@ -1003,11 +1001,13 @@ static void mf_hostaddr(adns_query qu, void *datap) { mfp_hostaddr(qu,rrp); } -static adns_status csp_hostaddr(vbuf *vb, const adns_rr_hostaddr *rrp) { +static adns_status csp_hostaddr(vbuf *vb, adns_rrtype rrt, + const adns_rr_hostaddr *rrp) { const char *errstr; adns_status st; char buf[20]; int i; + size_t addrsz= gsz_addr(0, rrt); st= csp_domain(vb,rrp->host); if (st) return st; @@ -1027,7 +1027,7 @@ static adns_status csp_hostaddr(vbuf *vb, const adns_rr_hostaddr *rrp) { CSP_ADDSTR(" ("); for (i=0; inaddrs; i++) { CSP_ADDSTR(" "); - st= csp_addr(vb,&rrp->addrs[i]); + st= csp_addr(vb, (const void*)((const char*)rrp->addrs + addrsz*i)); } CSP_ADDSTR(" )"); } else { @@ -1036,10 +1036,10 @@ static adns_status csp_hostaddr(vbuf *vb, const adns_rr_hostaddr *rrp) { return adns_s_ok; } -static adns_status cs_hostaddr(vbuf *vb, const void *datap) { +static adns_status cs_hostaddr(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_hostaddr *rrp= datap; - return csp_hostaddr(vb,rrp); + return csp_hostaddr(vb,rrt,rrp); } /* @@ -1111,26 +1111,35 @@ static void mf_inthostaddr(adns_query qu, void *datap) { mfp_hostaddr(qu,&rrp->ha); } -static adns_status cs_inthostaddr(vbuf *vb, const void *datap) { - const adns_rr_inthostaddr *rrp= datap; +static adns_status csp_intofinthost(vbuf *vb, int i) { char buf[10]; - sprintf(buf,"%u ",rrp->i); + if (i < 0 || i > 0xffff) + /* currently only used for MX whose priorities are 16-bit */ + return adns_s_invaliddata; + + sprintf(buf,"%u ",i); CSP_ADDSTR(buf); + return adns_s_ok; +} - return csp_hostaddr(vb,&rrp->ha); +static adns_status cs_inthostaddr(vbuf *vb, adns_rrtype rrt, const void *datap) { + const adns_rr_inthostaddr *rrp= datap; + adns_status st; + + st = csp_intofinthost(vb,rrp->i); if (st) return st; + return csp_hostaddr(vb,rrt,&rrp->ha); } /* * _inthost (cs) */ -static adns_status cs_inthost(vbuf *vb, const void *datap) { +static adns_status cs_inthost(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_intstr *rrp= datap; - char buf[10]; + adns_status st; - sprintf(buf,"%u ",rrp->i); - CSP_ADDSTR(buf); + st = csp_intofinthost(vb,rrp->i); if (st) return st; return csp_domain(vb,rrp->str); } @@ -1281,6 +1290,7 @@ static adns_status pap_mailbox822(const parseinfo *pai, pai->dgram, pai->dglen, max, *cbyte_io, cbyte_io); st= adns__findlabel_next(&fls,&lablen,&labstart); + if (st) return st; if (!lablen) { adns__vbuf_appendstr(vb,"."); goto x_ok; @@ -1353,7 +1363,7 @@ static adns_status pa_rp(const parseinfo *pai, int cbyte, return adns_s_ok; } -static adns_status cs_rp(vbuf *vb, const void *datap) { +static adns_status cs_rp(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_strpair *rrp= datap; adns_status st; @@ -1373,7 +1383,7 @@ static adns_status pa_soa(const parseinfo *pai, int cbyte, adns_rr_soa *rrp= datap; const byte *dgram= pai->dgram; adns_status st; - int msw, lsw, i; + int i; st= pap_domain(pai, &cbyte, max, &rrp->mname, pai->qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0); @@ -1385,9 +1395,8 @@ static adns_status pa_soa(const parseinfo *pai, int cbyte, if (cbyte+20 != max) return adns_s_invaliddata; for (i=0; i<5; i++) { - GET_W(cbyte,msw); - GET_W(cbyte,lsw); - (&rrp->serial)[i]= (msw<<16) | lsw; + unsigned long v; + (&rrp->serial)[i]= GET_L(cbyte, v); } return adns_s_ok; @@ -1400,7 +1409,7 @@ static void mf_soa(adns_query qu, void *datap) { adns__makefinal_str(qu,&rrp->rname); } -static adns_status cs_soa(vbuf *vb, const void *datap) { +static adns_status cs_soa(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_soa *rrp= datap; char buf[20]; int i; @@ -1411,6 +1420,8 @@ static adns_status cs_soa(vbuf *vb, const void *datap) { st= csp_mailbox(vb,rrp->rname); if (st) return st; for (i=0; i<5; i++) { + if (rrp->serial > 0xffffffffUL) + return adns_s_invaliddata; sprintf(buf," %lu",(&rrp->serial)[i]); CSP_ADDSTR(buf); } @@ -1499,12 +1510,16 @@ static int di_srv(adns_state ads, const void *datap_a, const void *datap_b) { static adns_status csp_srv_begin(vbuf *vb, const adns_rr_srvha *rrp /* might be adns_rr_srvraw* */) { char buf[30]; + if (rrp->priority < 0 || rrp->priority > 0xffff || + rrp->weight < 0 || rrp->weight > 0xffff || + rrp->port < 0 || rrp->port > 0xffff) + return adns_s_invaliddata; sprintf(buf,"%u %u %u ", rrp->priority, rrp->weight, rrp->port); CSP_ADDSTR(buf); return adns_s_ok; } -static adns_status cs_srvraw(vbuf *vb, const void *datap) { +static adns_status cs_srvraw(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_srvraw *rrp= datap; adns_status st; @@ -1512,12 +1527,12 @@ static adns_status cs_srvraw(vbuf *vb, const void *datap) { return csp_domain(vb,rrp->host); } -static adns_status cs_srvha(vbuf *vb, const void *datap) { +static adns_status cs_srvha(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_srvha *rrp= datap; adns_status st; st= csp_srv_begin(vb,(const void*)datap); if (st) return st; - return csp_hostaddr(vb,&rrp->ha); + return csp_hostaddr(vb,rrt,&rrp->ha); } static void postsort_srv(adns_state ads, void *array, int nrrs,int rrsz, @@ -1608,12 +1623,15 @@ static adns_status pa_opaque(const parseinfo *pai, int cbyte, return adns_s_ok; } -static adns_status cs_opaque(vbuf *vb, const void *datap) { +static adns_status cs_opaque(vbuf *vb, adns_rrtype rrt, const void *datap) { const adns_rr_byteblock *rrp= datap; char buf[10]; int l; unsigned char *p; + if (rrp->len < 0 || rrp->len > 0xffff) + return adns_s_invaliddata; + sprintf(buf,"\\# %d",rrp->len); CSP_ADDSTR(buf); @@ -1697,6 +1715,10 @@ DEEP_TYPE(unknown,0, "unknown",byteblock,opaque, 0, opaque ); const typeinfo *adns__findtype(adns_rrtype type) { const typeinfo *begin, *end, *mid; + if (type & ~(adns_rrtype)0x63ffffff) + /* 0x60000000 is reserved for `harmless' future expansion */ + return 0; + if (type & adns_r_unknown) return &typeinfo_unknown; type &= adns_rrt_reprmask;