]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix race condition dnssec-policy with views
authorMatthijs Mekking <matthijs@isc.org>
Tue, 3 Mar 2020 05:58:45 +0000 (06:58 +0100)
committerMatthijs Mekking <matthijs@isc.org>
Mon, 9 Mar 2020 13:48:17 +0000 (14:48 +0100)
When configuring the same dnssec-policy for two zones with the same
name but in different views, there is a race condition for who will
run the keymgr first. If running sequential only one set of keys will
be created, if running parallel two set of keys will be created.

Lock the kasp when running looking for keys and running the key
manager. This way, for the same zone in different views only one
keyset will be created.

The dnssec-policy does not implement sharing keys between different
zones.

bin/tests/system/kasp/ns4/example1.db.in [new file with mode: 0644]
bin/tests/system/kasp/ns4/example2.db.in [new file with mode: 0644]
bin/tests/system/kasp/ns4/named.conf.in
bin/tests/system/kasp/ns4/setup.sh
bin/tests/system/kasp/tests.sh
lib/dns/kasp.c
lib/dns/zone.c

diff --git a/bin/tests/system/kasp/ns4/example1.db.in b/bin/tests/system/kasp/ns4/example1.db.in
new file mode 100644 (file)
index 0000000..ea4a911
--- /dev/null
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@              IN      SOA  mname1. . (
+                       1       ; serial
+                       20      ; refresh (20 seconds)
+                       20      ; retry (20 seconds)
+                       1814400 ; expire (3 weeks)
+                       3600    ; minimum (1 hour)
+                       )
+
+                       NS      ns4
+ns4                    A       10.53.0.4
+
+view                   TXT     "view1"
diff --git a/bin/tests/system/kasp/ns4/example2.db.in b/bin/tests/system/kasp/ns4/example2.db.in
new file mode 100644 (file)
index 0000000..90004d3
--- /dev/null
@@ -0,0 +1,22 @@
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, You can obtain one at http://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@              IN      SOA  mname1. . (
+                       1       ; serial
+                       20      ; refresh (20 seconds)
+                       20      ; retry (20 seconds)
+                       1814400 ; expire (3 weeks)
+                       3600    ; minimum (1 hour)
+                       )
+
+                       NS      ns4
+ns4                    A       10.53.0.4
+
+view                   TXT     "view2"
index c8d4094f8551642930c860213db51886dbc27997..8d209aef63e7ce231e4059002822b1037d7704b7 100644 (file)
@@ -26,6 +26,16 @@ key "sha256" {
        secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=";
 };
 
