Commit Diff
Diff:
a7ca57e70964cdd7287e8e046931d96dc4b125d6
148580501579cb25deadca5fadd06c65111431fb
Commit:
148580501579cb25deadca5fadd06c65111431fb
Tree:
50927585cf02e91978acb291e98806b98a43c817
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Fri Oct 25 10:24:49 2019 UTC
Message:
act on a notify packet, if we have an rzone configured. Nothing happens yet it still needs to be passed on to an raxfr process which I'll work on soon, but this is out of the way. Fix countless little bugs. works on OpenBSD.
blob - 6d755e5049cf31c7e97a1194b24638b661d1bad3
blob + 1281f8234cb629f6e5d0f0ac5ecc81dc6c56796f
--- ddd-dns.h
+++ ddd-dns.h
@@ -27,7 +27,7 @@
*/
/*
- * $Id: ddd-dns.h,v 1.8 2019/02/24 14:53:02 pjp Exp $
+ * $Id: ddd-dns.h,v 1.9 2019/10/25 10:24:49 pjp Exp $
*/
#ifndef _DNS_H
@@ -258,6 +258,7 @@ struct question {
int rd;
int dnssecok;
int badvers;
+ int notify;
struct tsig tsig;
};
@@ -271,6 +272,7 @@ struct parsequestion {
u_int8_t ednsversion;
int rd;
int dnssecok;
+ int notify;
int badvers;
struct tsig tsig;
int rc; /* return code */
blob - 702d2576e49f6f822a6152e59d177fb9c75c486a
blob + 3b0b37abe79fb928fa34800f842c440d342ab86e
--- delphinusdnsd.c
+++ delphinusdnsd.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: delphinusdnsd.c,v 1.68 2019/09/12 07:24:54 pjp Exp $
+ * $Id: delphinusdnsd.c,v 1.69 2019/10/25 10:24:49 pjp Exp $
*/
@@ -129,6 +129,7 @@ extern int reply_notauth(struct sreply *, ddDB *);
extern int reply_notimpl(struct sreply *, ddDB *);
extern int reply_nxdomain(struct sreply *, ddDB *);
extern int reply_noerror(struct sreply *, ddDB *);
+extern int reply_notify(struct sreply *, ddDB *);
extern int reply_soa(struct sreply *, ddDB *);
extern int reply_mx(struct sreply *, ddDB *);
extern int reply_naptr(struct sreply *, ddDB *);
@@ -156,8 +157,9 @@ extern int free_question(struct question *);
extern struct rbtree * create_rr(ddDB *db, char *name, int len, int type, void *rdata);
extern struct rbtree * find_rrset(ddDB *db, char *name, int len);
extern struct rrset * find_rr(struct rbtree *rbt, u_int16_t rrtype);
-extern int add_rr(struct rbtree *rbt, char *name, int len, u_int16_t rrtype, void *rdata);
-extern int display_rr(struct rrset *rrset);
+extern int add_rr(struct rbtree *, char *, int, u_int16_t, void *);
+extern int display_rr(struct rrset *rrset);
+extern int notifysource(struct question *, struct sockaddr_storage *);
struct question *convert_question(struct parsequestion *);
@@ -240,6 +242,7 @@ struct tcpentry {
extern char *__progname;
extern struct logging logging;
+extern struct rzone *rz;
extern int axfrport;
extern int ratelimit;
extern int ratelimit_packets_per_second;
@@ -1410,7 +1413,7 @@ mainloop(struct cfg *cfg, struct imsgbuf **ibuf)
pid_t pid;
int sel;
- int len, slen;
+ int len, slen = 0;
int is_ipv6;
int i;
int istcp = 1;
@@ -1859,11 +1862,44 @@ axfrentry:
/* goto drop beyond this point should goto out instead */
+ if (question->notify) {
+ if (question->tsig.have_tsig && notifysource(question, (struct sockaddr_storage *)from) &&
+ question->tsig.tsigverified == 1) {
+ dolog(LOG_INFO, "on descriptor %u interface \"%s\" authenticated dns NOTIFY packet from %s, replying NOTIFY\n", so, cfg->ident[i], address);
+ snprintf(replystring, DNS_MAXNAME, "NOTIFY");
+ build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, NULL, replybuf);
+ slen = reply_notify(&sreply, NULL);
+ goto udpout;
+
+ } else if (question->tsig.have_tsig && question->tsig.tsigerrorcode != 0) {
+ dolog(LOG_INFO, "on descriptor %u interface \"%s\" not authenticated dns NOTIFY packet (code = %d) from %s, replying notauth\n", so, cfg->ident[i], question->tsig.tsigerrorcode, address);
+ snprintf(replystring, DNS_MAXNAME, "NOTAUTH");
+ build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, NULL, replybuf);
+ slen = reply_notauth(&sreply, NULL);
+ goto udpout;
+ }
+
+ if (notifysource(question, (struct sockaddr_storage *)from)) {
+ dolog(LOG_INFO, "on descriptor %u interface \"%s\" dns NOTIFY packet from %s, replying NOTIFY\n", so, cfg->ident[i], address);
+ snprintf(replystring, DNS_MAXNAME, "NOTIFY");
+ build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, NULL, replybuf);
+ slen = reply_notify(&sreply, NULL);
+ goto udpout;
+ } else {
+ /* RFC 1996 - 3.10 */
+ dolog(LOG_INFO, "on descriptor %u interface \"%s\" dns NOTIFY packet from %s, NOT in our list of MASTER servers replying DROP\n", so, cfg->ident[i], address);
+ snprintf(replystring, DNS_MAXNAME, "DROP");
+ slen = 0;
+
+ goto udpout;
+ }
+ } /* if question->notify */
+
if (question->tsig.have_tsig && question->tsig.tsigerrorcode != 0) {
dolog(LOG_INFO, "on descriptor %u interface \"%s\" not authenticated dns packet (code = %d) from %s, replying notauth\n", so, cfg->ident[i], question->tsig.tsigerrorcode, address);
snprintf(replystring, DNS_MAXNAME, "NOTAUTH");
build_reply(&sreply, so, buf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, NULL, replybuf);
- reply_notauth(&sreply, NULL);
+ slen = reply_notauth(&sreply, NULL);
goto udpout;
}
/* hack around whether we're edns version 0 */
@@ -1896,6 +1932,7 @@ axfrentry:
/* FALLTHROUGH */
case ERR_DROP:
snprintf(replystring, DNS_MAXNAME, "DROP");
+ slen = 0;
goto udpout;
case ERR_REFUSED:
snprintf(replystring, DNS_MAXNAME, "REFUSED");
@@ -1972,7 +2009,7 @@ axfrentry:
}
snprintf(replystring, DNS_MAXNAME, "DROP");
-
+ slen = 0;
goto udpout;
}
}
@@ -2336,7 +2373,7 @@ tcploop(struct cfg *cfg, struct imsgbuf **ibuf)
{
fd_set rset;
int sel;
- int len, slen, length = 0;
+ int len, slen = 0, length = 0;
int is_ipv6;
int i;
int istcp = 1;
@@ -2760,7 +2797,7 @@ tcploop(struct cfg *cfg, struct imsgbuf **ibuf)
dolog(LOG_INFO, "on TCP descriptor %u interface \"%s\" not authenticated dns packet (code = %d) from %s, replying notauth\n", so, cfg->ident[tcpnp->intidx], question->tsig.tsigerrorcode, tcpnp->address);
snprintf(replystring, DNS_MAXNAME, "NOTAUTH");
build_reply(&sreply, so, pbuf, len, question, from, fromlen, NULL, NULL, aregion, istcp, 0, NULL, replybuf);
- reply_notauth(&sreply, NULL);
+ slen = reply_notauth(&sreply, NULL);
goto tcpout;
}
/* hack around whether we're edns version 0 */
@@ -2777,6 +2814,7 @@ tcploop(struct cfg *cfg, struct imsgbuf **ibuf)
dolog(LOG_INFO, "AXFR connection from %s on interface \"%s\" was not in our axfr acl, drop\n", tcpnp->address, cfg->ident[tcpnp->intidx]);
snprintf(replystring, DNS_MAXNAME, "DROP");
+ slen = 0;
goto tcpout;
}
break;
@@ -2802,6 +2840,7 @@ tcploop(struct cfg *cfg, struct imsgbuf **ibuf)
/* FALLTHROUGH */
case ERR_DROP:
snprintf(replystring, DNS_MAXNAME, "DROP");
+ slen = 0;
goto tcpout;
case ERR_REFUSED:
@@ -2876,6 +2915,7 @@ tcploop(struct cfg *cfg, struct imsgbuf **ibuf)
}
snprintf(replystring, DNS_MAXNAME, "DROP");
+ slen = 0;
goto tcpout;
}
@@ -3210,6 +3250,7 @@ parseloop(struct cfg *cfg, struct imsgbuf **ibuf)
pq.tsig.tsigalglen = question->tsig.tsigalglen;
pq.tsig.tsig_timefudge = question->tsig.tsig_timefudge;
pq.tsig.tsigorigid = question->tsig.tsigorigid;
+ pq.notify = question->notify;
imsg_compose(mybuf, IMSG_PARSEREPLY_MESSAGE, 0, 0, -1, (char *)&pq, sizeof(struct parsequestion));
msgbuf_write(&mybuf->w);
@@ -3291,6 +3332,8 @@ convert_question(struct parsequestion *pq)
q->tsig.tsig_timefudge = pq->tsig.tsig_timefudge;
q->tsig.tsigorigid = pq->tsig.tsigorigid;
+
+ q->notify = pq->notify;
return (q);
}
blob - 4b0f0477be8c6d86c4ad32d6bd79d1e38df1262c
blob + 49cea88d6fa682cccdfc36dc36b27028fe1bd519
--- parse.y
+++ parse.y
@@ -21,7 +21,7 @@
*/
/*
- * $Id: parse.y,v 1.74 2019/07/09 12:24:09 pjp Exp $
+ * $Id: parse.y,v 1.75 2019/10/25 10:24:49 pjp Exp $
*/
%{
@@ -70,6 +70,7 @@
void yyerror(const char *);
int yylex(void);
+extern int memcasecmp(u_char *, u_char *, int);
extern struct rrtab *rrlookup(char *);
extern int base32hex_decode(u_char *, u_char *);
extern void dolog(int, char *, ...);
@@ -135,9 +136,11 @@ static struct file {
SLIST_HEAD(rzones, rzone) rzones = SLIST_HEAD_INITIALIZER(rzones);
struct rzone {
SLIST_ENTRY(rzone) rzone_entry;
+ int active;
char *zonename;
u_int16_t masterport;
char *master;
+ struct sockaddr_storage storage;
char *tsigkey;
char *filename;
} *rz, *rz0;
@@ -233,6 +236,7 @@ int yyparse(void);
static struct rzone * add_rzone(void);
static struct mzone * add_mzone(void);
static int pull_remote_zone(struct rzone *);
+int notifysource(struct question *, struct sockaddr_storage *);
%}
@@ -674,6 +678,7 @@ rzonestatement:
return -1;
}
+ rz->active = 1;
rz->masterport = $2 & 0xffff;
#ifdef __OpenBSD__
@@ -684,6 +689,8 @@ rzonestatement:
|
MASTER ipcidr SEMICOLON CRLF
{
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
char *p;
rz = SLIST_FIRST(&rzones);
@@ -691,6 +698,7 @@ rzonestatement:
return -1;
}
+ rz->active = 1;
p = strdup($2);
if (p == NULL) {
perror("strdup");
@@ -699,6 +707,19 @@ rzonestatement:
rz->master = p;
+ sin = (struct sockaddr_in *)&rz->storage;
+ sin6 = (struct sockaddr_in6 *)&rz->storage;
+
+ if (strchr(rz->master, ':')) {
+ rz->storage.ss_family = AF_INET6;
+ rz->storage.ss_len = 16;
+ inet_pton(AF_INET6, rz->master, &sin6->sin6_addr);
+ } else {
+ rz->storage.ss_family = AF_INET;
+ rz->storage.ss_len = 4;
+ inet_pton(AF_INET, rz->master, &sin->sin_addr.s_addr);
+ }
+
#ifdef __OpenBSD__
if (debug)
printf("at rzone %x, added master server at %s\n", (unsigned int)rz,
@@ -718,6 +739,7 @@ rzonestatement:
return -1;
}
+ rz->active = 1;
p = strdup($2);
if (p == NULL) {
perror("strdup");
@@ -3673,6 +3695,7 @@ add_rzone(void)
lrz->master = NULL;
lrz->tsigkey = NULL;
lrz->filename = NULL;
+ memset(&lrz->storage, 0, sizeof(struct sockaddr_storage));
SLIST_INSERT_HEAD(&rzones, lrz, rzone_entry);
#ifdef __OpenBSD__
@@ -3713,4 +3736,54 @@ add_mzone(void)
SLIST_INSERT_HEAD(&mzones, lmz, mzone_entry);
return (lmz);
+}
+
+int
+notifysource(struct question *q, struct sockaddr_storage *from)
+{
+ char *zone, *tsigkey;
+ int zoneretlen, tsigretlen;
+ struct sockaddr_in *rzs, *fromi = (struct sockaddr_in *)from;
+ struct sockaddr_in6 *rzs6, *fromi6 = (struct sockaddr_in6 *)from;
+
+ SLIST_FOREACH(rz, &rzones, rzone_entry) {
+ if (! rz->active)
+ continue;
+
+ tsigkey = dns_label(rz->tsigkey, &tsigretlen);
+ zone = dns_label(rz->zonename, &zoneretlen);
+
+ /* if we are the right zone, right tsigkey, and right master IP/IP6 */
+ if ((zoneretlen == q->hdr->namelen) &&
+ (memcasecmp(zone, q->hdr->name, zoneretlen) == 0) &&
+ (tsigretlen == q->tsig.tsigkeylen) &&
+ (memcasecmp(tsigkey, q->tsig.tsigkey, tsigretlen) == 0) &&
+ (rz->storage.ss_family == from->ss_family)) {
+ free(tsigkey);
+ free(zone);
+ if (from->ss_family == AF_INET) {
+ /* IPv4 notify */
+ rzs = (struct sockaddr_in *)&rz->storage;
+
+ if (fromi->sin_addr.s_addr == rzs->sin_addr.s_addr) {
+#if 0
+ if (memcmp((void*)&fromi->sin_addr, (void*)&rzs->sin_addr, 4) == 0) {
+#endif
+ return 1;
+ }
+ } else {
+ /* IPv6 notify */
+ rzs6 = (struct sockaddr_in6 *)&rz->storage;
+
+ if (memcmp((void*)&fromi6->sin6_addr,
+ (void*)&rzs6->sin6_addr, 16) == 0)
+ return 1;
+ }
+ } else {
+ free(tsigkey);
+ free(zone);
+ }
+ }
+
+ return 0;
}
blob - dd3bda408521bec90dc9ebd546822561dd0b59ee
blob + 6db1bbe72ece055f45ca54e5f45a0551d5cae166
--- reply.c
+++ reply.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: reply.c,v 1.80 2019/06/06 15:08:00 pjp Exp $
+ * $Id: reply.c,v 1.81 2019/10/25 10:24:49 pjp Exp $
*/
#include <sys/types.h>
@@ -125,6 +125,7 @@ int reply_any(struct sreply *, ddDB *);
int reply_refused(struct sreply *, ddDB *);
int reply_fmterror(struct sreply *, ddDB *);
int reply_notauth(struct sreply *, ddDB *);
+int reply_notify(struct sreply *, ddDB *);
struct rbtree * find_nsec(char *name, int namelen, struct rbtree *, ddDB *db);
int nsec_comp(const void *a, const void *b);
char * convert_name(char *name, int namelen);
@@ -4554,13 +4555,15 @@ reply_notauth(struct sreply *sreply, ddDB *db)
HTONS(odh->query);
- odh->additional = htons(1);
+ odh->additional = 0;
tmplen = additional_tsig(q, reply, replysize, outlen, 0, 0, NULL);
if (tmplen != 0)
outlen = tmplen;
+ odh->additional = htons(1);
+
if (istcp) {
char *tmpbuf;
u_int16_t *plen;
@@ -4587,6 +4590,98 @@ reply_notauth(struct sreply *sreply, ddDB *db)
return (retlen);
}
+/*
+ * REPLY_NOTIFY() - replies a DNS question (*q) on socket (so)
+ *
+ */
+
+int
+reply_notify(struct sreply *sreply, ddDB *db)
+{
+ char *reply = sreply->replybuf;
+ struct dns_header *odh;
+ u_int16_t outlen = 0;
+ u_int16_t tmplen;
+
+ int so = sreply->so;
+ int len = sreply->len;
+ char *buf = sreply->buf;
+ struct sockaddr *sa = sreply->sa;
+ int salen = sreply->salen;
+ int istcp = sreply->istcp;
+ int replysize = 512;
+ int retlen = -1;
+
+ struct question *q = sreply->q;
+
+ if (istcp) {
+ replysize = 65535;
+ }
+
+ memset(reply, 0, replysize);
+
+ odh = (struct dns_header *)&reply[0];
+
+ if (len > replysize) {
+ return (retlen);
+ }
+
+ memset((char *)&odh->query, 0, sizeof(u_int16_t));
+
+#if 0
+ /* XXX is this really needed? */
+ /* copy question to reply */
+ if (istcp)
+ memcpy(&reply[0], &buf[2], sizeof(struct dns_header) + q->hdr->namelen + 4);
+ else
+#endif
+ memcpy(&reply[0], buf, sizeof(struct dns_header) + q->hdr->namelen + 4);
+
+
+ outlen += (sizeof(struct dns_header) + q->hdr->namelen + 4);
+
+
+ SET_DNS_REPLY(odh);
+ SET_DNS_NOTIFY(odh);
+ SET_DNS_AUTHORITATIVE(odh);
+ SET_DNS_RCODE_NOERR(odh);
+
+ HTONS(odh->query);
+
+ if (q->tsig.have_tsig && q->tsig.tsigverified) {
+ odh->additional = 0;
+ tmplen = additional_tsig(q, reply, replysize, outlen, 0, 0, NULL);
+ if (tmplen != 0)
+ outlen = tmplen;
+ odh->additional = htons(1);
+
+ }
+
+ if (istcp) {
+ char *tmpbuf;
+ u_int16_t *plen;
+
+ tmpbuf = malloc(outlen + 2);
+ if (tmpbuf == 0) {
+ dolog(LOG_INFO, "malloc: %s\n", strerror(errno));
+ }
+ plen = (u_int16_t *)tmpbuf;
+ *plen = htons(outlen);
+
+ memcpy(&tmpbuf[2], reply, outlen);
+
+ if ((retlen = send(so, tmpbuf, outlen + 2, 0)) < 0) {
+ dolog(LOG_INFO, "send: %s\n", strerror(errno));
+ }
+ free(tmpbuf);
+ } else {
+ if ((retlen = sendto(so, reply, outlen, 0, sa, salen)) < 0) {
+ dolog(LOG_INFO, "sendto: %s\n", strerror(errno));
+ }
+ }
+
+ return (retlen);
+}
/*
* REPLY_FMTERROR() - replies a DNS question (*q) on socket (so)
*
blob - 5bfb2d714f787135ae127694bd24f9803414f1ef
blob + 5e4e6e13eeb44ad5abd1ae2e42db99ff220c9e19
--- util.c
+++ util.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: util.c,v 1.38 2019/10/15 12:22:45 pjp Exp $
+ * $Id: util.c,v 1.39 2019/10/25 10:24:49 pjp Exp $
*/
#include <sys/types.h>
@@ -1224,6 +1224,13 @@ build_question(char *buf, int len, int additional, cha
/* make note of whether recursion is desired */
q->rd = ((ntohs(hdr->query) & DNS_RECURSE) == DNS_RECURSE);
+
+ /* are we a notify packet? */
+ if ((ntohs(*qtype) == DNS_TYPE_SOA) && (ntohs(*qclass) == DNS_CLASS_IN))
+ q->notify = ((ntohs(hdr->query) & (DNS_NOTIFY | DNS_AUTH)) \
+ == (DNS_NOTIFY | DNS_AUTH));
+ else
+ q->notify = 0;
return (q);
}
repomaster@centroid.eu