From 549a6745e3b6a69c9a14deb5090b8fa1ad444f06 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sun, 28 Jan 2018 22:36:01 +0100 Subject: [PATCH] ndb/dns: fix leak in myaddr(), normalize ip strings remove myaddr() function and replace with myip() function that receives binary ip address. and don't use string comparsion for ip addresses... parse and then ipcmp(). for sanity reasons, normalize ip address strings and reject unparsable ones. done by calling ipalookup() with a binary ip address. --- sys/src/cmd/ndb/dblookup.c | 130 +++++++++++++++++------------------- sys/src/cmd/ndb/dn.c | 9 +++ sys/src/cmd/ndb/dnresolve.c | 14 ++-- sys/src/cmd/ndb/dns.h | 5 +- 4 files changed, 80 insertions(+), 78 deletions(-) diff --git a/sys/src/cmd/ndb/dblookup.c b/sys/src/cmd/ndb/dblookup.c index b001daec7..4a1dd12b8 100644 --- a/sys/src/cmd/ndb/dblookup.c +++ b/sys/src/cmd/ndb/dblookup.c @@ -316,8 +316,7 @@ dblookup1(char *name, int type, int auth, int ttl) nstrcpy(dname, nt->val, sizeof dname); found = 1; } - if(strcmp(attr, nt->attr) == 0){ - rp = (*f)(t, nt); + if(strcmp(attr, nt->attr) == 0 && (rp = (*f)(t, nt)) != nil){ rp->auth = auth; rp->db = 1; if(ttl) @@ -336,12 +335,11 @@ dblookup1(char *name, int type, int auth, int ttl) /* search whole entry */ for(nt = t; nt; nt = nt->entry) - if(nt->ptr == 0 && strcmp(attr, nt->attr) == 0){ - rp = (*f)(t, nt); + if(nt->ptr == 0 && strcmp(attr, nt->attr) == 0 && (rp = (*f)(t, nt)) != nil){ + rp->auth = auth; rp->db = 1; if(ttl) rp->ttl = ttl; - rp->auth = auth; if(dp == nil) dp = idnlookup(dname, Cin, 1); rp->owner = dp; @@ -358,26 +356,22 @@ dblookup1(char *name, int type, int auth, int ttl) * make various types of resource records from a database entry */ static RR* -addrrr(Ndbtuple *entry, Ndbtuple *pair) +addrrr(Ndbtuple*, Ndbtuple *pair) { RR *rp; - uchar addr[IPaddrlen]; + uchar ip[IPaddrlen]; - USED(entry); - parseip(addr, pair->val); - if(isv4(addr)) - rp = rralloc(Ta); - else - rp = rralloc(Taaaa); - rp->ip = dnlookup(pair->val, Cin, 1); + if(parseip(ip, pair->val) == -1) + return nil; + rp = rralloc(isv4(ip) ? Ta : Taaaa); + rp->ip = ipalookup(ip, Cin, 1); return rp; } static RR* -nullrr(Ndbtuple *entry, Ndbtuple *pair) +nullrr(Ndbtuple*, Ndbtuple *pair) { RR *rp; - USED(entry); rp = rralloc(Tnull); rp->null->data = (uchar*)estrdup(pair->val); rp->null->dlen = strlen((char*)rp->null->data); @@ -389,13 +383,12 @@ nullrr(Ndbtuple *entry, Ndbtuple *pair) * <= 255 byte ones. */ static RR* -txtrr(Ndbtuple *entry, Ndbtuple *pair) +txtrr(Ndbtuple*, Ndbtuple *pair) { RR *rp; Txt *t, **l; int i, len, sofar; - USED(entry); rp = rralloc(Ttxt); l = &rp->txt; rp->txt = nil; @@ -420,11 +413,10 @@ txtrr(Ndbtuple *entry, Ndbtuple *pair) return rp; } static RR* -cnamerr(Ndbtuple *entry, Ndbtuple *pair) +cnamerr(Ndbtuple*, Ndbtuple *pair) { RR *rp; - USED(entry); rp = rralloc(Tcname); rp->host = idnlookup(pair->val, Cin, 1); return rp; @@ -453,11 +445,10 @@ nsrr(Ndbtuple *entry, Ndbtuple *pair) return rp; } static RR* -ptrrr(Ndbtuple *entry, Ndbtuple *pair) +ptrrr(Ndbtuple*, Ndbtuple *pair) { RR *rp; - USED(entry); rp = rralloc(Tns); rp->ptr = dnlookup(pair->val, Cin, 1); return rp; @@ -815,33 +806,29 @@ baddelegation(RR *rp, RR *nsrp, uchar *addr) } int -myaddr(char *addr) +myip(uchar *ip) { char *line, *sp; - char buf[64]; + char buf[Maxpath]; + uchar ipa[IPaddrlen]; Biobuf *bp; if(ipcmp(ipaddr, IPnoaddr) == 0) if(myipaddr(ipaddr, mntpt) < 0) return -1; - snprint(buf, sizeof buf, "%I", ipaddr); - if (strcmp(addr, buf) == 0) { - dnslog("rejecting my ip %s as local dns server", addr); + if(ipcmp(ipaddr, ip) == 0) return 1; - } snprint(buf, sizeof buf, "%s/ipselftab", mntpt); bp = Bopen(buf, OREAD); - if (bp != nil) { - while ((line = Brdline(bp, '\n')) != nil) { + if(bp != nil) { + while((line = Brdline(bp, '\n')) != nil) { line[Blinelen(bp) - 1] = '\0'; - sp = strchr(line, ' '); - if (sp) { + if((sp = strchr(line, ' ')) != nil) { *sp = '\0'; - if (strcmp(addr, line) == 0) { - dnslog("rejecting my ip %s as local dns server", - addr); + if(parseip(ipa, line) != -1 && ipcmp(ipa, ip) == 0) { + Bterm(bp); return 1; } } @@ -851,39 +838,52 @@ myaddr(char *addr) return 0; } -static char *locdns[20]; -static QLock locdnslck; - static void addlocaldnsserver(DN *dp, int class, char *ipaddr, int i) { - int n; - DN *nsdp; - RR *rp; - char buf[32]; uchar ip[IPaddrlen]; + DN *nsdp, *ipdp; + RR *rp, *tp; + int type, n; + char buf[32]; + + if(parseip(ip, ipaddr) == -1 || ipcmp(ip, IPnoaddr) == 0){ + dnslog("rejecting bad ip %s as local dns server", ipaddr); + return; + } /* reject our own ip addresses so we don't query ourselves via udp */ - if (myaddr(ipaddr)) + if(myip(ip)){ + dnslog("rejecting my ip %I as local dns server", ip); return; + } - qlock(&locdnslck); - for (n = 0; n < i && n < nelem(locdns) && locdns[n]; n++) - if (strcmp(locdns[n], ipaddr) == 0) { - dnslog("rejecting duplicate local dns server ip %s", - ipaddr); - qunlock(&locdnslck); - return; + /* A or AAAA record */ + type = isv4(ip) ? Ta : Taaaa; + ipdp = ipalookup(ip, class, 1); + + /* check duplicate ip */ + for(n = 0; n < i; n++){ + snprint(buf, sizeof buf, "local#dns#server%d", n); + nsdp = dnlookup(buf, class, 0); + if(nsdp == nil) + continue; + rp = rrlookup(nsdp, type, NOneg); + for(tp = rp; tp != nil; tp = tp->next){ + if(tp->ip == ipdp){ + dnslog("rejecting duplicate local dns server ip %I", ip); + rrfreelist(rp); + return; + } } - if (n < nelem(locdns)) - if (locdns[n] == nil || ++n < nelem(locdns)) - locdns[n] = strdup(ipaddr); /* remember 1st few local ns */ - qunlock(&locdnslck); + rrfreelist(rp); + } + + snprint(buf, sizeof buf, "local#dns#server%d", i); + nsdp = dnlookup(buf, class, 1); /* ns record for name server, make up an impossible name */ rp = rralloc(Tns); - snprint(buf, sizeof buf, "local#dns#server%d", i); - nsdp = dnlookup(buf, class, 1); rp->host = nsdp; rp->owner = dp; /* e.g., local#dns#servers */ rp->local = 1; @@ -892,12 +892,8 @@ addlocaldnsserver(DN *dp, int class, char *ipaddr, int i) rrattach(rp, Authoritative); /* will not attach rrs in my area */ dnagenever(dp); - /* A or AAAA record */ - if (parseip(ip, ipaddr) >= 0 && isv4(ip)) - rp = rralloc(Ta); - else - rp = rralloc(Taaaa); - rp->ip = dnlookup(ipaddr, class, 1); + rp = rralloc(type); + rp->ip = ipdp; rp->owner = nsdp; rp->local = 1; rp->db = 1; @@ -905,7 +901,7 @@ addlocaldnsserver(DN *dp, int class, char *ipaddr, int i) rrattach(rp, Authoritative); /* will not attach rrs in my area */ dnagenever(nsdp); - dnslog("added local dns server %s at %s", buf, ipaddr); + dnslog("added local dns server %s at %I", buf, ip); } /* @@ -917,7 +913,7 @@ dnsservers(int class) { int i, n; char *p; - char *args[5]; + char *args[16]; Ndbtuple *t, *nt; RR *nsrp; DN *dp; @@ -1208,8 +1204,7 @@ insidens(uchar *ip) for (t = innmsrvs; t != nil; t = t->entry) if (strcmp(t->attr, "ip") == 0) { - parseip(ipa, t->val); - if (memcmp(ipa, ip, sizeof ipa) == 0) + if (parseip(ipa, t->val) != -1 && ipcmp(ipa, ip) == 0) return 1; } return 0; @@ -1224,7 +1219,8 @@ outsidensip(int n, uchar *ip) i = 0; for (t = outnmsrvs; t != nil; t = t->entry) if (strcmp(t->attr, "ip") == 0 && i++ == n) { - parseip(ip, t->val); + if (parseip(ip, t->val) == -1) + return -1; return 0; } return -1; diff --git a/sys/src/cmd/ndb/dn.c b/sys/src/cmd/ndb/dn.c index f5bc103ab..dd566be06 100644 --- a/sys/src/cmd/ndb/dn.c +++ b/sys/src/cmd/ndb/dn.c @@ -233,6 +233,15 @@ idnlookup(char *name, int class, int enter) return dnlookup(name, class, enter); } +DN* +ipalookup(uchar *ip, int class, int enter) +{ + char addr[64]; + + snprint(addr, sizeof(addr), "%I", ip); + return dnlookup(addr, class, enter); +} + static int rrsame(RR *rr1, RR *rr2) { diff --git a/sys/src/cmd/ndb/dnresolve.c b/sys/src/cmd/ndb/dnresolve.c index 3e700e5b6..eddf86ceb 100644 --- a/sys/src/cmd/ndb/dnresolve.c +++ b/sys/src/cmd/ndb/dnresolve.c @@ -922,13 +922,12 @@ static int mydnsquery(Query *qp, int medium, uchar *udppkt, int len) { int rv, nfd; - char conndir[40], addr[128], domain[64]; + char conndir[40], addr[128]; uchar belen[2]; NetConnInfo *nci; rv = -1; - snprint(domain, sizeof(domain), "%I", udppkt); - if (myaddr(domain)) + if (myip(udppkt)) return rv; switch (medium) { case Udp: @@ -958,9 +957,8 @@ mydnsquery(Query *qp, int medium, uchar *udppkt, int len) case Tcp: /* send via TCP & keep fd around for reply */ memmove(qp->tcpip, udppkt, sizeof qp->tcpip); - snprint(addr, sizeof addr, "%s/tcp!%s!dns", - (mntpt && *mntpt) ? mntpt : "/net", - domain); + snprint(addr, sizeof addr, "%s/tcp!%I!dns", + (mntpt && *mntpt) ? mntpt : "/net", udppkt); alarm(10*1000); qp->tcpfd = dial(addr, nil, conndir, &qp->tcpctlfd); alarm(0); @@ -1049,7 +1047,7 @@ xmitquery(Query *qp, int medium, int depth, uchar *obuf, int inns, int len) if((1<nx) > qp->ndest) continue; - if(memcmp(p->a, IPnoaddr, sizeof IPnoaddr) == 0) + if(ipcmp(p->a, IPnoaddr) == 0) continue; /* mistake */ procsetname("udp %sside query to %I/%s %s %s", @@ -1387,7 +1385,7 @@ queryns(Query *qp, int depth, uchar *ibuf, uchar *obuf, ulong waitms, int inns) if(debug) dnslog("queryns got reply from %I", srcip); for(p = qp->dest; p < qp->curdest; p++) - if(memcmp(p->a, srcip, sizeof p->a) == 0) + if(ipcmp(p->a, srcip) == 0) break; if(p >= qp->curdest){ dnslog("response from %I but no destination", srcip); diff --git a/sys/src/cmd/ndb/dns.h b/sys/src/cmd/ndb/dns.h index 32f55d96d..22d20aaa0 100644 --- a/sys/src/cmd/ndb/dns.h +++ b/sys/src/cmd/ndb/dns.h @@ -449,13 +449,12 @@ void dnagedb(void); void dnagenever(DN *); void dnauthdb(void); void dndump(char*); -void dnget(void); void dninit(void); DN* dnlookup(char*, int, int); DN* idnlookup(char*, int, int); +DN* ipalookup(uchar*, int, int); void dnptr(uchar*, uchar*, char*, int, int, int); void dnpurge(void); -void dnput(void); void dnslog(char*, ...); void dnstats(char *file); void* emalloc(int); @@ -501,7 +500,7 @@ RR* dnsservers(int); RR* domainlist(int); int insideaddr(char *dom); int insidens(uchar *ip); -int myaddr(char *addr); +int myip(uchar *ip); int opendatabase(void); int outsidensip(int, uchar *ip);