+key "keyforview1" {
+       algorithm "hmac-sha1";
+       secret "YPfMoAk6h+3iN8MDRQC004iSNHY=";
+};
+
+key "keyforview2" {
+       algorithm "hmac-sha1";
+       secret "4xILSZQnuO1UKubXHkYUsvBRPu8=";
+};
+
 dnssec-policy "test" {
        keys {
                csk key-directory lifetime 0 algorithm 14;
@@ -115,3 +125,21 @@ view "none" {
                file "none.none.signed.db";
        };
 };
+
+view "example1" {
+       match-clients { key "keyforview1"; };
+
+       zone "example.net" {
+               type master;
+               file "example1.db";
+       };
+};
+
+view "example2" {
+       match-clients { key "keyforview2"; };
+
+       zone "example.net" {
+               type master;
+               file "example2.db";
+       };
+};
index ca830dd0288a04402448d7f1a97e99b90e24380b..4b02fd3fa0a38839e110136dacecf5eb4c9c5924 100644 (file)
@@ -26,3 +26,6 @@ do
        zonefile="${zone}.db"
        cp template.db.in $zonefile
 done
+
+cp example1.db.in example1.db
+cp example2.db.in example2.db
index 30b82679a3bf6859f390d477cb83842b4ad78e53..24bd5f21ef8a36849b85deeb5831a6c52ab9249f 100644 (file)
@@ -28,6 +28,8 @@ TSIG=""
 SHA1="FrSt77yPTFx6hTs4i2tKLB9LmE0="
 SHA224="hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA=="
 SHA256="R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY="
+VIEW1="YPfMoAk6h+3iN8MDRQC004iSNHY="
+VIEW2="4xILSZQnuO1UKubXHkYUsvBRPu8="
 
 ###############################################################################
 # Key properties                                                              #
@@ -1799,6 +1801,7 @@ dnssec_verify
 # ns4/override.none.signed
 # ns5/override.override.unsigned
 # ns5/override.none.unsigned
+# ns4/example.net (both views)
 set_keyrole      "KEY1" "csk"
 set_keylifetime  "KEY1" "0"
 set_keyalgorithm "KEY1" "14" "ECDSAP384SHA384" "384"
@@ -1850,6 +1853,39 @@ check_apex
 check_subdomain
 dnssec_verify
 
+set_keydir "ns4"
+set_zone "example.net"
+set_server "ns4" "10.53.0.4"
+TSIG="hmac-sha1:keyforview1:$VIEW1"
+check_keys
+check_apex
+dnssec_verify
+n=$((n+1))
+# check subdomain
+echo_i "check TXT example.net (view example1) rrset is signed correctly ($n)"
+ret=0
+dig_with_opts "view.${ZONE}" "@${SERVER}" TXT > "dig.out.$DIR.test$n.txt" || log_error "dig view.${ZONE} TXT failed"
+grep "status: NOERROR" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "mismatch status in DNS response"
+grep "view.${ZONE}\..*${DEFAULT_TTL}.*IN.*TXT.*view1" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "missing view.${ZONE} TXT record in response"
+check_signatures TXT "dig.out.$DIR.test$n.txt" "ZSK"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
+TSIG="hmac-sha1:keyforview2:$VIEW2"
+check_keys
+check_apex
+dnssec_verify
+n=$((n+1))
+# check subdomain
+echo_i "check TXT example.net (view example2) rrset is signed correctly ($n)"
+ret=0
+dig_with_opts "view.${ZONE}" "@${SERVER}" TXT > "dig.out.$DIR.test$n.txt" || log_error "dig view.${ZONE} TXT failed"
+grep "status: NOERROR" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "mismatch status in DNS response"
+grep "view.${ZONE}\..*${DEFAULT_TTL}.*IN.*TXT.*view2" "dig.out.$DIR.test$n.txt" > /dev/null || log_error "missing view.${ZONE} TXT record in response"
+check_signatures TXT "dig.out.$DIR.test$n.txt" "ZSK"
+test "$ret" -eq 0 || echo_i "failed"
+status=$((status+ret))
+
 # Clear TSIG.
 TSIG=""
 
index 1d9bbb27f49eb13b7ca5a8a7dab83ff8da4cb874..69c069e5f7018ce44f7eabb069430e707cbc2600 100644 (file)
@@ -90,6 +90,7 @@ destroy(dns_kasp_t *kasp) {
        }
        INSIST(ISC_LIST_EMPTY(kasp->keys));
 
+       isc_mutex_destroy(&kasp->lock);
        isc_mem_free(kasp->mctx, kasp->name);
        isc_mem_putanddetach(&kasp->mctx, kasp, sizeof(*kasp));
 }
index ff02549c78a85186054e16a1abcb05979c916317..04f4b8e74b4dec04c75867f36f477f99fe296348 100644 (file)
@@ -7279,6 +7279,7 @@ signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
                int zsk_count = 0;
                bool approved;
 
+               LOCK(&kasp->lock);
                for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
                     kkey = ISC_LIST_NEXT(kkey, link))
                {
@@ -7289,6 +7290,7 @@ signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
                                zsk_count++;
                        }
                }
+               UNLOCK(&kasp->lock);
 
                if (type == dns_rdatatype_dnskey ||
                    type == dns_rdatatype_cdnskey || type == dns_rdatatype_cds)
@@ -19423,6 +19425,10 @@ zone_rekey(dns_zone_t *zone) {
        kasp = dns_zone_getkasp(zone);
        fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
 
+       if (kasp != NULL) {
+               LOCK(&kasp->lock);
+       }
+
        result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
                                             &keys);
        if (result != ISC_R_SUCCESS) {
@@ -19431,9 +19437,9 @@ zone_rekey(dns_zone_t *zone) {
                           isc_result_totext(result));
        }
 
-       if (kasp && (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND)) {
+       if (kasp != NULL &&
+           (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND)) {
                ttl = dns_kasp_dnskeyttl(kasp);
-
                result = dns_keymgr_run(&zone->origin, zone->rdclass, dir, mctx,
                                        &keys, kasp, now, &nexttime);
                if (result != ISC_R_SUCCESS) {
@@ -19444,6 +19450,10 @@ zone_rekey(dns_zone_t *zone) {
                }
        }
 
+       if (kasp != NULL) {
+               UNLOCK(&kasp->lock);
+       }
+
        if (result == ISC_R_SUCCESS) {
                result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
                                               &zone->origin, ttl, &diff, mctx,