diff options
Diffstat (limited to 'lib/dns/zone.c')
-rw-r--r-- | lib/dns/zone.c | 89 |
1 files changed, 85 insertions, 4 deletions
diff --git a/lib/dns/zone.c b/lib/dns/zone.c index a4247ce4..a60ee79b 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -2473,6 +2473,30 @@ zone_check_dup(dns_zone_t *zone, dns_db_t *db) { } static isc_boolean_t +isspf(const dns_rdata_t *rdata) { + char buf[1024]; + const unsigned char *data = rdata->data; + unsigned int rdl = rdata->length, i = 0, tl, len; + + while (rdl > 0U) { + len = tl = *data; + ++data; + --rdl; + INSIST(tl <= rdl); + if (len > sizeof(buf) - i - 1) + len = sizeof(buf) - i - 1; + memcpy(buf + i, data, len); + i += len; + data += tl; + rdl -= tl; + } + buf[i] = 0; + if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) + return (ISC_TRUE); + return (ISC_FALSE); +} + +static isc_boolean_t integrity_checks(dns_zone_t *zone, dns_db_t *db) { dns_dbiterator_t *dbiterator = NULL; dns_dbnode_t *node = NULL; @@ -2486,7 +2510,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) { dns_name_t *name; dns_name_t *bottom; isc_result_t result; - isc_boolean_t ok = ISC_TRUE; + isc_boolean_t ok = ISC_TRUE, have_spf, have_txt; dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); @@ -2564,7 +2588,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) { result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv, 0, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) - goto next; + goto checkspf; result = dns_rdataset_first(&rdataset); while (result == ISC_R_SUCCESS) { dns_rdataset_current(&rdataset, &rdata); @@ -2577,6 +2601,50 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) { } dns_rdataset_disassociate(&rdataset); + checkspf: + /* + * Check if there is a type TXT spf record without a type SPF + * RRset being present. + */ + if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) + goto next; + if (zone->rdclass != dns_rdataclass_in) + goto next; + have_spf = have_txt = ISC_FALSE; + result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf, + 0, 0, &rdataset, NULL); + if (result == ISC_R_SUCCESS) { + dns_rdataset_disassociate(&rdataset); + have_spf = ISC_TRUE; + } + result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt, + 0, 0, &rdataset, NULL); + if (result != ISC_R_SUCCESS) + goto notxt; + result = dns_rdataset_first(&rdataset); + while (result == ISC_R_SUCCESS) { + dns_rdataset_current(&rdataset, &rdata); + have_txt = isspf(&rdata); + dns_rdata_reset(&rdata); + if (have_txt) + break; + result = dns_rdataset_next(&rdataset); + } + dns_rdataset_disassociate(&rdataset); + + notxt: + if (have_spf != have_txt) { + char namebuf[DNS_NAME_FORMATSIZE]; + const char *found = have_txt ? "TXT" : "SPF"; + const char *need = have_txt ? "SPF" : "TXT"; + + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found SPF/%s " + "record but no SPF/%s record found, add " + "matching type %s record", namebuf, found, + need, need); + } + next: dns_db_detachnode(db, &node); result = dns_dbiterator_next(dbiterator); @@ -12183,6 +12251,7 @@ zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, va_list ap; char message[4096]; int level = ISC_LOG_DEBUG(debuglevel); + const char *zstr; if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE) return; @@ -12190,9 +12259,21 @@ zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, va_start(ap, fmt); vsnprintf(message, sizeof(message), fmt, ap); va_end(ap); + + switch (zone->type) { + case dns_zone_key: + zstr = "managed-keys-zone"; + break; + case dns_zone_redirect: + zstr = "redirect-zone"; + break; + default: + zstr = "zone"; + } + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, - level, "%s: %s %s: %s", me, zone->type != dns_zone_key ? - "zone" : "managed-keys-zone", zone->strnamerd, message); + level, "%s: %s %s: %s", me, zstr, zone->strnamerd, + message); } static int |