Commit Diff
Diff:
0e7d94ac570129566a40f0d5c2138c844ef7c4c0
6f8d6a57a0f2c70b84c06f965027574ff7615972
Commit:
6f8d6a57a0f2c70b84c06f965027574ff7615972
Tree:
ec68a79f1bff41f27941847f29a9a998120f32ca
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Sun May 18 18:47:54 2014 UTC
Message:
* add whitelisting * this mode is based on the filter which is a blacklist. * whitelist assumes everything as denied and opens access to listed ip ranges. * while there fix filtering for tcp6 which was broken
blob - 9aa9bbb263fbcbec746d8a7bc7a80c3cf29f1bd3
blob + a895f4b80b7802738a4553a67adecbcee5bb696c
--- Makefile.freebsd
+++ Makefile.freebsd
@@ -1,6 +1,6 @@
PROG=wildcarddnsd
-SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c axfr.c filter.c ratelimit.c
+SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c axfr.c filter.c ratelimit.c whitelist.c
CFLAGS= -Wall -g -I/usr/local/include/db5/
LDFLAGS= -Wall -g -L/usr/local/lib/db5/
blob - eb87a348ea3d2b9ae0e6785e4f8c90c78b473e4f
blob + 76cee253e3cb44ad130b247e671c50e4fac1ab68
--- Makefile.linux
+++ Makefile.linux
@@ -22,7 +22,8 @@ build:
$(CC) $(CFLAGS) -c axfr.c
$(CC) $(CFLAGS) -c filter.c
$(CC) $(CFLAGS) -c ratelimit.c
- $(CC) $(CFLAGS) -o wildcarddnsd additional.o main.o parse.o reply.o region.o wildcard.o recurse.o bsd-arc4random.o res_random.o log.o axfr.o filter.o ratelimit.o $(LDADD)
+ $(CC) $(CFLAGS) -c whitelist.c
+ $(CC) $(CFLAGS) -o wildcarddnsd additional.o main.o parse.o reply.o region.o wildcard.o recurse.o bsd-arc4random.o res_random.o log.o axfr.o filter.o ratelimit.o whitelist.o $(LDADD)
install:
blob - e20d9ba43fef050435f5c93e74b1e9b12c7a68e4
blob + 5b7e9b6faac3827629d78f627697823caf8c710a
--- Makefile.macosx
+++ Makefile.macosx
@@ -19,7 +19,8 @@ build:
$(CC) $(CFLAGS) -c ratelimit.c
$(CC) $(CFLAGS) -c res_random.c
$(CC) $(CFLAGS) -c bsd-arc4random.c
- $(CC) $(CFLAGS) -o wildcarddnsd additional.o main.o parse.o reply.o region.o wildcard.o log.o recurse.o axfr.o res_random.c bsd-arc4random.o filter.o ratelimit.o $(LDADD)
+ $(CC) $(CFLAGS) -c whitelist.c
+ $(CC) $(CFLAGS) -o wildcarddnsd additional.o main.o parse.o reply.o region.o wildcard.o log.o recurse.o axfr.o res_random.c bsd-arc4random.o filter.o ratelimit.o whitelist.o $(LDADD)
clean:
rm -f *.o wildcarddnsd config.h Makefile
blob - 7f3415e43128d56eb0199a0b0da63607e09e7045
blob + 6f992c2ef3e032293de916c71c5fbb32c6ae723c
--- Makefile.netbsd
+++ Makefile.netbsd
@@ -1,6 +1,6 @@
PROG=wildcarddnsd
-SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c bsd-arc4random.c log.c axfr.c filter.c ratelimit.c
+SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c bsd-arc4random.c log.c axfr.c filter.c ratelimit.c whitelist.c
CFLAGS= -Wall -g -I/usr/pkg/include/db46/
LDFLAGS= -Wall -g -L/usr/pkg/lib -R/usr/pkg/lib
blob - 2530de2465462c07bbda680f0391c396321df12d
blob + edd76b8b81a95207b0935bf6830c82a7b9e5d3e0
--- Makefile.openbsd
+++ Makefile.openbsd
@@ -1,6 +1,6 @@
PROG=wildcarddnsd
-SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c axfr.c filter.c ratelimit.c
+SRCS=main.c parse.y reply.c additional.c region.c wildcard.c recurse.c res_random.c log.c axfr.c filter.c ratelimit.c whitelist.c
#CFLAGS= -DDEBUG -g -Wall
CFLAGS= -Wall -g -I/usr/local/include/db4
blob - f91f1d6861339dea475f45b89fa3b6c2639de4df
blob + 0c99cc84f3a5179014e0c07f0f05a2e41cf8e4ab
--- example8.conf
+++ example8.conf
@@ -16,7 +16,8 @@ options "cool stuff" {
log;
}
-filter "these hosts" {
+whitelist "these hosts" {
+ ::1;
127.0.0.1;
}
blob - 493396456311a5bd13dcd30bcd9d031afcd4cd1a
blob + 9b659875a91ea5e2daa4c1a64a91d9d62bb3388a
--- main.c
+++ main.c
@@ -40,12 +40,14 @@ extern void dolog(int, char *, ...);
extern int find_filter(struct sockaddr_storage *, int);
extern int find_recurse(struct sockaddr_storage *, int);
extern u_int8_t find_region(struct sockaddr_storage *, int);
+extern int find_whitelist(struct sockaddr_storage *, int);
extern int find_wildcard(struct sockaddr_storage *, int);
extern void init_wildcard(void);
extern void init_recurse(void);
extern void init_region(void);
extern void init_filter(void);
extern void init_notifyslave(void);
+extern void init_whitelist(void);
extern void recurseloop(int sp, int *, DB *);
extern void receivelog(char *, int);
extern void reply_a(struct sreply *, DB *);
@@ -126,6 +128,7 @@ extern struct logging logging;
extern int axfrport;
extern int ratelimit;
extern int ratelimit_packets_per_second;
+extern int whitelist;
static int *ptr = NULL;
static int reload = 0;
@@ -169,7 +172,7 @@ static struct tcps {
} *tn1, *tnp, *tntmp;
-static const char rcsid[] = "$Id: main.c,v 1.98 2014/05/18 17:14:05 pjp Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.99 2014/05/18 18:47:54 pjp Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -415,6 +418,7 @@ main(int argc, char *argv[])
init_recurse();
init_region();
init_filter();
+ init_whitelist();
init_notifyslave();
if (parse_file(db, conffile) < 0) {
@@ -1976,6 +1980,7 @@ mainloop(struct cfg *cfg)
int wildcard = 0;
int filter = 0;
int rcheck = 0;
+ int blacklist = 1;
int sp;
int lfd;
@@ -2150,8 +2155,10 @@ mainloop(struct cfg *cfg)
inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, (char *)&address, sizeof(address));
aregion = find_region((struct sockaddr_storage *)sin6, AF_INET6);
wildcard = find_wildcard((struct sockaddr_storage *)sin6, AF_INET6);
- // filter = find_filter((struct sockaddr_storage *)sin6, AF_INET6);
- filter = 0;
+ filter = find_filter((struct sockaddr_storage *)sin6, AF_INET6);
+ if (whitelist) {
+ blacklist = find_whitelist((struct sockaddr_storage *)sin6, AF_INET6);
+ }
} else if (from->sa_family == AF_INET) {
is_ipv6 = 0;
@@ -2161,6 +2168,9 @@ mainloop(struct cfg *cfg)
wildcard = find_wildcard((struct sockaddr_storage *)sin, AF_INET);
aregion = find_region((struct sockaddr_storage *)sin, AF_INET);
filter = find_filter((struct sockaddr_storage *)sin, AF_INET);
+ if (whitelist) {
+ blacklist = find_whitelist((struct sockaddr_storage *)sin, AF_INET);
+ }
} else {
dolog(LOG_INFO, "TCP packet received on descriptor %u interface \"%s\" had weird address family (%u), drop\n", so, cfg->ident[i], from->sa_family);
close(so);
@@ -2174,7 +2184,15 @@ mainloop(struct cfg *cfg)
continue;
}
+ if (whitelist && blacklist == 0) {
+ dolog(LOG_INFO, "TCP connection refused on descriptor %u interface \"%s\" from %s, whitelist policy\n", so, cfg->ident[i], address);
+ close(so);
+ continue;
+ }
+
+
+
/*
* make this socket nonblocking
*/
@@ -2760,6 +2778,9 @@ axfrentry:
aregion = find_region((struct sockaddr_storage *)sin6, AF_INET6);
wildcard = find_wildcard((struct sockaddr_storage *)sin6, AF_INET6);
filter = find_filter((struct sockaddr_storage *)sin6, AF_INET6);
+ if (whitelist) {
+ blacklist = find_whitelist((struct sockaddr_storage *)sin6, AF_INET6);
+ }
if (rflag) {
recursion = find_recurse((struct sockaddr_storage *)sin6, AF_INET6);
recurseheader(&rh, IPPROTO_UDP, (struct sockaddr_storage*)sin6, &sto, AF_INET6);
@@ -2779,6 +2800,10 @@ axfrentry:
aregion = find_region((struct sockaddr_storage *)sin, AF_INET);
wildcard = find_wildcard((struct sockaddr_storage *)sin, AF_INET);
filter = find_filter((struct sockaddr_storage *)sin, AF_INET);
+ if (whitelist) {
+ blacklist = find_whitelist((struct sockaddr_storage *)sin, AF_INET);
+ }
+
if (rflag) {
recursion = find_recurse((struct sockaddr_storage *)sin, AF_INET);
recurseheader(&rh, IPPROTO_UDP, (struct sockaddr_storage*)sin, &sto, AF_INET);
@@ -2823,6 +2848,15 @@ axfrentry:
reply_refused(&sreply);
dolog(LOG_INFO, "UDP connection refused on descriptor %u interface \"%s\" from %s (ttl=%d, region=%d) replying REFUSED, filter policy\n", so, cfg->ident[i], address, received_ttl, aregion);
+ goto drop;
+ }
+
+ if (whitelist && blacklist == 0) {
+
+ build_reply(&sreply, so, buf, len, NULL, from, fromlen, NULL, NULL, aregion, istcp, wildcard, NULL, replybuf);
+ reply_refused(&sreply);
+
+ dolog(LOG_INFO, "UDP connection refused on descriptor %u interface \"%s\" from %s (ttl=%d, region=%d) replying REFUSED, whitelist policy\n", so, cfg->ident[i], address, received_ttl, aregion);
goto drop;
}
blob - c77446c9451f7f317c860fd5eda89101db2bc927
blob + 1c2e8adb2a9cd646f94654128e4aebb8c11e5aed
--- parse.y
+++ parse.y
@@ -34,9 +34,11 @@ extern int insert_axfr(char *, char *);
extern int insert_notifyslave(char *, char *);
extern int insert_filter(char *, char *);
extern int insert_recurse(char *, char *);
+extern int insert_whitelist(char *, char *);
extern int insert_wildcard(char *, char *);
extern void slave_shutdown(void);
+extern int whitelist;
extern int notify;
extern int errno;
extern int debug;
@@ -90,7 +92,7 @@ typedef struct {
int lineno;
} YYSTYPE;
-static const char rcsid[] = "$Id: parse.y,v 1.22 2014/05/18 17:14:05 pjp Exp $";
+static const char rcsid[] = "$Id: parse.y,v 1.23 2014/05/18 18:47:54 pjp Exp $";
static int version = 0;
static int state = 0;
static uint8_t region = 0;
@@ -172,6 +174,7 @@ struct rrtab {
%token VERSION OBRACE EBRACE REGION AXFRFOR RECURSEFOR
%token DOT COLON TEXT WOF INCLUDE ZONE COMMA CRLF
%token ERROR AXFRPORT LOGGING OPTIONS FILTER NOTIFY
+%token WHITELIST
%token <v.string> POUND
%token <v.string> SEMICOLON
@@ -201,6 +204,7 @@ cmd :
| wof CRLF
| axfr CRLF
| notify CRLF
+ | whitelist CRLF
| filter CRLF
| recurse CRLF
| logging
@@ -781,6 +785,58 @@ loggingstatement:
| comment CRLF
;
+/* whitelist "these hosts" { .. } */
+
+whitelist:
+ WHITELIST whitelistlabel whitelistcontent
+ {
+ if ((confstatus & CONFIG_VERSION) != CONFIG_VERSION) {
+ dolog(LOG_INFO, "There must be a version at the top of the first configfile\n");
+ return (-1);
+ }
+ }
+ ;
+
+whitelistlabel:
+ QUOTEDSTRING
+ ;
+
+whitelistcontent:
+ OBRACE whiteliststatements EBRACE
+ | OBRACE CRLF whiteliststatements EBRACE
+ ;
+
+whiteliststatements :
+ whiteliststatements whiteliststatement
+ | whiteliststatement
+ ;
+
+whiteliststatement : ipcidr SEMICOLON CRLF
+ {
+ char prefixlength[INET_ADDRSTRLEN];
+ char *dst;
+
+
+ if ((dst = get_prefixlen($1, (char *)&prefixlength, sizeof(prefixlength))) == NULL) {
+ return (-1);
+ }
+
+ if (insert_whitelist(dst, prefixlength) < 0) {
+ dolog(LOG_ERR, "insert_whitelist, line %d\n", file->lineno);
+ return (-1);
+ }
+
+ if (debug)
+ printf("recurse inserted %s address\n", $1);
+
+ whitelist = 1;
+
+ free (dst);
+ free ($1);
+ }
+ | comment CRLF
+ ;
+
/* filter "these hosts" { .. } */
filter:
@@ -1101,6 +1157,7 @@ struct tab {
struct tab cmdtab[] = {
{ "axfrport", AXFRPORT, 0},
{ "axfr-for", AXFRFOR, STATE_IP },
+ { "whitelist", WHITELIST, STATE_IP },
{ "filter", FILTER, STATE_IP },
{ "include", INCLUDE, 0 },
{ "logging", LOGGING, 0 },
blob - /dev/null
blob + eb62005c3af4cb5ad40c9203125370386676fda3 (mode 644)
--- /dev/null
+++ whitelist.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2014 Peter J. Philipp
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * this file is based on filter.c
+ */
+
+#include "include.h"
+#include "dns.h"
+#include "db.h"
+
+int find_whitelist(struct sockaddr_storage *, int);
+void init_whitelist(void);
+int insert_whitelist(char *, char *);
+
+extern void dolog(int, char *, ...);
+extern in_addr_t getmask(int);
+extern int getmask6(int, struct sockaddr_in6 *);
+
+extern int debug, verbose;
+
+int whitelist = 0; /* whitelist is off by default */
+
+SLIST_HEAD(listhead, whitelistentry) whitelisthead;
+
+static struct whitelistentry {
+ char name[INET6_ADDRSTRLEN];
+ int family;
+ struct sockaddr_storage hostmask;
+ struct sockaddr_storage netmask;
+ u_int8_t prefixlen;
+ SLIST_ENTRY(whitelistentry) whitelist_entry;
+} *wln2, *wlnp;
+
+
+static const char rcsid[] = "$Id: whitelist.c,v 1.1 2014/05/18 18:47:54 pjp Exp $";
+
+/*
+ * INIT_FILTER - initialize the whitelist singly linked list
+ */
+
+void
+init_whitelist(void)
+{
+ SLIST_INIT(&whitelisthead);
+ return;
+}
+
+/*
+ * INSERT_FILTER - insert an address and prefixlen into the whitelist slist
+ */
+
+int
+insert_whitelist(char *address, char *prefixlen)
+{
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ int pnum;
+ int ret;
+
+ pnum = atoi(prefixlen);
+ wln2 = malloc(sizeof(struct whitelistentry)); /* Insert after. */
+
+ if (strchr(address, ':') != NULL) {
+ wln2->family = AF_INET6;
+ sin6 = (struct sockaddr_in6 *)&wln2->hostmask;
+ if ((ret = inet_pton(AF_INET6, address, &sin6->sin6_addr.s6_addr)) != 1)
+ return (-1);
+ sin6->sin6_family = AF_INET6;
+ sin6 = (struct sockaddr_in6 *)&wln2->netmask;
+ sin6->sin6_family = AF_INET6;
+ if (getmask6(pnum, sin6) < 0)
+ return(-1);
+ wln2->prefixlen = pnum;
+ } else {
+
+ wln2->family = AF_INET;
+ sin = (struct sockaddr_in *)&wln2->hostmask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = inet_addr(address);
+ sin = (struct sockaddr_in *)&wln2->netmask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = getmask(pnum);
+ wln2->prefixlen = pnum;
+
+ }
+
+ SLIST_INSERT_HEAD(&whitelisthead, wln2, whitelist_entry);
+
+ return (0);
+}
+
+/*
+ * FIND_FILTER - walk the whitelist list and find the correponding network
+ * if a network matches return 1, if no match is found return
+ * 0.
+ */
+
+int
+find_whitelist(struct sockaddr_storage *sst, int family)
+{
+ struct sockaddr_in *sin, *sin0;
+ struct sockaddr_in6 *sin6, *sin60, *sin61;
+ u_int32_t hostmask, netmask;
+ u_int32_t a;
+#ifdef __amd64
+ u_int64_t *hm[2], *nm[2], *a6[2];
+#else
+ u_int32_t *hm[4], *nm[4], *a6[4];
+#endif
+
+ SLIST_FOREACH(wlnp, &whitelisthead, whitelist_entry) {
+ if (wlnp->family == AF_INET) {
+ if (family != AF_INET)
+ continue;
+ sin = (struct sockaddr_in *)sst;
+ a = sin->sin_addr.s_addr;
+ sin = (struct sockaddr_in *)&wlnp->hostmask;
+ sin0 = (struct sockaddr_in *)&wlnp->netmask;
+ hostmask = sin->sin_addr.s_addr;
+ netmask = sin0->sin_addr.s_addr;
+ if ((hostmask & netmask) == (a & netmask)) {
+ return (1);
+ } /* if hostmask */
+ } else if (wlnp->family == AF_INET6) {
+ if (family != AF_INET6)
+ continue;
+ sin6 = (struct sockaddr_in6 *)sst;
+ sin60 = (struct sockaddr_in6 *)&wlnp->hostmask;
+ sin61 = (struct sockaddr_in6 *)&wlnp->netmask;
+#ifdef __amd64
+ /*
+ * If this is on a 64 bit machine, we'll benefit
+ * by using 64 bit registers, this should make it
+ * a tad faster...
+ */
+ hm[0] = (u_int64_t *)&sin60->sin6_addr.s6_addr;
+ hm[1] = (hm[0] + 1);
+ nm[0] = (u_int64_t *)&sin61->sin6_addr.s6_addr;
+ nm[1] = (nm[0] + 1);
+ a6[0] = (u_int64_t *)&sin6->sin6_addr.s6_addr;
+ a6[1] = (a6[0] + 1);
+ if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
+ ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))) {
+#else
+ hm[0] = (u_int32_t *)&sin60->sin6_addr.s6_addr;
+ hm[1] = (hm[0] + 1); hm[2] = (hm[1] + 1);
+ hm[3] = (hm[2] + 1);
+ nm[0] = (u_int32_t *)&sin61->sin6_addr.s6_addr;
+ nm[1] = (nm[0] + 1); nm[2] = (nm[1] + 1);
+ nm[3] = (nm[2] + 1);
+ a6[0] = (u_int32_t *)&sin6->sin6_addr.s6_addr;
+ a6[1] = (a6[0] + 1); a6[2] = (a6[1] + 1);
+ a6[3] = (a6[2] + 1);
+
+ if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
+ ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))&&
+ ((*hm[2] & *nm[2]) == (*a6[2] & *nm[2]))&&
+ ((*hm[3] & *nm[3]) == (*a6[3] & *nm[3]))) {
+#endif
+
+ return (1);
+ } /* if ip6 address */
+
+ } /* if AF_INET6 */
+ } /* SLIST */
+
+ return (0);
+}
repomaster@centroid.eu