diff --git a/CHANGES b/CHANGES index f4fa76b3f4..2705d14d5c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +1249. [func] named-checkzone will now check if nameservers that + appear to be IP addresses. Available modes "fail", + "warn" (default) and "ignore" the results of the + check. + 1248. [bug] The validator could incorrectly verify an invalid negative proof. diff --git a/bin/check/check-tool.c b/bin/check/check-tool.c index cec63c4a4d..c9bebd0ccf 100644 --- a/bin/check/check-tool.c +++ b/bin/check/check-tool.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check-tool.c,v 1.7 2002/04/02 06:54:00 marka Exp $ */ +/* $Id: check-tool.c,v 1.8 2002/07/19 02:34:57 marka Exp $ */ #include @@ -47,6 +47,7 @@ static const char *dbtype[] = { "rbt" }; int debug = 0; isc_boolean_t nomerge = ISC_TRUE; +unsigned int zone_options = DNS_ZONEOPT_CHECKNS|DNS_ZONEOPT_MANYERRORS; isc_result_t setup_logging(isc_mem_t *mctx, isc_log_t **logp) { @@ -109,7 +110,7 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, CHECK(dns_rdataclass_fromtext(&rdclass, ®ion)); dns_zone_setclass(zone, rdclass); - dns_zone_setoption(zone, DNS_ZONEOPT_MANYERRORS, ISC_TRUE); + dns_zone_setoption(zone, zone_options, ISC_TRUE); dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge); CHECK(dns_zone_load(zone)); diff --git a/bin/check/check-tool.h b/bin/check/check-tool.h index 9a5efc8a6d..85b05bab1b 100644 --- a/bin/check/check-tool.h +++ b/bin/check/check-tool.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check-tool.h,v 1.4 2002/04/02 06:54:02 marka Exp $ */ +/* $Id: check-tool.h,v 1.5 2002/07/19 02:34:58 marka Exp $ */ #ifndef CHECK_TOOL_H #define CHECK_TOOL_H @@ -36,6 +36,7 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, extern int debug; extern isc_boolean_t nomerge; +extern unsigned int zone_options; ISC_LANG_ENDDECLS diff --git a/bin/check/named-checkzone.c b/bin/check/named-checkzone.c index c988a0c63f..f2f29df77c 100644 --- a/bin/check/named-checkzone.c +++ b/bin/check/named-checkzone.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named-checkzone.c,v 1.23 2002/07/11 04:50:36 marka Exp $ */ +/* $Id: named-checkzone.c,v 1.24 2002/07/19 02:34:58 marka Exp $ */ #include @@ -81,7 +81,7 @@ main(int argc, char **argv) { char *classname = classname_in; const char *workdir = NULL; - while ((c = isc_commandline_parse(argc, argv, "c:dijqst:vw:")) != EOF) { + while ((c = isc_commandline_parse(argc, argv, "c:dijn:qst:vw:")) != EOF) { switch (c) { case 'c': classname = isc_commandline_argument; @@ -95,6 +95,18 @@ main(int argc, char **argv) { nomerge = ISC_FALSE; break; + case 'n': + if (!strcmp(isc_commandline_argument, "ignore")) + zone_options &= ~(DNS_ZONEOPT_CHECKNS| + DNS_ZONEOPT_FATALNS); + else if (!strcmp(isc_commandline_argument, "warn")) { + zone_options |= DNS_ZONEOPT_CHECKNS; + zone_options &= ~DNS_ZONEOPT_FATALNS; + } else if (!strcmp(isc_commandline_argument, "fail")) + zone_options |= DNS_ZONEOPT_CHECKNS| + DNS_ZONEOPT_FATALNS; + break; + case 'q': quiet++; break; diff --git a/bin/check/named-checkzone.docbook b/bin/check/named-checkzone.docbook index 6c113ac915..47356c9312 100644 --- a/bin/check/named-checkzone.docbook +++ b/bin/check/named-checkzone.docbook @@ -16,7 +16,7 @@ - WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. --> - + @@ -42,6 +42,7 @@ + zonename @@ -109,6 +110,18 @@ + + -n mode + + + Specify whether NS records should be checked to see if they + are addresses. Possible modes are "fail", + "warn" (default) and + "ignore". + + + + -t directory diff --git a/lib/dns/include/dns/master.h b/lib/dns/include/dns/master.h index c026502b00..be15c38d45 100644 --- a/lib/dns/include/dns/master.h +++ b/lib/dns/include/dns/master.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: master.h,v 1.35 2002/02/21 00:45:11 bwelling Exp $ */ +/* $Id: master.h,v 1.36 2002/07/19 02:34:56 marka Exp $ */ #ifndef DNS_MASTER_H #define DNS_MASTER_H 1 @@ -39,6 +39,10 @@ #define DNS_MASTER_ZONE 0x00000008 /* Loading a zone master file. */ #define DNS_MASTER_HINT 0x00000010 /* Loading a hint master file. */ #define DNS_MASTER_SLAVE 0x00000020 /* Loading a slave master file. */ +#define DNS_MASTER_CHECKNS 0x00000040 /* Check NS records to see if + * they are an address */ +#define DNS_MASTER_FATALNS 0x00000080 /* Treat DNS_MASTER_CHECKNS + * matches as fatal */ ISC_LANG_BEGINDECLS diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h index 3983d74b0d..656098ba7f 100644 --- a/lib/dns/include/dns/result.h +++ b/lib/dns/include/dns/result.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.h,v 1.89 2002/06/17 04:01:32 marka Exp $ */ +/* $Id: result.h,v 1.90 2002/07/19 02:34:56 marka Exp $ */ #ifndef DNS_RESULT_H #define DNS_RESULT_H 1 @@ -121,8 +121,9 @@ #define DNS_R_UNKNOWNFLAG (ISC_RESULTCLASS_DNS + 82) #define DNS_R_EXPECTEDRESPONSE (ISC_RESULTCLASS_DNS + 83) #define DNS_R_NOVALIDDS (ISC_RESULTCLASS_DNS + 84) +#define DNS_R_NSISADDRESS (ISC_RESULTCLASS_DNS + 85) -#define DNS_R_NRESULTS 85 /* Number of results */ +#define DNS_R_NRESULTS 86 /* Number of results */ /* * DNS wire format rcodes. diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 37f6768f29..cef274f2f6 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.115 2002/06/13 07:05:47 marka Exp $ */ +/* $Id: zone.h,v 1.116 2002/07/19 02:34:57 marka Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -46,6 +46,8 @@ typedef enum { #define DNS_ZONEOPT_MANYERRORS 0x00000010U /* return many errors on load */ #define DNS_ZONEOPT_IXFRFROMDIFFS 0x00000020U /* calculate differences */ #define DNS_ZONEOPT_NOMERGE 0x00000040U /* don't merge journal */ +#define DNS_ZONEOPT_CHECKNS 0x00000080U /* check if NS's are addresses */ +#define DNS_ZONEOPT_FATALNS 0x00000100U /* DNS_ZONEOPT_CHECKNS is fatal */ #ifndef NOMINUM_PUBLIC /* diff --git a/lib/dns/master.c b/lib/dns/master.c index f7efb2ff20..fbef5b2227 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: master.c,v 1.141 2002/03/12 04:10:57 marka Exp $ */ +/* $Id: master.c,v 1.142 2002/07/19 02:34:55 marka Exp $ */ #include @@ -780,6 +780,44 @@ limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source, unsigned int line } } +static isc_result_t +check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source, + unsigned long line) +{ + char *tmp = NULL; + isc_result_t result = ISC_R_SUCCESS; + void (*callback)(struct dns_rdatacallbacks *, const char *, ...); + + if ((lctx->options & DNS_MASTER_FATALNS) != 0) + callback = lctx->callbacks->error; + else + callback = lctx->callbacks->warn; + + if (token->type == isc_tokentype_string) { + struct in_addr addr; + struct in6_addr addr6; + + tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token)); + if (tmp == NULL) + return (ISC_R_NOMEMORY); + /* + * Catch both "1.2.3.4" and "1.2.3.4." + */ + if (tmp[strlen(tmp) - 1] == '.') + tmp[strlen(tmp) - 1] = '\0'; + if (inet_aton(tmp, &addr) == 1 || + inet_pton(AF_INET6, tmp, &addr6) == 1) + result = DNS_R_NSISADDRESS; + } + if (result != ISC_R_SUCCESS) + (*callback)(lctx->callbacks, "%s:%lu: NS record '%s' " + "appears to be an address", + source, line, DNS_AS_STR(*token)); + if (tmp != NULL) + isc_mem_free(lctx->mctx, tmp); + return (result); +} + static isc_result_t load(dns_loadctx_t *lctx) { dns_rdataclass_t rdclass; @@ -1422,6 +1460,24 @@ load(dns_loadctx_t *lctx) { rdata = new_rdata; } + /* + * Peek at the NS record. + */ + if (type == dns_rdatatype_ns && + lctx->zclass == dns_rdataclass_in && + (lctx->options & DNS_MASTER_CHECKNS) != 0) { + + GETTOKEN(lctx->lex, 0, &token, ISC_FALSE); + result = check_ns(lctx, &token, source, line); + isc_lex_ungettoken(lctx->lex, &token); + if ((lctx->options & DNS_MASTER_FATALNS) != 0) { + if (MANYERRS(lctx, result)) { + SETRESULT(lctx, result); + } else if (result != ISC_R_SUCCESS) + goto insist_and_cleanup; + } + } + /* * Read rdata contents. */ diff --git a/lib/dns/result.c b/lib/dns/result.c index a65e32c280..66ecd25070 100644 --- a/lib/dns/result.c +++ b/lib/dns/result.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.c,v 1.99 2002/06/17 04:01:25 marka Exp $ */ +/* $Id: result.c,v 1.100 2002/07/19 02:34:56 marka Exp $ */ #include @@ -126,7 +126,9 @@ static const char *text[DNS_R_NRESULTS] = { "already frozen", /* 81 DNS_R_FROZEN */ "unknown flag", /* 82 DNS_R_UNKNOWNFLAG */ "expected a response", /* 83 DNS_R_EXPECTEDRESPONSE */ - "no valid DS" /* 84 DNS_R_NOVALIDDS */ + "no valid DS", /* 84 DNS_R_NOVALIDDS */ + + "NS is an address" /* 85 DNS_R_NSISADDRESS */ }; static const char *rcode_text[DNS_R_NRCODERESULTS] = { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index f648cd3078..4b8017e5bc 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.371 2002/06/19 06:47:22 marka Exp $ */ +/* $Id: zone.c,v 1.372 2002/07/19 02:34:56 marka Exp $ */ #include @@ -1078,6 +1078,10 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) { options = DNS_MASTER_ZONE; if (load->zone->type == dns_zone_slave) options |= DNS_MASTER_SLAVE; + if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNS)) + options |= DNS_MASTER_CHECKNS; + if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_FATALNS)) + options |= DNS_MASTER_FATALNS; result = dns_master_loadfileinc(load->zone->masterfile, dns_db_origin(load->db), dns_db_origin(load->db), @@ -1133,6 +1137,17 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { dns_load_t *load; isc_result_t result; isc_result_t tresult; + unsigned int options; + + options = DNS_MASTER_ZONE; + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) + options |= DNS_MASTER_MANYERRORS; + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) + options |= DNS_MASTER_CHECKNS; + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) + options |= DNS_MASTER_FATALNS; + if (zone->type == dns_zone_slave) + options |= DNS_MASTER_SLAVE; if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) { load = isc_mem_get(zone->mctx, sizeof(*load)); @@ -1164,26 +1179,20 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { goto cleanup; } else result = DNS_R_CONTINUE; - } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) { - dns_rdatacallbacks_t callbacks; - unsigned int options; + } else { + dns_rdatacallbacks_t callbacks; dns_rdatacallbacks_init(&callbacks); result = dns_db_beginload(db, &callbacks.add, &callbacks.add_private); if (result != ISC_R_SUCCESS) return (result); - options = DNS_MASTER_MANYERRORS|DNS_MASTER_ZONE; - if (zone->type == dns_zone_slave) - options |= DNS_MASTER_SLAVE; result = dns_master_loadfile(zone->masterfile, &zone->origin, &zone->origin, zone->rdclass, options, &callbacks, zone->mctx); tresult = dns_db_endload(db, &callbacks.add_private); if (result == ISC_R_SUCCESS) result = tresult; - } else { - result = dns_db_load(db, zone->masterfile); } return (result);