Commit Diff
Diff:
8c24ba133a6485514616fac9b030b1301fbee17c
7fb3593ebe69d6485bdbc43d9eccbf494d47951d
Commit:
7fb3593ebe69d6485bdbc43d9eccbf494d47951d
Tree:
0f8638f4540436d4dc139015521bccf72f1e7db9
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Thu Jul 16 06:35:55 2020 UTC
Message:
check a reply for the question, this makes us even more safer. While there send out labels with the 0x20 bit on random after this internet draft: https://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00 Our system didn't have means of accomodating this so I had to hack the struct question stuff.
blob - a9c5b9e1213e24eda3104a5777bfb65ee43d00ba
blob + df2fe26fbf8df2d71a39596967e79762a391330f
--- ddd-dns.h
+++ ddd-dns.h
@@ -27,7 +27,7 @@
*/
/*
- * $Id: ddd-dns.h,v 1.23 2020/07/14 07:00:18 pjp Exp $
+ * $Id: ddd-dns.h,v 1.24 2020/07/16 06:35:55 pjp Exp $
*/
#ifndef _DNS_H
@@ -99,6 +99,7 @@ struct dns_tsigrr {
/* RFC 1035 - page 28 */
struct dns_question_hdr {
char *name;
+ char *original_name;
u_int namelen;
u_int16_t qtype;
u_int16_t qclass;
@@ -274,6 +275,7 @@ struct question {
struct parsequestion {
char name[DNS_MAXNAME];
+ char original_name[DNS_MAXNAME];
u_int namelen;
u_int16_t qtype;
u_int16_t qclass;
blob - 6d0a4348ca7af9e994c50848bc4efcbd1611102c
blob + b157355fd667c7a81217d221afa21c2dd7596218
--- delphinusdnsd.c
+++ delphinusdnsd.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: delphinusdnsd.c,v 1.128 2020/07/15 20:27:15 pjp Exp $
+ * $Id: delphinusdnsd.c,v 1.129 2020/07/16 06:35:55 pjp Exp $
*/
@@ -2149,7 +2149,7 @@ forwardudp:
break;
}
- memcpy(&sforward->buf, question->hdr->name, question->hdr->namelen);
+ memcpy(&sforward->buf, question->hdr->original_name, question->hdr->namelen);
sforward->buflen = question->hdr->namelen;
memcpy((char *)&sforward->header, buf, sizeof(struct dns_header));
@@ -3639,6 +3639,7 @@ parseloop(struct cfg *cfg, struct imsgbuf *ibuf)
}
memcpy(pq.name, question->hdr->name, question->hdr->namelen);
+ memcpy(pq.original_name, question->hdr->original_name, question->hdr->namelen);
pq.namelen = question->hdr->namelen;
pq.qtype = question->hdr->qtype;
pq.qclass = question->hdr->qclass;
@@ -3705,13 +3706,24 @@ convert_question(struct parsequestion *pq, int authori
return NULL;
}
- q->hdr->name = strdup(pq->name);
+ q->hdr->name = calloc(1, pq->namelen);
if (q->hdr->name == NULL) {
- dolog(LOG_INFO, "strdup: %s\n", strerror(errno));
+ dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
free(q->hdr);
free(q);
return NULL;
}
+ memcpy(q->hdr->name, pq->name, pq->namelen);
+
+ q->hdr->original_name = calloc(1, pq->namelen);
+ if (q->hdr->original_name == NULL) {
+ dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
+ free(q->hdr->name);
+ free(q->hdr);
+ free(q);
+ return NULL;
+ }
+ memcpy(q->hdr->original_name, pq->original_name, pq->namelen);
q->hdr->namelen = pq->namelen;
q->hdr->qtype = pq->qtype;
@@ -3720,6 +3732,8 @@ convert_question(struct parsequestion *pq, int authori
q->converted_name = strdup(pq->converted_name);
if (q->converted_name == NULL) {
dolog(LOG_INFO, "strdup: %s\n", strerror(errno));
+ free(q->hdr->name);
+ free(q->hdr->original_name);
free(q->hdr);
free(q);
return NULL;
blob - b94a84d62f3c987c5aea8044b8be1296069a1ecd
blob + 7a25c7b7d37e0e02c4621654aa9668df5a22d0ad
--- forward.c
+++ forward.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: forward.c,v 1.27 2020/07/15 20:27:15 pjp Exp $
+ * $Id: forward.c,v 1.28 2020/07/16 06:35:55 pjp Exp $
*/
#include <sys/types.h>
@@ -47,6 +47,7 @@
#include <string.h>
#include <errno.h>
#include <syslog.h>
+#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
@@ -98,6 +99,8 @@ struct forwardentry {
SLIST_HEAD(, forwardqueue) fwqhead;
struct forwardqueue {
+ char dnsname[DNS_MAXNAME]; /* the request name */
+ char dnsnamelen; /* the len of dnsname */
uint32_t longid; /* a long identifier */
time_t time; /* time created */
struct sockaddr_storage host; /* remote host to query */
@@ -135,6 +138,8 @@ struct tsig * check_tsig(char *, int, char *);
void fwdparseloop(struct imsgbuf *, struct imsgbuf *, struct cfg *);
void changeforwarder(struct forwardqueue *);
void stirforwarders(void);
+void randomize_dnsname(char *buf, int len);
+void lower_dnsname(char *buf, int len);
extern void dolog(int, char *, ...);
extern void pack(char *, char *, int);
@@ -666,6 +671,7 @@ forwardthis(ddDB *db, struct cfg *cfg, int so, struct
char buf[512];
char replystring[DNS_MAXNAME + 1];
+ char savednsname[DNS_MAXNAME];
static char *replybuf = NULL;
int len, slen;
@@ -745,6 +751,10 @@ forwardthis(ddDB *db, struct cfg *cfg, int so, struct
if (! cache)
goto newqueue;
+
+ /* set our name to lower case for db work */
+ memcpy(&savednsname, sforward->buf, sforward->buflen);
+ lower_dnsname(sforward->buf, sforward->buflen);
/* check cache and expire it, then send if it remains */
if ((count = expire_rr(db, sforward->buf, sforward->buflen,
@@ -768,7 +778,8 @@ forwardthis(ddDB *db, struct cfg *cfg, int so, struct
pack16((char *)&dh->id, sforward->header.id);
p = (char *)&dh[1];
- pack(p, sforward->buf, sforward->buflen);
+ /* make sure we reply as it was given */
+ pack(p, savednsname, sforward->buflen);
p += sforward->buflen;
pack16(p, sforward->type);
p += sizeof(uint16_t);
@@ -793,11 +804,11 @@ forwardthis(ddDB *db, struct cfg *cfg, int so, struct
}
if (sforward->havemac)
- q = build_fake_question(sforward->buf, sforward->buflen,
+ q = build_fake_question(savednsname, sforward->buflen,
sforward->type, sforward->tsigname,
sforward->tsignamelen);
else
- q = build_fake_question(sforward->buf, sforward->buflen,
+ q = build_fake_question(savednsname, sforward->buflen,
sforward->type, NULL, 0);
@@ -885,9 +896,14 @@ forwardthis(ddDB *db, struct cfg *cfg, int so, struct
}
/* create a new queue and send it */
-
newqueue:
+ /*
+ * we're out of cache territory, let's mutilate our
+ * our dns question a little bit...
+ */
+ randomize_dnsname(sforward->buf, sforward->buflen);
+
TAILQ_FOREACH(fw2, &forwardhead, forward_entry) {
if (fw2->active == 1)
break;
@@ -914,6 +930,9 @@ newqueue:
dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
return;
}
+ memcpy(&fwq1->dnsname, sforward->buf, sforward->buflen);
+ fwq1->dnsnamelen = sforward->buflen;
+
fwq1->oldfamily = sforward->family;
fwq1->oldsel = sforward->oldsel;
@@ -1175,6 +1194,17 @@ returnit(ddDB *db, struct cfg *cfg, struct forwardqueu
return;
}
+ if (rlen < (sizeof(struct dns_header) + fwq->dnsnamelen)) {
+ /* the packet size can't fit the question name */
+ dolog(LOG_INFO, "FORWARD returnit, question name can't fit in packet thus it gets dropped\n");
+ return;
+ } else {
+ if (memcasecmp((char *)&dh[1], fwq->dnsname, fwq->dnsnamelen) != 0) {
+ dolog(LOG_INFO, "reply for a question we didn't send, drop\n");
+ return;
+ }
+ }
+
/* send it on to our sandbox */
if (pi == NULL) {
pi = (struct pkt_imsg *)calloc(1, sizeof(struct pkt_imsg));
@@ -2126,4 +2156,58 @@ stirforwarders(void)
count++;
}
+}
+
+/* https://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00 */
+
+void
+randomize_dnsname(char *buf, int len)
+{
+ char randompad[DNS_MAXNAME];
+ char *p, *q;
+ int offset, labellen;
+ int i;
+ char ch;
+
+ if (len > sizeof(randompad))
+ return;
+
+ arc4random_buf(randompad, sizeof(randompad));
+
+ q = &buf[0];
+ for (p = q, offset = 0; *p != 0; p = (p + *p + 1), offset += (*p + 1)) {
+ if (offset > DNS_MAXNAME)
+ return;
+
+ labellen = *p;
+ for (i = 1; i < (1 + labellen); i++) {
+ ch = q[offset + i];
+ q[offset + i] = (randompad[offset + i] & 1) ? toupper(ch) : ch;
+ }
+ }
+
+ return;
+}
+
+void
+lower_dnsname(char *buf, int len)
+{
+ char *p, *q;
+ int offset, labellen;
+ int i;
+ char ch;
+
+ q = &buf[0];
+ for (p = q, offset = 0; *p != 0; p = (p + *p + 1), offset += (*p + 1)) {
+ if (offset > DNS_MAXNAME)
+ return;
+
+ labellen = *p;
+ for (i = 1; i < (1 + labellen); i++) {
+ ch = tolower(q[offset + i]);
+ q[offset + i] = ch;
+ }
+ }
+
+ return;
}
blob - f69ea967d54e9bdbfc2a836e149c034f42edc205
blob + 863550133511760af3e545248f9a31c849654c86
--- util.c
+++ util.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: util.c,v 1.67 2020/07/15 20:27:15 pjp Exp $
+ * $Id: util.c,v 1.68 2020/07/16 06:35:55 pjp Exp $
*/
#include <sys/types.h>
@@ -809,11 +809,20 @@ build_fake_question(char *name, int namelen, u_int16_t
free(q);
return NULL;
}
+ q->hdr->original_name = (void *) calloc(1, q->hdr->namelen);
+ if (q->hdr->original_name == NULL) {
+ dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
+ free(q->hdr->name);
+ free(q->hdr);
+ free(q);
+ return NULL;
+ }
q->converted_name = NULL;
/* fill our name into the dns header struct */
memcpy(q->hdr->name, name, q->hdr->namelen);
+ memcpy(q->hdr->original_name, name, q->hdr->namelen);
q->hdr->qtype = type;
q->hdr->qclass = htons(DNS_CLASS_IN);
@@ -824,6 +833,7 @@ build_fake_question(char *name, int namelen, u_int16_t
if (tsigkeylen > sizeof(q->tsig.tsigkey)) {
free(q->hdr->name);
+ free(q->hdr->original_name);
free(q->hdr);
free(q);
return NULL;
@@ -1021,10 +1031,19 @@ build_question(char *buf, int len, int additional, cha
free(q);
return NULL;
}
+ q->hdr->original_name = (void *)calloc(1, q->hdr->namelen);
+ if (q->hdr->original_name == NULL) {
+ dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
+ free(q->hdr->name);
+ free(q->hdr);
+ free(q);
+ return NULL;
+ }
q->converted_name = (void *)calloc(1, namelen + num_label + 2);
if (q->converted_name == NULL) {
dolog(LOG_INFO, "calloc: %s\n", strerror(errno));
free(q->hdr->name);
+ free(q->hdr->original_name);
free(q->hdr);
free(q);
return NULL;
@@ -1444,8 +1463,9 @@ build_question(char *buf, int len, int additional, cha
/* fill our name into the dns header struct */
memcpy(q->hdr->name, &buf[sizeof(struct dns_header)], q->hdr->namelen);
+ memcpy(q->hdr->original_name, &buf[sizeof(struct dns_header)], q->hdr->namelen);
- /* make it lower case */
+ /* make hdr->name lower case */
for (i = 0; i < q->hdr->namelen; i++) {
int c0;
@@ -1488,6 +1508,7 @@ int
free_question(struct question *q)
{
free(q->hdr->name);
+ free(q->hdr->original_name);
free(q->hdr);
free(q->converted_name);
free(q);
repomaster@centroid.eu