mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
3559. [func] Check that both forms of Sender Policy Framework
records exist or do not exist. [RT #33355]
This commit is contained in:
parent
e658a6635d
commit
26bb3b7a67
17 changed files with 318 additions and 5 deletions
3
CHANGES
3
CHANGES
|
|
@ -1,3 +1,6 @@
|
|||
3559. [func] Check that both forms of Sender Policy Framework
|
||||
records exist or do not exist. [RT #33355]
|
||||
|
||||
3558. [bug] IXFR of a DLZ stored zone was broken. [RT #33331]
|
||||
|
||||
3557. [bug] Reloading redirect zones was broken. [RT #33292]
|
||||
|
|
|
|||
|
|
@ -294,6 +294,18 @@ configure_zone(const char *vclass, const char *view,
|
|||
zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
if (get_maps(maps, "check-spf", &obj)) {
|
||||
if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
|
||||
zone_options |= DNS_ZONEOPT_CHECKSPF;
|
||||
} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
|
||||
zone_options &= ~DNS_ZONEOPT_CHECKSPF;
|
||||
} else
|
||||
INSIST(0);
|
||||
} else {
|
||||
zone_options |= DNS_ZONEOPT_CHECKSPF;
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
if (get_checknames(maps, &obj)) {
|
||||
if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
|
||||
|
|
|
|||
|
|
@ -155,19 +155,21 @@ main(int argc, char **argv) {
|
|||
if (progmode == progmode_compile) {
|
||||
zone_options |= (DNS_ZONEOPT_CHECKNS |
|
||||
DNS_ZONEOPT_FATALNS |
|
||||
DNS_ZONEOPT_CHECKSPF |
|
||||
DNS_ZONEOPT_CHECKDUPRR |
|
||||
DNS_ZONEOPT_CHECKNAMES |
|
||||
DNS_ZONEOPT_CHECKNAMESFAIL |
|
||||
DNS_ZONEOPT_CHECKWILDCARD);
|
||||
} else
|
||||
zone_options |= DNS_ZONEOPT_CHECKDUPRR;
|
||||
zone_options |= (DNS_ZONEOPT_CHECKDUPRR |
|
||||
DNS_ZONEOPT_CHECKSPF);
|
||||
|
||||
#define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
|
||||
|
||||
isc_commandline_errprint = ISC_FALSE;
|
||||
|
||||
while ((c = isc_commandline_parse(argc, argv,
|
||||
"c:df:hi:jJ:k:L:m:n:qr:s:t:o:vw:DF:M:S:W:"))
|
||||
"c:df:hi:jJ:k:L:m:n:qr:s:t:o:vw:DF:M:S:T:W:"))
|
||||
!= EOF) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
|
|
@ -389,6 +391,18 @@ main(int argc, char **argv) {
|
|||
}
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if (ARGCMP("warn")) {
|
||||
zone_options |= DNS_ZONEOPT_CHECKSPF;
|
||||
} else if (ARGCMP("ignore")) {
|
||||
zone_options &= ~DNS_ZONEOPT_CHECKSPF;
|
||||
} else {
|
||||
fprintf(stderr, "invalid argument to -T: %s\n",
|
||||
isc_commandline_argument);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
if (ARGCMP("warn"))
|
||||
zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@
|
|||
<arg><option>-s <replaceable class="parameter">style</replaceable></option></arg>
|
||||
<arg><option>-S <replaceable class="parameter">mode</replaceable></option></arg>
|
||||
<arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
|
||||
<arg><option>-T <replaceable class="parameter">mode</replaceable></option></arg>
|
||||
<arg><option>-w <replaceable class="parameter">directory</replaceable></option></arg>
|
||||
<arg><option>-D</option></arg>
|
||||
<arg><option>-W <replaceable class="parameter">mode</replaceable></option></arg>
|
||||
|
|
@ -105,6 +106,7 @@
|
|||
<arg><option>-r <replaceable class="parameter">mode</replaceable></option></arg>
|
||||
<arg><option>-s <replaceable class="parameter">style</replaceable></option></arg>
|
||||
<arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
|
||||
<arg><option>-T <replaceable class="parameter">mode</replaceable></option></arg>
|
||||
<arg><option>-w <replaceable class="parameter">directory</replaceable></option></arg>
|
||||
<arg><option>-D</option></arg>
|
||||
<arg><option>-W <replaceable class="parameter">mode</replaceable></option></arg>
|
||||
|
|
@ -419,6 +421,18 @@
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-T <replaceable class="parameter">mode</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Check if Sender Policy Framework records (TXT and SPF)
|
||||
both exist or both don't exist. A warning is issued
|
||||
if they don't match. Possible modes are
|
||||
<command>"warn"</command> (default), <command>"ignore"</command>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>-w <replaceable class="parameter">directory</replaceable></term>
|
||||
<listitem>
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ options {\n\
|
|||
check-names response ignore;\n\
|
||||
check-dup-records warn;\n\
|
||||
check-mx warn;\n\
|
||||
check-spf warn;\n\
|
||||
acache-enable no;\n\
|
||||
acache-cleaning-interval 60;\n\
|
||||
max-acache-size 16M;\n\
|
||||
|
|
|
|||
|
|
@ -1259,6 +1259,17 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||
dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
|
||||
cfg_obj_asboolean(obj));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "check-spf", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS && obj != NULL);
|
||||
if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
|
||||
check = ISC_TRUE;
|
||||
} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
|
||||
check = ISC_FALSE;
|
||||
} else
|
||||
INSIST(0);
|
||||
dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check);
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "zero-no-soa-ttl", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS && obj != NULL);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,21 @@ cmp -s test.changed.db test.out1.db || ret=1
|
|||
mv -f test.orig.db.jnl test.journal
|
||||
$CHECKZONE -D -J test.journal -o test.out2.db test test.orig.db > /dev/null 2>&1 || ret=1
|
||||
cmp -s test.changed.db test.out2.db || ret=1
|
||||
n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking with spf warnings ($n)"
|
||||
ret=0
|
||||
$CHECKZONE example zones/spf.db > test.out1.$n 2>&1 || ret=1
|
||||
$CHECKZONE -T ignore example zones/spf.db > test.out2.$n 2>&1 || ret=1
|
||||
grep "'x.example' found SPF/TXT" test.out1.$n > /dev/null || ret=1
|
||||
grep "'y.example' found SPF/SPF" test.out1.$n > /dev/null || ret=1
|
||||
grep "'example' found SPF/" test.out1.$n > /dev/null && ret=1
|
||||
grep "'x.example' found SPF/" test.out2.$n > /dev/null && ret=1
|
||||
grep "'y.example' found SPF/" test.out2.$n > /dev/null && ret=1
|
||||
grep "'example' found SPF/" test.out2.$n > /dev/null && ret=1
|
||||
n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
|
|
|
|||
21
bin/tests/system/checkzone/zones/spf.db
Normal file
21
bin/tests/system/checkzone/zones/spf.db
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
; Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; Permission to use, copy, modify, and/or distribute this software for any
|
||||
; purpose with or without fee is hereby granted, provided that the above
|
||||
; copyright notice and this permission notice appear in all copies.
|
||||
;
|
||||
; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
; PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
@ 0 IN SOA . . 0 0 0 0 0
|
||||
@ 0 IN NS .
|
||||
@ 0 IN TXT "v=spf1 -all"
|
||||
@ 0 IN SPF "v=spf1 -all"
|
||||
x 0 IN TXT "v=spf1"
|
||||
y 0 IN SPF "v=spf1"
|
||||
y 0 IN TXT "a non spf record"
|
||||
|
|
@ -64,7 +64,7 @@ SUBDIRS="acl additional allow_query addzone autosign builtin
|
|||
dsdigest dscp ecdsa formerr forward glue gost ixfr inline limits
|
||||
logfileconfig lwresd masterfile masterformat metadata
|
||||
notify nsupdate pending pkcs11 redirect resolver rndc rpz
|
||||
rrl rrsetorder rsabigexponent sortlist smartsign staticstub
|
||||
rrl rrsetorder rsabigexponent smartsign sortlist spf staticstub
|
||||
statistics stub tkey tsig tsiggss unknown upforwd verify
|
||||
views wildcard xfer xferquota zonechecks"
|
||||
|
||||
|
|
|
|||
2
bin/tests/system/spf/clean.sh
Normal file
2
bin/tests/system/spf/clean.sh
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
rm -f ns1/named.run
|
||||
rm -f ns1/named.memstats
|
||||
47
bin/tests/system/spf/ns1/named.conf
Normal file
47
bin/tests/system/spf/ns1/named.conf
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
controls { /* empty */ };
|
||||
|
||||
options {
|
||||
query-source address 10.53.0.1;
|
||||
notify-source 10.53.0.1;
|
||||
transfer-source 10.53.0.1;
|
||||
port 5300;
|
||||
pid-file "named.pid";
|
||||
listen-on { 10.53.0.1; };
|
||||
listen-on-v6 { none; };
|
||||
recursion no;
|
||||
notify yes;
|
||||
ixfr-from-differences yes;
|
||||
};
|
||||
|
||||
zone "spf" {
|
||||
type master;
|
||||
file "spf.db";
|
||||
};
|
||||
|
||||
zone "warn" {
|
||||
type master;
|
||||
file "spf.db";
|
||||
check-spf warn;
|
||||
};
|
||||
|
||||
zone "nowarn" {
|
||||
type master;
|
||||
file "spf.db";
|
||||
check-spf ignore;
|
||||
};
|
||||
21
bin/tests/system/spf/ns1/spf.db
Normal file
21
bin/tests/system/spf/ns1/spf.db
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
; Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; Permission to use, copy, modify, and/or distribute this software for any
|
||||
; purpose with or without fee is hereby granted, provided that the above
|
||||
; copyright notice and this permission notice appear in all copies.
|
||||
;
|
||||
; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
; PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
@ 0 IN SOA . . 0 0 0 0 0
|
||||
@ 0 IN NS .
|
||||
@ 0 IN TXT "v=spf1 -all"
|
||||
@ 0 IN SPF "v=spf1 -all"
|
||||
x 0 IN TXT "v=spf1"
|
||||
y 0 IN SPF "v=spf1"
|
||||
y 0 IN TXT "a non spf record"
|
||||
45
bin/tests/system/spf/tests.sh
Normal file
45
bin/tests/system/spf/tests.sh
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
SYSTEMTESTTOP=..
|
||||
. $SYSTEMTESTTOP/conf.sh
|
||||
|
||||
n=1
|
||||
status=0
|
||||
|
||||
echo "I:checking that SPF warnings have been correctly generated ($n)"
|
||||
ret=0
|
||||
|
||||
grep "zone spf/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1
|
||||
grep "'x.spf' found SPF/TXT" ns1/named.run > /dev/null || ret=1
|
||||
grep "'y.spf' found SPF/SPF" ns1/named.run > /dev/null || ret=1
|
||||
grep "'spf' found SPF/" ns1/named.run > /dev/null && ret=1
|
||||
|
||||
grep "zone warn/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1
|
||||
grep "'x.warn' found SPF/TXT" ns1/named.run > /dev/null || ret=1
|
||||
grep "'y.warn' found SPF/SPF" ns1/named.run > /dev/null || ret=1
|
||||
grep "'warn' found SPF/" ns1/named.run > /dev/null && ret=1
|
||||
|
||||
grep "zone nowarn/IN: loaded serial 0" ns1/named.run > /dev/null || ret=1
|
||||
grep "'x.nowarn' found SPF/" ns1/named.run > /dev/null && ret=1
|
||||
grep "'y.nowarn' found SPF/" ns1/named.run > /dev/null && ret=1
|
||||
grep "'nowarn' found SPF/" ns1/named.run > /dev/null && ret=1
|
||||
n=`expr $n + 1`
|
||||
if [ $ret != 0 ]; then echo "I:failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:exit status: $status"
|
||||
exit $status
|
||||
|
|
@ -5343,6 +5343,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
|
|||
<optional> check-mx-cname ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
|
||||
<optional> check-srv-cname ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
|
||||
<optional> check-sibling <replaceable>yes_or_no</replaceable>; </optional>
|
||||
<optional> check-spf ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
|
||||
<optional> allow-new-zones { <replaceable>yes_or_no</replaceable> }; </optional>
|
||||
<optional> allow-notify { <replaceable>address_match_list</replaceable> }; </optional>
|
||||
<optional> allow-query { <replaceable>address_match_list</replaceable> }; </optional>
|
||||
|
|
@ -7212,6 +7213,12 @@ options {
|
|||
checks use <command>named-checkzone</command>).
|
||||
The default is <command>yes</command>.
|
||||
</para>
|
||||
<para>
|
||||
Check that the two forms of Sender Policy Framework
|
||||
records (TXT and SPF) either both exist or both
|
||||
don't exist. Warnings are emitted it they don't
|
||||
and be suppressed with <command>check-spf</command>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
@ -7247,6 +7254,19 @@ options {
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>check-spf</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
When performing integrity checks, check that the
|
||||
two forms of Sender Policy Framwork records (TXT
|
||||
and SPF) both exist or both don't exist and issue
|
||||
a warning if not met. The default is
|
||||
<command>warn</command>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>zero-no-soa-ttl</command></term>
|
||||
<listitem>
|
||||
|
|
@ -10982,6 +11002,7 @@ view "external" {
|
|||
<optional> check-names (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
|
||||
<optional> check-mx (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
|
||||
<optional> check-wildcard <replaceable>yes_or_no</replaceable>; </optional>
|
||||
<optional> check-spf ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
|
||||
<optional> check-integrity <replaceable>yes_or_no</replaceable> ; </optional>
|
||||
<optional> dialup <replaceable>dialup_option</replaceable> ; </optional>
|
||||
<optional> file <replaceable>string</replaceable> ; </optional>
|
||||
|
|
@ -11631,6 +11652,16 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>check-spf</command></term>
|
||||
<listitem>
|
||||
<para>
|
||||
See the description of
|
||||
<command>check-spf</command> in <xref linkend="boolean_options"/>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><command>check-wildcard</command></term>
|
||||
<listitem>
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ typedef enum {
|
|||
#define DNS_ZONEOPT_DNSKEYKSKONLY 0x10000000U /*%< dnssec-dnskey-kskonly */
|
||||
#define DNS_ZONEOPT_CHECKDUPRR 0x20000000U /*%< check-dup-records */
|
||||
#define DNS_ZONEOPT_CHECKDUPRRFAIL 0x40000000U /*%< fatal check-dup-records failures */
|
||||
#define DNS_ZONEOPT_CHECKSPF 0x80000000U /*%< check SPF records */
|
||||
|
||||
#ifndef NOMINUM_PUBLIC
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -2610,6 +2610,30 @@ zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
|
|||
return (ok);
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -2624,7 +2648,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);
|
||||
|
|
@ -2702,7 +2726,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);
|
||||
|
|
@ -2715,6 +2739,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);
|
||||
|
|
|
|||
|
|
@ -549,6 +549,12 @@ static cfg_type_t cfg_type_checkmode = {
|
|||
&cfg_rep_string, &checkmode_enums
|
||||
};
|
||||
|
||||
static const char *warn_enums[] = { "warn", "ignore", NULL };
|
||||
static cfg_type_t cfg_type_warn = {
|
||||
"warn", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
|
||||
&cfg_rep_string, &warn_enums
|
||||
};
|
||||
|
||||
static cfg_tuplefielddef_t checknames_fields[] = {
|
||||
{ "type", &cfg_type_checktype, 0 },
|
||||
{ "mode", &cfg_type_checkmode, 0 },
|
||||
|
|
@ -1588,6 +1594,7 @@ zone_clauses[] = {
|
|||
{ "check-mx", &cfg_type_checkmode, 0 },
|
||||
{ "check-mx-cname", &cfg_type_checkmode, 0 },
|
||||
{ "check-sibling", &cfg_type_boolean, 0 },
|
||||
{ "check-spf", &cfg_type_warn, 0 },
|
||||
{ "check-srv-cname", &cfg_type_checkmode, 0 },
|
||||
{ "check-wildcard", &cfg_type_boolean, 0 },
|
||||
{ "dialup", &cfg_type_dialuptype, 0 },
|
||||
|
|
|
|||
Loading…
Reference in a new issue