diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2017-08-12 00:24:14 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2017-08-12 00:24:14 +0000 |
commit | 417f5b172035797439150c2b3651c20ece0ceb3a (patch) | |
tree | 753a98110c26aa49142f768725cb1200f62fe263 /usr.sbin/rebound/rebound.c | |
parent | cf926db5854f963bfb82d1ca153c2891c5b6d230 (diff) |
stop pretending that qnames are always strings. treat everything as a
dname always.
Diffstat (limited to 'usr.sbin/rebound/rebound.c')
-rw-r--r-- | usr.sbin/rebound/rebound.c | 59 |
1 files changed, 29 insertions, 30 deletions
diff --git a/usr.sbin/rebound/rebound.c b/usr.sbin/rebound/rebound.c index a04f99ce88b..782f735f622 100644 --- a/usr.sbin/rebound/rebound.c +++ b/usr.sbin/rebound/rebound.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rebound.c,v 1.89 2017/07/19 22:51:30 tedu Exp $ */ +/* $OpenBSD: rebound.c,v 1.90 2017/08/12 00:24:13 tedu Exp $ */ /* * Copyright (c) 2015 Ted Unangst <tedu@openbsd.org> * @@ -164,23 +164,23 @@ cachecmp(struct dnscache *c1, struct dnscache *c2) RB_GENERATE_STATIC(cachetree, dnscache, cachenode, cachecmp) static void -lowercase(unsigned char *s) +lowercase(unsigned char *s, size_t len) { - while (*s) { + while (len--) { *s = tolower(*s); s++; } } static void -randomcase(unsigned char *s) +randomcase(unsigned char *s, size_t len) { unsigned char bits[NAMELEN / 8], *b; u_int i = 0; - arc4random_buf(bits, (strlen(s) + 7) / 8); + arc4random_buf(bits, (len + 7) / 8); b = bits; - while (*s) { + while (len--) { *s = (*b & (1 << i)) ? toupper(*s) : tolower(*s); s++; i++; @@ -275,20 +275,14 @@ adjustttl(struct dnscache *ent) } static struct dnscache * -cachelookup(struct dnspacket *dnsreq, size_t reqlen) +cachelookup(struct dnspacket *dnsreq, size_t reqlen, size_t namelen) { struct dnscache *hit, key; unsigned char origname[NAMELEN]; uint16_t origid; - size_t namelen; - if (ntohs(dnsreq->qdcount) != 1) - return NULL; - - namelen = strlcpy(origname, dnsreq->qname, sizeof(origname)); - if (namelen >= sizeof(origname)) - return NULL; - lowercase(dnsreq->qname); + memcpy(origname, dnsreq->qname, namelen); + lowercase(dnsreq->qname, namelen); origid = dnsreq->id; dnsreq->id = 0; @@ -304,7 +298,7 @@ cachelookup(struct dnspacket *dnsreq, size_t reqlen) cachehits += 1; } - memcpy(dnsreq->qname, origname, namelen + 1); + memcpy(dnsreq->qname, origname, namelen); dnsreq->id = origid; return hit; } @@ -350,8 +344,9 @@ newrequest(int ud, struct sockaddr *remoteaddr) struct request *req; uint8_t buf[65536]; struct dnspacket *dnsreq; - struct dnscache *hit; + struct dnscache *hit = NULL; size_t r; + size_t namelen = 0; dnsreq = (struct dnspacket *)buf; @@ -361,14 +356,18 @@ newrequest(int ud, struct sockaddr *remoteaddr) return NULL; if (ntohs(dnsreq->qdcount) == 1) { /* some more checking */ - if (!memchr(dnsreq->qname, '\0', r - sizeof(struct dnspacket))) + namelen = dnamelen(dnsreq->qname, r - sizeof(struct dnspacket)); + if (namelen > r - sizeof(struct dnspacket)) + return NULL; + if (namelen > NAMELEN) return NULL; + hit = cachelookup(dnsreq, r, namelen); } conntotal += 1; - if ((hit = cachelookup(dnsreq, r))) { + if (hit) { hit->resp->id = dnsreq->id; - memcpy(hit->resp->qname, dnsreq->qname, strlen(hit->resp->qname) + 1); + memcpy(hit->resp->qname, dnsreq->qname, namelen); sendto(ud, hit->resp, hit->resplen, 0, &from.a, fromlen); return NULL; } @@ -389,12 +388,9 @@ newrequest(int ud, struct sockaddr *remoteaddr) req->reqid = randomid(); dnsreq->id = req->reqid; if (ntohs(dnsreq->qdcount) == 1) { - size_t namelen; - namelen = strlcpy(req->origname, dnsreq->qname, sizeof(req->origname)); - if (namelen >= sizeof(req->origname)) - goto fail; - randomcase(dnsreq->qname); - memcpy(req->newname, dnsreq->qname, namelen + 1); + memcpy(req->origname, dnsreq->qname, namelen); + randomcase(dnsreq->qname, namelen); + memcpy(req->newname, dnsreq->qname, namelen); hit = calloc(1, sizeof(*hit)); if (hit) { @@ -403,7 +399,7 @@ newrequest(int ud, struct sockaddr *remoteaddr) memcpy(hit->req, dnsreq, r); hit->reqlen = r; hit->req->id = 0; - lowercase(hit->req->qname); + lowercase(hit->req->qname, namelen); } else { free(hit); hit = NULL; @@ -498,11 +494,14 @@ sendreply(struct request *req) resp->id = req->clientid; if (ntohs(resp->qdcount) == 1) { /* some more checking */ - if (!memchr(resp->qname, '\0', r - sizeof(struct dnspacket))) + size_t namelen = dnamelen(resp->qname, r - sizeof(struct dnspacket)); + if (namelen > r - sizeof(struct dnspacket)) + return; + if (namelen > NAMELEN) return; - if (strcmp(resp->qname, req->newname) != 0) + if (memcmp(resp->qname, req->newname, namelen) != 0) return; - memcpy(resp->qname, req->origname, strlen(resp->qname) + 1); + memcpy(resp->qname, req->origname, namelen); } sendto(req->client, buf, r, 0, &req->from.a, req->fromlen); if ((ent = req->cacheent)) { |