Skip to content

Commit

Permalink
Add keys logging
Browse files Browse the repository at this point in the history
  • Loading branch information
vstakhov committed Mar 20, 2019
1 parent 3f68584 commit 4a943fa
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 43 deletions.
2 changes: 1 addition & 1 deletion contrib/debian/changelog
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ rbldnsd (0.998-1) UNRELEASED; urgency=low

rbldnsd (0.997a-1) unstable; urgency=low

* change the way how `make dist' behaves
* change the way how `make dist' behaves
(no need for a temporary subdir anymore)
* fixed sed expression to determine version number, needed for *BSD

Expand Down
5 changes: 3 additions & 2 deletions rbldnsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1187,18 +1187,19 @@ static struct dnspacket pkt;
static void request(int fd) {
int q, r;
socklen_t salen = sizeof(peer_sa);
struct dnsqinfo qi;

q = recvfrom(fd, (void*)pkt.p_buf, sizeof(pkt.p_buf), 0,
(struct sockaddr *)&peer_sa, &salen);
if (q <= 0) /* interrupted? */
return;

pkt.p_peerlen = salen;
r = replypacket(&pkt, q, zonelist);
r = replypacket(&pkt, q, zonelist, &qi);
if (!r)
return;
if (flog)
logreply(&pkt, flog, flushlog);
logreply(&pkt, flog, flushlog, &qi);

/* finally, send a reply */
while(sendto(fd, (void*)pkt.p_buf, r, 0,
Expand Down
9 changes: 7 additions & 2 deletions rbldnsd.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct dnsqinfo { /* qi */
int qi_ip6valid; /* true if qi_ip6 is valid */
ip4addr_t qi_ip4; /* parsed IP4 address */
ip6oct_t qi_ip6[IP6ADDR_FULL]; /* parsed IP6 address */
void *qi_additional; /* additional pointer depending on tflag */
};

#define PACK32(b,n) ((b)[0]=(n)>>24,(b)[1]=(n)>>16,(b)[2]=(n)>>8,(b)[3]=(n))
Expand Down Expand Up @@ -125,6 +126,9 @@ ds_dumpfn_t(const struct dataset *ds, const unsigned char *odn, FILE *f);
#define NSQUERY_EMPTY 0x040000u
#define NSQUERY_ALWAYS 0x080000u

/* special case for keyed ACL */
#define NSQUERY_KEY 0x0100000u

/* result flags from dataset queryfn */
#define NSQUERY_FOUND 0x01
#define NSQUERY_ADDPEER 0x02
Expand Down Expand Up @@ -289,14 +293,15 @@ int update_zone_ns(struct zone *zone, const struct dsns *dsns, unsigned ttl,
const struct zone *zonelist);

/* parse query and construct a reply to it, return len of answer or 0 */
int replypacket(struct dnspacket *p, unsigned qlen, struct zone *zone);
int replypacket(struct dnspacket *p, unsigned qlen, struct zone *zone,
struct dnsqinfo *qi);
const struct zone *
findqzone(const struct zone *zonelist,
unsigned dnlen, unsigned dnlab, unsigned char *const *const dnlptr,
struct dnsqinfo *qi);

/* log a reply */
void logreply(const struct dnspacket *pkt, FILE *flog, int flushlog);
void logreply(const struct dnspacket *pkt, FILE *flog, int flushlog, const struct dnsqinfo *qi);

/* details of DNS packet structure are in rbldnsd_packet.c */

Expand Down
21 changes: 16 additions & 5 deletions rbldnsd_aclkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@ ds_aclkey_line(struct dataset *ds, char *s, struct dsctx *dsc) {
key.ldn = key_storage;
key.len = tail - s;

if (key.len > DNS_MAXLABEL) {
dslog(LOG_ERR, dsc, "cannot insert value %s to acl keys: too long (> %d chars)",
key.ldn, DNS_MAXLABEL);

return 0;
}

k = kh_put(acl_key_hash, dsd->auth_keys, key, &rrl);

switch(rrl) {
Expand Down Expand Up @@ -222,6 +229,7 @@ int ds_aclkey_query(const struct dataset *ds, struct dnsqinfo *qi,
const char *rr;
khiter_t k;
struct acl_key key;
int add_flags = 0;

if (qi->qi_dnlab <= 1) {
rr = ds->ds_dsd->def_rr;
Expand Down Expand Up @@ -250,15 +258,18 @@ int ds_aclkey_query(const struct dataset *ds, struct dnsqinfo *qi,
/* Also modify qi */
qi->qi_dnlab --;
qi->qi_dnlen0 -= key.len + 1;
add_flags |= NSQUERY_KEY;
/* Zero terminated when parsing */
qi->qi_additional = (void *)(kh_key(ds->ds_dsd->auth_keys, k).ldn);
}
}

switch((unsigned long)rr) {
case 0: return 0;
case RR_IGNORE: return NSQUERY_IGNORE;
case RR_REFUSE: return NSQUERY_REFUSE;
case RR_EMPTY: return NSQUERY_EMPTY;
case RR_PASS: return 0;
case RR_IGNORE: return add_flags|NSQUERY_IGNORE;
case RR_REFUSE: return add_flags|NSQUERY_REFUSE;
case RR_EMPTY: return add_flags|NSQUERY_EMPTY;
case RR_PASS: return add_flags;
}

/* Substitute zone value and handle it further in check_query_overwrites */
Expand All @@ -267,7 +278,7 @@ int ds_aclkey_query(const struct dataset *ds, struct dnsqinfo *qi,
pkt->p_substds = ds;
}

return NSQUERY_ALWAYS;
return add_flags|NSQUERY_ALWAYS;
}

/*definedstype(acl, DSTF_SPECIAL, "Access Control List dataset");*/
Expand Down
76 changes: 43 additions & 33 deletions rbldnsd_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,9 @@ findqzone(const struct zone *zone,
#endif

/* construct reply to a query. */
int replypacket(struct dnspacket *pkt, unsigned qlen, struct zone *zone) {
int replypacket(struct dnspacket *pkt, unsigned qlen, struct zone *zone, struct dnsqinfo *qi) {

struct dnsquery qry; /* query structure */
struct dnsqinfo qi; /* query info structure */
unsigned char *h = pkt->p_buf; /* packet's header */
const struct dslist *dsl;
int found;
Expand Down Expand Up @@ -336,30 +335,30 @@ int replypacket(struct dnspacket *pkt, unsigned qlen, struct zone *zone) {
refuse(DNS_R_REFUSED);
}
switch(qry.q_type) {
case DNS_T_ANY: qi.qi_tflag = NSQUERY_ANY; break;
case DNS_T_A: qi.qi_tflag = NSQUERY_A; break;
case DNS_T_TXT: qi.qi_tflag = NSQUERY_TXT; break;
case DNS_T_NS: qi.qi_tflag = NSQUERY_NS; break;
case DNS_T_SOA: qi.qi_tflag = NSQUERY_SOA; break;
case DNS_T_MX: qi.qi_tflag = NSQUERY_MX; break;
case DNS_T_ANY: qi->qi_tflag = NSQUERY_ANY; break;
case DNS_T_A: qi->qi_tflag = NSQUERY_A; break;
case DNS_T_TXT: qi->qi_tflag = NSQUERY_TXT; break;
case DNS_T_NS: qi->qi_tflag = NSQUERY_NS; break;
case DNS_T_SOA: qi->qi_tflag = NSQUERY_SOA; break;
case DNS_T_MX: qi->qi_tflag = NSQUERY_MX; break;
default:
if (qry.q_type >= DNS_T_TSIG)
refuse(DNS_R_NOTIMPL);
qi.qi_tflag = NSQUERY_OTHER;
qi->qi_tflag = NSQUERY_OTHER;
}
qi.qi_tflag |= found;
qi->qi_tflag |= found;
h[p_f2] = DNS_R_NOERROR;

/* find matching zone */
zone = (struct zone*)
findqzone(zone, qry.q_dnlen, qry.q_dnlab, qry.q_lptr, &qi);
findqzone(zone, qry.q_dnlen, qry.q_dnlab, qry.q_lptr, qi);
if (!zone) /* not authoritative */
refuse(DNS_R_REFUSED);


/* check global ACL key, we can do it merely after zone data has been parsed */
if (g_dsaclkey && g_dsaclkey->ds_stamp) {
found = ds_aclkey_query(g_dsaclkey, &qi, pkt);
found = ds_aclkey_query(g_dsaclkey, qi, pkt);
if (found & NSQUERY_IGNORE) {
do_stats(gstats.q_dropped += 1; gstats.b_in += qlen);
return 0;
Expand All @@ -371,16 +370,16 @@ int replypacket(struct dnspacket *pkt, unsigned qlen, struct zone *zone) {
do_stats(zone->z_stats.b_in += qlen);

if (zone->z_dsacl && zone->z_dsacl->ds_stamp) {
qi.qi_tflag |= ds_acl_query(zone->z_dsacl, pkt);
if (qi.qi_tflag & NSQUERY_IGNORE) {
qi->qi_tflag |= ds_acl_query(zone->z_dsacl, pkt);
if (qi->qi_tflag & NSQUERY_IGNORE) {
do_stats(gstats.q_err += 1);
return 0;
}
}

if (zone->z_dsaclkey && zone->z_dsaclkey->ds_stamp) {
qi.qi_tflag |= ds_aclkey_query(zone->z_dsaclkey, &qi, pkt);
if (qi.qi_tflag & NSQUERY_IGNORE) {
qi->qi_tflag |= ds_aclkey_query(zone->z_dsaclkey, qi, pkt);
if (qi->qi_tflag & NSQUERY_IGNORE) {
do_stats(gstats.q_dropped += 1);
return 0;
}
Expand All @@ -389,23 +388,23 @@ int replypacket(struct dnspacket *pkt, unsigned qlen, struct zone *zone) {
if (!zone->z_stamp) /* do not answer if not loaded */
refuse(DNS_R_SERVFAIL);

if (qi.qi_tflag & NSQUERY_REFUSE)
if (qi->qi_tflag & NSQUERY_REFUSE)
refuse(DNS_R_REFUSED);

if ((found = call_hook(query_access, (pkt->p_peer, zone, &qi)))) {
if ((found = call_hook(query_access, (pkt->p_peer, zone, qi)))) {
if (found < 0) return 0;
refuse(DNS_R_REFUSED);
}

if (qi.qi_dnlab == 0) { /* query to base zone: SOA and NS */
if (qi->qi_dnlab == 0) { /* query to base zone: SOA and NS */

found = NSQUERY_FOUND;

/* NS and SOA with auth=0 will only touch answer section */
if ((qi.qi_tflag & NSQUERY_SOA) && !addrr_soa(pkt, zone, 0))
if ((qi->qi_tflag & NSQUERY_SOA) && !addrr_soa(pkt, zone, 0))
found = 0;
else
if ((qi.qi_tflag & NSQUERY_NS) && !addrr_ns(pkt, zone, 0))
if ((qi->qi_tflag & NSQUERY_NS) && !addrr_ns(pkt, zone, 0))
found = 0;
if (!found) {
pkt->p_cur = pkt->p_sans;
Expand All @@ -419,19 +418,19 @@ int replypacket(struct dnspacket *pkt, unsigned qlen, struct zone *zone) {

/* search the datasets */
for(dsl = zone->z_dsl; dsl; dsl = dsl->dsl_next)
found |= dsl->dsl_queryfn(dsl->dsl_ds, &qi, pkt);
found |= dsl->dsl_queryfn(dsl->dsl_ds, qi, pkt);

if (found & NSQUERY_ADDPEER) {
#ifdef NO_IPv6
addrr_a_txt(pkt, qi.qi_tflag, pkt->p_substrr,
addrr_a_txt(pkt, qi->qi_tflag, pkt->p_substrr,
inet_ntoa(((struct sockaddr_in*)pkt->p_peer)->sin_addr),
pkt->p_substds);
#else
char subst[IPSIZE];
if (getnameinfo(pkt->p_peer, pkt->p_peerlen,
subst, NI_MAXHOST, NULL, 0, NI_NUMERICHOST) != 0)
subst[0] = '\0';
addrr_a_txt(pkt, qi.qi_tflag, pkt->p_substrr, subst, pkt->p_substds);
addrr_a_txt(pkt, qi->qi_tflag, pkt->p_substrr, subst, pkt->p_substds);
#endif
}

Expand All @@ -448,12 +447,12 @@ int replypacket(struct dnspacket *pkt, unsigned qlen, struct zone *zone) {
addrr_soa(pkt, zone, 1); /* add SOA if any to AUTHORITY */
}
else if (zone->z_nns &&
/* (!(qi.qi_tflag & NSQUERY_NS) || qi.qi_dnlab) && */
/* (!(qi->qi_tflag & NSQUERY_NS) || qi->qi_dnlab) && */
!lazy)
addrr_ns(pkt, zone, 1); /* add nameserver records to positive reply */
do_stats(zone->z_stats.q_ok += 1);
}
(void)call_hook(query_result, (pkt->p_peer, zone, &qi, found));
(void)call_hook(query_result, (pkt->p_peer, zone, qi, found));
if (rlen() > DNS_MAXPACKET) { /* add OPT record for long replies */
/* as per parsequery(), we always have 11 bytes for minimal OPT record at
* the end of our reply packet, OR rlen() does not exceed DNS_MAXPACKET */
Expand Down Expand Up @@ -993,8 +992,8 @@ static int version_req(struct dnspacket *pkt, const struct dnsquery *qry) {
return 1;
}

void logreply(const struct dnspacket *pkt, FILE *flog, int flushlog) {
char cbuf[DNS_MAXDOMAIN + IPSIZE + 50];
void logreply(const struct dnspacket *pkt, FILE *flog, int flushlog, const struct dnsqinfo *qi) {
char cbuf[DNS_MAXDOMAIN + IPSIZE + 51 + DNS_MAXLABEL];
char *cp = cbuf;
const unsigned char *const q = pkt->p_sans - 4;

Expand All @@ -1012,11 +1011,22 @@ void logreply(const struct dnspacket *pkt, FILE *flog, int flushlog) {
#endif
*cp++ = ' ';
cp += dns_dntop(pkt->p_buf + p_hdrsize, cp, DNS_MAXDOMAIN);
cp += sprintf(cp, " %s %s: %s/%u/%d\n",
dns_typename(((unsigned)q[0]<<8)|q[1]),
dns_classname(((unsigned)q[2]<<8)|q[3]),
dns_rcodename(pkt->p_buf[p_f2] & pf2_rcode),
pkt->p_buf[p_ancnt2], (int)(pkt->p_cur - pkt->p_buf));
cp += sprintf(cp, " %s %s: %s/%u/%d",
dns_typename(((unsigned) q[0] << 8) | q[1]),
dns_classname(((unsigned) q[2] << 8) | q[3]),
dns_rcodename(pkt->p_buf[p_f2] & pf2_rcode),
pkt->p_buf[p_ancnt2], (int) (pkt->p_cur - pkt->p_buf));

if (qi->qi_tflag & NSQUERY_KEY && qi->qi_additional) {
int len = strlen(qi->qi_additional);

*cp++ = ' ';
memcpy(cp, qi->qi_additional, len);
cp += len;
}

*cp++ = '\n';

if (flushlog)
write(fileno(flog), cbuf, cp - cbuf);
else
Expand Down

0 comments on commit 4a943fa

Please sign in to comment.