Commit Diff
Diff:
9d8a2e59b12881b4615f17410fc40b3728ce45e2
07e7314d36a1a18e4592260501076ee66695f777
Commit:
07e7314d36a1a18e4592260501076ee66695f777
Tree:
f448199fe577e9daf9b8bc56a48c28a45d4a31b0
Author:
pjp <pjp@delphinusdns.org>
Committer:
pjp <pjp@delphinusdns.org>
Date:
Sun Jul 26 17:08:14 2020 UTC
Message:
prevent zones from being poisoned in an AXFR, see here: https://cr.yp.to/djbdns/axfr-notes.html (skip to Poison in a zone) This was tested on my test zone dtschland.eu, on OpenBSD/amd64
blob - 4e529820440e591b040e42b891a55d3780ba0061
blob + 216c5b6526c6e1b009533c7648c34f4bc61ac78d
--- query.c
+++ query.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: query.c,v 1.10 2020/07/26 16:17:10 pjp Exp $
+ * $Id: query.c,v 1.11 2020/07/26 17:08:14 pjp Exp $
*/
#include <sys/types.h>
@@ -160,7 +160,7 @@ extern int raxfr_ds(FILE *, u_char *, u_char *, u_char
extern int raxfr_sshfp(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
extern u_int16_t raxfr_skip(FILE *, u_char *, u_char *);
extern int raxfr_soa(FILE *, u_char *, u_char *, u_char *, struct soa *, int, u_int32_t, u_int16_t, HMAC_CTX *);
-extern int raxfr_peek(FILE *, u_char *, u_char *, u_char *, int *, int, u_int16_t *, u_int32_t, HMAC_CTX *);
+extern int raxfr_peek(FILE *, u_char *, u_char *, u_char *, int *, int, u_int16_t *, u_int32_t, HMAC_CTX *, char *, int);
extern int memcasecmp(u_char *, u_char *, int);
extern int tsig_pseudoheader(char *, uint16_t, time_t, HMAC_CTX *);
@@ -662,7 +662,7 @@ lookup_name(FILE *f, int so, char *zonename, u_int16_t
skip:
- if ((rrlen = raxfr_peek(f, p, estart, end, &rrtype, 0, &rdlen, format, NULL)) < 0) {
+ if ((rrlen = raxfr_peek(f, p, estart, end, &rrtype, 0, &rdlen, format, NULL, name, zonelen)) < 0) {
fprintf(stderr, "not a SOA reply, or ERROR\n");
return -1;
}
blob - d8dc95eb561581fb1f6179c17fde9d578079aaee
blob + d927168780237f8a546dd675db42cb89cccd47b6
--- raxfr.c
+++ raxfr.c
@@ -26,7 +26,7 @@
*
*/
/*
- * $Id: raxfr.c,v 1.57 2020/07/26 16:17:10 pjp Exp $
+ * $Id: raxfr.c,v 1.58 2020/07/26 17:08:14 pjp Exp $
*/
#include <sys/types.h>
@@ -118,7 +118,7 @@ int raxfr_naptr(FILE *, u_char *, u_char *, u_char *,
int raxfr_soa(FILE *, u_char *, u_char *, u_char *, struct soa *, int, u_int32_t, u_int16_t, HMAC_CTX *);
u_int16_t raxfr_skip(FILE *, u_char *, u_char *);
-int raxfr_peek(FILE *, u_char *, u_char *, u_char *, int *, int, u_int16_t *, u_int32_t, HMAC_CTX *);
+int raxfr_peek(FILE *, u_char *, u_char *, u_char *, int *, int, u_int16_t *, u_int32_t, HMAC_CTX *, char *, int);
int raxfr_tsig(FILE *f, u_char *p, u_char *estart, u_char *end, struct soa *mysoa, u_int16_t rdlen, HMAC_CTX *ctx, char *, int);
@@ -177,7 +177,9 @@ extern uint32_t unpack32(char *);
extern uint16_t unpack16(char *);
extern void unpack(char *, char *, int);
+extern int dn_contains(char *, int, char *, int);
+
/* The following alias helps with bounds checking all input, needed! */
#define BOUNDS_CHECK(cur, begin, rdlen, end) do { \
@@ -213,7 +215,7 @@ static struct raxfr_logic supported[] = {
int
-raxfr_peek(FILE *f, u_char *p, u_char *estart, u_char *end, int *rrtype, int soacount, u_int16_t *rdlen, u_int32_t format, HMAC_CTX *ctx)
+raxfr_peek(FILE *f, u_char *p, u_char *estart, u_char *end, int *rrtype, int soacount, u_int16_t *rdlen, u_int32_t format, HMAC_CTX *ctx, char *zonename, int zonelen)
{
int rrlen;
char *save;
@@ -239,6 +241,7 @@ raxfr_peek(FILE *f, u_char *p, u_char *estart, u_char
if ((q + 2) > end)
return -1;
+
rtype = unpack16(q);
q += 2;
@@ -278,6 +281,17 @@ raxfr_peek(FILE *f, u_char *p, u_char *estart, u_char
return -1;
}
+ /* check for poison */
+ if (!dn_contains(expand, elen, zonename, zonelen)) {
+ char *humanzone;
+
+ humanzone = convert_name(zonename, zonelen);
+ dolog(LOG_INFO, "possible poison in AXFR, %s not part of %s", humanname, humanzone);
+ free(humanname);
+ free(humanzone);
+ return -1;
+ }
+
hightype = get_dns_type(ntohs(rtype), 0);
for (i = 0; i < strlen(hightype); i++)
@@ -2154,7 +2168,7 @@ get_remote_soa(struct rzone *rzone)
for (i = answers; i > 0; i--) {
- if ((rrlen = raxfr_peek(f, p, estart, end, &rrtype, 0, &rdlen, format, (dotsig == 1) ? ctx : NULL)) < 0) {
+ if ((rrlen = raxfr_peek(f, p, estart, end, &rrtype, 0, &rdlen, format, (dotsig == 1) ? ctx : NULL, name, zonelen)) < 0) {
dolog(LOG_INFO, "not a SOA reply, or ERROR\n");
close(so);
free(reply); free(dupreply);
blob - b8d92cfd231f5aa2e18bcbf33723cfd54dfcefb6
blob + 4bae4719fdd09df4e096e75e81ae4f4ae8d660a2
--- util.c
+++ util.c
@@ -27,7 +27,7 @@
*/
/*
- * $Id: util.c,v 1.78 2020/07/26 16:17:10 pjp Exp $
+ * $Id: util.c,v 1.79 2020/07/26 17:08:14 pjp Exp $
*/
#include <sys/types.h>
@@ -164,7 +164,7 @@ extern int raxfr_hinfo(FILE *, u_char *, u_char *, u_c
extern int raxfr_sshfp(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *);
extern u_int16_t raxfr_skip(FILE *, u_char *, u_char *);
extern int raxfr_soa(FILE *, u_char *, u_char *, u_char *, struct soa *, int, u_int32_t, u_int16_t, HMAC_CTX *);
-extern int raxfr_peek(FILE *, u_char *, u_char *, u_char *, int *, int, u_int16_t *, u_int32_t, HMAC_CTX *);
+extern int raxfr_peek(FILE *, u_char *, u_char *, u_char *, int *, int, u_int16_t *, u_int32_t, HMAC_CTX *, char *, int);
extern int raxfr_tsig(FILE *, u_char *, u_char *, u_char *, struct soa *, u_int16_t, HMAC_CTX *, char *, int);
extern char *convert_name(char *, int);
@@ -2147,7 +2147,7 @@ lookup_axfr(FILE *f, int so, char *zonename, struct so
char mac[32];
elen = 0;
- if ((rrlen = raxfr_peek(f, p, estart, end, &rrtype, soacount, &rdlen, format, ctx)) < 0) {
+ if ((rrlen = raxfr_peek(f, p, estart, end, &rrtype, soacount, &rdlen, format, ctx, name, zonelen)) < 0) {
fprintf(stderr, "not a SOA reply, or ERROR\n");
return -1;
}
repomaster@centroid.eu