Compare commits

..
Author SHA1 Message Date
Evan Hunt 14271bf4e2 fixup! fixup! refactor validated() 2025-03-14 18:29:48 -07:00
Evan Hunt db6e91497c fixup! split out some functionality in cache_name() 2025-03-14 18:29:48 -07:00
Evan Hunt b735f2e821 fixup! refactor validated() 2025-03-14 18:29:48 -07:00
Evan Hunt e39d265a99 refactor validated()
- there was special-case code in validated() to handle the results
  of a validator started by a CD=1 query. since that never happens,
  the code has been removed.
- the section of code that handles opportunistic caching of
  validated SOA, NS and NSEC data has been split out to a separate
  function.
- the number of goto statements has been reduced considerably.
2025-03-14 18:29:48 -07:00
Evan Hunt 8f03f31106 split out helper functions
- fctx_setresult() sets the event result in a fetch response
  according to the rdataset being returned - DNS_R_NCACHENXDOMAIN or
  DNS_R_NXRRSET for negative responses, ISC_R_SUCCESS, DNS_R_CNAME,
  or DNS_R_DNAME for positive ones.
- cache_rrset() looks up a node and adds an rdataset.
- delete_rrset() looks up a node and removes rdatasets of a specified
  type and, optionally, the associated signatures.
- gettrust() returns the trust level of an rdataset, or dns_trust_none
  if the rdataset is NULL or not associated.
- getrrsig() scans the rdatasets associated with a name for the
  RRSIG covering a given type.
2025-03-14 18:29:48 -07:00
Evan Hunt d3d981f38e further subdivide caching functions
rctx_cacherdataset() has been split into two functions:
- rctx_cache_secure() starts validation for rdatasets
  that need it; they are then cached by the validator
  completion callback validated()
- rctx_cache_insecure() caches rdatasets immediately; it
  is called when validation is disabled or the data
  to be cached is glue.
2025-03-14 18:29:48 -07:00
Evan Hunt 6c291971db rename and refactor cache_name() and related functions
- renamed cache_message() to rctx_cachemessage()
- renamed cache_name() to rctx_cachename()
- merged ncache_message() into rctx_ncache()
- split out a new function, rctx_cacherdataset(), which is
  called by rctx_cachename() in a loop to process each of
  the rdatasets associated with the name.
2025-03-14 18:29:48 -07:00
Evan Hunt d61dc02a7c reduce code duplication around findnoqname()
every call to findnoqname() was followed by a call to
dns_rdataset_addnoqname(). we can move that call into
findnoqname() itself, and simplify the calling functions
a bit.
2025-03-14 18:29:48 -07:00
Evan Hunt 503c7a86fe set ANSWERSIG flag when processing ANY responses
previously, rctx_answer_any() set the ANSWER flag for all
rdatasets in the answer section; it now sets ANSWERSIG for
RRSIG/SIG rdatasets and ANSWER for everything else.  this
error didn't cause any harm in the current code, but it
could have led to unexpected behavior in the future.
2025-03-14 18:29:48 -07:00
Evan Hunt 6876c06918 split out some functionality in cache_name()
there are now separate functions to check the cacheability of
an rdataset or to normalize TTLs, and the code to determine
whether validation is necessary has been simplified.
2025-03-14 18:29:48 -07:00
Evan Hunt fdb9a24d18 add functions to match rdataset types
- dns_rdataset_issigtype() returns true if the rdataset is
  of type RRSIG and covers a specified type
- dns_rdataset_matchestype() returns true if the rdataset
  is of the specified type *or* the RRSIG covering it.
2025-03-14 18:29:48 -07:00
Evan Hunt ea33257ad0 reduce steps for negative caching
whenever ncache_adderesult() was called, some preparatory code
was run first; this has now been moved into a single function
negcache() to reduce code duplication.
2025-03-14 18:29:48 -07:00
Evan Hunt dd971ad4e4 change issecuredomain() functions to bool
dns_keytable_issecuredomain() and dns_view_issecuredomain()
previously returned a result code to inform the caller of
unexpected database failures when looking up names in the
keytable and/or NTA table. such failures are not actually
possible. both functions now return a simple bool.

also, dns_view_issecuredomain() now returns false if
view->enablevalidation is false, so the caller no longer
has to check for that.
2025-03-14 18:29:48 -07:00
Evan Hunt 8368ef5ae7 split out cookie checks from resquery_response_continue()
split the code section that handles cookie issues into a
separate function for better readablity.
2025-03-14 18:29:48 -07:00
Evan Hunt d8778caec7 simplify dns_ncache_add()
there's no longer any reason to have both dns_ncache_add() and
dns_ncache_addoptout().
2025-03-14 18:29:48 -07:00
77 changed files with 2718 additions and 3446 deletions
+6 -6
View File
@@ -383,9 +383,6 @@ stages:
SHOTGUN_ROUNDS: 3 SHOTGUN_ROUNDS: 3
- &shotgun_rule_other - &shotgun_rule_other
if: '$CI_PIPELINE_SOURCE =~ /^(api|pipeline|schedule|trigger|web)$/' if: '$CI_PIPELINE_SOURCE =~ /^(api|pipeline|schedule|trigger|web)$/'
# when using data from a single run, the overall instability of the results
# causes quite high false positive rate, rerun the test to attemp to reduce those
retry: 1
script: script:
- if [ -z "$BASELINE" ]; then export BASELINE=$BIND_BASELINE_VERSION; fi # this dotenv variable can't be set in the rules section, because rules are evaluated before any jobs run - if [ -z "$BASELINE" ]; then export BASELINE=$BIND_BASELINE_VERSION; fi # this dotenv variable can't be set in the rules section, because rules are evaluated before any jobs run
- PIPELINE_ID=$(curl -s -X POST --fail - PIPELINE_ID=$(curl -s -X POST --fail
@@ -587,7 +584,7 @@ vulture:
<<: *precheck_job <<: *precheck_job
needs: [] needs: []
script: script:
- vulture --exclude "*ans.py,conftest.py,isctest" --ignore-names "pytestmark" bin/tests/system/ - vulture --exclude "*/ans*/ans.py,conftest.py,isctest" --ignore-names "pytestmark" bin/tests/system/
ci-variables: ci-variables:
stage: precheck stage: precheck
@@ -1691,6 +1688,9 @@ respdiff-third-party:
# Performance tests # Performance tests
# Run shotgun:udp right away, but delay other shotgun jobs sligthly in order to
# allow re-use of the built container image. Otherwise, the jobs would do the
# same builds in parallel rather than re-use the already built image.
shotgun:udp: shotgun:udp:
<<: *shotgun_job <<: *shotgun_job
variables: variables:
@@ -1701,7 +1701,7 @@ shotgun:tcp:
<<: *shotgun_job <<: *shotgun_job
variables: variables:
SHOTGUN_SCENARIO: tcp SHOTGUN_SCENARIO: tcp
SHOTGUN_TRAFFIC_MULTIPLIER: 12 SHOTGUN_TRAFFIC_MULTIPLIER: 13
shotgun:dot: shotgun:dot:
<<: *shotgun_job <<: *shotgun_job
@@ -1722,7 +1722,7 @@ shotgun:doh-get:
variables: variables:
SHOTGUN_SCENARIO: doh-get SHOTGUN_SCENARIO: doh-get
SHOTGUN_TRAFFIC_MULTIPLIER: 3 SHOTGUN_TRAFFIC_MULTIPLIER: 3
SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_MAX: 0.4 # bump from the default due to increased tail-end jitter SHOTGUN_EVAL_THRESHOLD_LATENCY_PCTL_MAX: 0.3 # bump from the default due to increased tail-end jitter
rules: *shotgun_rules_manual_mr rules: *shotgun_rules_manual_mr
.stress-test: &stress_test .stress-test: &stress_test
+1 -7
View File
@@ -129,7 +129,6 @@ static int maxudp = 0;
/* /*
* -T options: * -T options:
*/ */
static bool cookiealwaysvalid = false;
static bool dropedns = false; static bool dropedns = false;
static bool ednsformerr = false; static bool ednsformerr = false;
static bool ednsnotimp = false; static bool ednsnotimp = false;
@@ -653,9 +652,7 @@ parse_T_opt(char *option) {
* force the server to behave (or misbehave) in * force the server to behave (or misbehave) in
* specified ways for testing purposes. * specified ways for testing purposes.
*/ */
if (!strcmp(option, "cookiealwaysvalid")) { if (!strcmp(option, "dropedns")) {
cookiealwaysvalid = true;
} else if (!strcmp(option, "dropedns")) {
dropedns = true; dropedns = true;
} else if (!strcmp(option, "ednsformerr")) { } else if (!strcmp(option, "ednsformerr")) {
ednsformerr = true; ednsformerr = true;
@@ -1223,9 +1220,6 @@ setup(void) {
/* /*
* Modify server context according to command line options * Modify server context according to command line options
*/ */
if (cookiealwaysvalid) {
ns_server_setoption(sctx, NS_SERVER_COOKIEALWAYSVALID, true);
}
if (disable4) { if (disable4) {
ns_server_setoption(sctx, NS_SERVER_DISABLE4, true); ns_server_setoption(sctx, NS_SERVER_DISABLE4, true);
} }
+2 -2
View File
@@ -1603,7 +1603,7 @@ xfrin_xmlrender(dns_zone_t *zone, void *arg) {
isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf)); isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf));
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf)); TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf));
} else if (is_presoa) { } else if (is_presoa) {
dns_zone_getsourceaddr(zone, &addr); addr = dns_zone_getsourceaddr(zone);
isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf)); isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf));
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf)); TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf));
} else { } else {
@@ -2660,7 +2660,7 @@ xfrin_jsonrender(dns_zone_t *zone, void *arg) {
json_object_object_add(xfrinobj, "localaddr", json_object_object_add(xfrinobj, "localaddr",
json_object_new_string(addr_buf)); json_object_new_string(addr_buf));
} else if (is_presoa) { } else if (is_presoa) {
dns_zone_getsourceaddr(zone, &addr); addr = dns_zone_getsourceaddr(zone);
isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf)); isc_sockaddr_format(&addr, addr_buf, sizeof(addr_buf));
json_object_object_add(xfrinobj, "localaddr", json_object_object_add(xfrinobj, "localaddr",
json_object_new_string(addr_buf)); json_object_new_string(addr_buf));
+8 -6
View File
@@ -1279,22 +1279,22 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
obj = NULL; obj = NULL;
result = named_config_get(maps, "parental-source", &obj); result = named_config_get(maps, "parental-source", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL); INSIST(result == ISC_R_SUCCESS && obj != NULL);
dns_zone_setparentalsrc4(zone, cfg_obj_assockaddr(obj)); CHECK(dns_zone_setparentalsrc4(zone, cfg_obj_assockaddr(obj)));
obj = NULL; obj = NULL;
result = named_config_get(maps, "parental-source-v6", &obj); result = named_config_get(maps, "parental-source-v6", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL); INSIST(result == ISC_R_SUCCESS && obj != NULL);
dns_zone_setparentalsrc6(zone, cfg_obj_assockaddr(obj)); CHECK(dns_zone_setparentalsrc6(zone, cfg_obj_assockaddr(obj)));
obj = NULL; obj = NULL;
result = named_config_get(maps, "notify-source", &obj); result = named_config_get(maps, "notify-source", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL); INSIST(result == ISC_R_SUCCESS && obj != NULL);
dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)); CHECK(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
obj = NULL; obj = NULL;
result = named_config_get(maps, "notify-source-v6", &obj); result = named_config_get(maps, "notify-source-v6", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL); INSIST(result == ISC_R_SUCCESS && obj != NULL);
dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)); CHECK(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
obj = NULL; obj = NULL;
result = named_config_get(maps, "notify-to-soa", &obj); result = named_config_get(maps, "notify-to-soa", &obj);
@@ -1938,12 +1938,14 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
obj = NULL; obj = NULL;
result = named_config_get(maps, "transfer-source", &obj); result = named_config_get(maps, "transfer-source", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL); INSIST(result == ISC_R_SUCCESS && obj != NULL);
dns_zone_setxfrsource4(mayberaw, cfg_obj_assockaddr(obj)); CHECK(dns_zone_setxfrsource4(mayberaw,
cfg_obj_assockaddr(obj)));
obj = NULL; obj = NULL;
result = named_config_get(maps, "transfer-source-v6", &obj); result = named_config_get(maps, "transfer-source-v6", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL); INSIST(result == ISC_R_SUCCESS && obj != NULL);
dns_zone_setxfrsource6(mayberaw, cfg_obj_assockaddr(obj)); CHECK(dns_zone_setxfrsource6(mayberaw,
cfg_obj_assockaddr(obj)));
obj = NULL; obj = NULL;
(void)named_config_get(maps, "try-tcp-refresh", &obj); (void)named_config_get(maps, "try-tcp-refresh", &obj);
+2 -4
View File
@@ -131,13 +131,11 @@ status=$((status + ret))
echo_i "checking that log-report-channel zones fail if '*._er/TXT' is missing ($n)" echo_i "checking that log-report-channel zones fail if '*._er/TXT' is missing ($n)"
ret=0 ret=0
$CHECKZONE -R fail example zones/er.db >test.out2.$n 2>&1 || ret=1 $CHECKZONE -R fail example zones/er.db >test.out2.$n 2>&1 || ret=1
grep -F "no '*._er/TXT' wildcard found" test.out2.$n >/dev/null && ret=1 grep -F "no '*._er/TXT' wildcard found" test.out4.$n >/dev/null && ret=1
$CHECKZONE example zones/er-missing.db >test.out3.$n 2>&1 || ret=1 $CHECKZONE example zones/er-missing.db >test.out3.$n 2>&1 || ret=1
grep -F "no '*._er/TXT' wildcard found" test.out3.$n >/dev/null && ret=1 grep -F "no '*._er/TXT' wildcard found" test.out4.$n >/dev/null && ret=1
$CHECKZONE -R fail example zones/er-missing.db >test.out4.$n 2>&1 && ret=1 $CHECKZONE -R fail example zones/er-missing.db >test.out4.$n 2>&1 && ret=1
grep -F "no '*._er/TXT' wildcard found" test.out4.$n >/dev/null || ret=1 grep -F "no '*._er/TXT' wildcard found" test.out4.$n >/dev/null || ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret)) status=$((status + ret))
echo_i "checking that raw zone with bad class is handled ($n)" echo_i "checking that raw zone with bad class is handled ($n)"
-1
View File
@@ -308,7 +308,6 @@ def logger(request, system_test_name):
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def expected_artifacts(request): def expected_artifacts(request):
common_artifacts = [ common_artifacts = [
"*/.hypothesis", # drop after Ubuntu 20.04 Focal Fossa gets removed from CI
".libs/*", # possible build artifacts, see GL #5055 ".libs/*", # possible build artifacts, see GL #5055
"ns*/named.conf", "ns*/named.conf",
"ns*/named.memstats", "ns*/named.memstats",
-17
View File
@@ -361,23 +361,6 @@ grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret)) status=$((status + ret))
n=$((n + 1))
echo_i "Restart NS4 with -T cookiealwaysvalid ($n)"
stop_server ns4
touch ns4/named.cookiealwaysvalid
start_server --noclean --restart --port ${PORT} ns4 || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1))
echo_i "test NS6 cookie on NS4 with -T cookiealwaysvalid (expect success) ($n)"
ret=0
$DIG $DIGOPTS +cookie=$ns6cookie -b 10.53.0.4 +nobadcookie soa . @10.53.0.4 >dig.out.test$n || ret=1
grep "; COOKIE:.*(good)" dig.out.test$n >/dev/null || ret=1
grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
n=$((n + 1)) n=$((n + 1))
echo_i "check that test server is correctly configured ($n)" echo_i "check that test server is correctly configured ($n)"
ret=0 ret=0
@@ -19,7 +19,6 @@ pytestmark = pytest.mark.extra_artifacts(
"ans*/ans.run", "ans*/ans.run",
"ans*/query.log", "ans*/query.log",
"ns1/named_dump.db*", "ns1/named_dump.db*",
"ns4/named.cookiealwaysvalid",
] ]
) )
+1 -1
View File
@@ -2191,7 +2191,7 @@ echo_i "checking RRSIG query from cache ($n)"
ret=0 ret=0
dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 a >/dev/null || ret=1 dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 a >/dev/null || ret=1
ans=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.4 rrsig) || ret=1 ans=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.4 rrsig) || ret=1
expect=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.3 rrsig | grep -E '^(A|NSEC)') || ret=1 expect=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.3 rrsig | grep '^\(A\|NSEC\)') || ret=1
test "$ans" = "$expect" || ret=1 test "$ans" = "$expect" || ret=1
# also check that RA is set # also check that RA is set
dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 rrsig >dig.out.ns4.test$n || ret=1 dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 rrsig >dig.out.ns4.test$n || ret=1
+35 -103
View File
@@ -224,20 +224,6 @@ class DnsProtocol(enum.Enum):
TCP = enum.auto() TCP = enum.auto()
@dataclass(frozen=True)
class Peer:
"""
Pretty-printed connection endpoint.
"""
host: str
port: int
def __str__(self) -> str:
host = f"[{self.host}]" if ":" in self.host else self.host
return f"{host}:{self.port}"
@dataclass @dataclass
class QueryContext: class QueryContext:
""" """
@@ -246,7 +232,7 @@ class QueryContext:
query: dns.message.Message query: dns.message.Message
response: dns.message.Message response: dns.message.Message
peer: Peer peer: Tuple[str, int]
protocol: DnsProtocol protocol: DnsProtocol
zone: Optional[dns.zone.Zone] = None zone: Optional[dns.zone.Zone] = None
soa: Optional[dns.rrset.RRset] = None soa: Optional[dns.rrset.RRset] = None
@@ -527,110 +513,56 @@ class AsyncDnsServer(AsyncServer):
self._zone_tree.add(zone) self._zone_tree.add(zone)
async def _handle_udp( async def _handle_udp(
self, wire: bytes, addr: Tuple[str, int], transport: asyncio.DatagramTransport self, wire: bytes, peer: Tuple[str, int], transport: asyncio.DatagramTransport
) -> None: ) -> None:
logging.debug("Received UDP message: %s", wire.hex()) logging.debug("Received UDP message: %s", wire.hex())
peer = Peer(addr[0], addr[1])
responses = self._handle_query(wire, peer, DnsProtocol.UDP) responses = self._handle_query(wire, peer, DnsProtocol.UDP)
async for response in responses: async for response in responses:
transport.sendto(response, addr) transport.sendto(response, peer)
async def _handle_tcp( async def _handle_tcp(
self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter
) -> None: ) -> None:
peer_info = writer.get_extra_info("peername") wire_length_bytes = await reader.read(2)
peer = Peer(peer_info[0], peer_info[1])
logging.debug("Accepted TCP connection from %s", peer)
while True:
try:
wire = await self._read_tcp_query(reader, peer)
if not wire:
break
await self._send_tcp_response(writer, peer, wire)
except ConnectionResetError:
logging.error("TCP connection from %s reset by peer", peer)
return
logging.debug("Closing TCP connection from %s", peer)
writer.close()
await writer.wait_closed()
async def _read_tcp_query(
self, reader: asyncio.StreamReader, peer: Peer
) -> Optional[bytes]:
wire_length = await self._read_tcp_query_wire_length(reader, peer)
if not wire_length:
return None
return await self._read_tcp_query_wire(reader, peer, wire_length)
async def _read_tcp_query_wire_length(
self, reader: asyncio.StreamReader, peer: Peer
) -> Optional[int]:
logging.debug("Receiving TCP message length from %s...", peer)
wire_length_bytes = await self._read_tcp_octets(reader, peer, 2)
if not wire_length_bytes:
return None
(wire_length,) = struct.unpack("!H", wire_length_bytes) (wire_length,) = struct.unpack("!H", wire_length_bytes)
logging.debug("Receiving TCP message (%d octets)...", wire_length)
return wire_length wire = await reader.read(wire_length)
full_message = wire_length_bytes + wire
logging.debug("Received complete TCP message: %s", full_message.hex())
async def _read_tcp_query_wire( peer = writer.get_extra_info("peername")
self, reader: asyncio.StreamReader, peer: Peer, wire_length: int
) -> Optional[bytes]:
logging.debug("Receiving TCP message (%d octets) from %s...", wire_length, peer)
wire = await self._read_tcp_octets(reader, peer, wire_length)
if not wire:
return None
logging.debug("Received complete TCP message from %s: %s", peer, wire.hex())
return wire
async def _read_tcp_octets(
self, reader: asyncio.StreamReader, peer: Peer, expected: int
) -> Optional[bytes]:
buffer = b""
while len(buffer) < expected:
chunk = await reader.read(expected - len(buffer))
if not chunk:
if buffer:
logging.debug(
"Received short TCP message (%d octets) from %s: %s",
len(buffer),
peer,
buffer.hex(),
)
else:
logging.debug("Received disconnect from %s", peer)
return None
logging.debug("Received %d TCP octets from %s", len(chunk), peer)
buffer += chunk
return buffer
async def _send_tcp_response(
self, writer: asyncio.StreamWriter, peer: Peer, wire: bytes
) -> None:
responses = self._handle_query(wire, peer, DnsProtocol.TCP) responses = self._handle_query(wire, peer, DnsProtocol.TCP)
async for response in responses: async for response in responses:
writer.write(response) writer.write(response)
await writer.drain() try:
await writer.drain()
except ConnectionResetError:
logging.error(
"TCP connection from %s reset by peer", self._format_peer(peer)
)
return
def _log_query(self, qctx: QueryContext, peer: Peer, protocol: DnsProtocol) -> None: writer.close()
await writer.wait_closed()
def _format_peer(self, peer: Tuple[str, int]) -> str:
host = peer[0]
port = peer[1]
if "::" in host:
host = f"[{host}]"
return f"{host}:{port}"
def _log_query(
self, qctx: QueryContext, peer: Tuple[str, int], protocol: DnsProtocol
) -> None:
logging.info( logging.info(
"Received %s/%s/%s (ID=%d) query from %s (%s)", "Received %s/%s/%s (ID=%d) query from %s (%s)",
qctx.qname.to_text(omit_final_dot=True), qctx.qname.to_text(omit_final_dot=True),
dns.rdataclass.to_text(qctx.qclass), dns.rdataclass.to_text(qctx.qclass),
dns.rdatatype.to_text(qctx.qtype), dns.rdatatype.to_text(qctx.qtype),
qctx.query.id, qctx.query.id,
peer, self._format_peer(peer),
protocol.name, protocol.name,
) )
logging.debug( logging.debug(
@@ -641,14 +573,14 @@ class AsyncDnsServer(AsyncServer):
self, self,
qctx: QueryContext, qctx: QueryContext,
response: Optional[Union[dns.message.Message, bytes]], response: Optional[Union[dns.message.Message, bytes]],
peer: Peer, peer: Tuple[str, int],
protocol: DnsProtocol, protocol: DnsProtocol,
) -> None: ) -> None:
if not response: if not response:
logging.info( logging.info(
"Not sending a response to query (ID=%d) from %s (%s)", "Not sending a response to query (ID=%d) from %s (%s)",
qctx.query.id, qctx.query.id,
peer, self._format_peer(peer),
protocol.name, protocol.name,
) )
return return
@@ -674,7 +606,7 @@ class AsyncDnsServer(AsyncServer):
len(response.authority), len(response.authority),
len(response.additional), len(response.additional),
qctx.query.id, qctx.query.id,
peer, self._format_peer(peer),
protocol.name, protocol.name,
) )
logging.debug( logging.debug(
@@ -686,13 +618,13 @@ class AsyncDnsServer(AsyncServer):
"Sending response (%d bytes) to a query (ID=%d) from %s (%s)", "Sending response (%d bytes) to a query (ID=%d) from %s (%s)",
len(response), len(response),
qctx.query.id, qctx.query.id,
peer, self._format_peer(peer),
protocol.name, protocol.name,
) )
logging.debug("[OUT] %s", response.hex()) logging.debug("[OUT] %s", response.hex())
async def _handle_query( async def _handle_query(
self, wire: bytes, peer: Peer, protocol: DnsProtocol self, wire: bytes, peer: Tuple[str, int], protocol: DnsProtocol
) -> AsyncGenerator[bytes, None]: ) -> AsyncGenerator[bytes, None]:
""" """
Yield wire data to send as a response over the established transport. Yield wire data to send as a response over the established transport.
+7 -6
View File
@@ -130,7 +130,7 @@ $KEYGEN -G -k rsasha256 -l policies/kasp.conf $zone >keygen.out.$zone.2 2>&1
zone="multisigner-model2.kasp" zone="multisigner-model2.kasp"
echo_i "setting up zone: $zone" echo_i "setting up zone: $zone"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.1) KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 -M 32768:65535 $zone 2>keygen.out.$zone.2) ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zone -M 32768:65535 2>keygen.out.$zone.2)
cat "${KSK}.key" | grep -v ";.*" >>"${zone}.db" cat "${KSK}.key" | grep -v ";.*" >>"${zone}.db"
cat "${ZSK}.key" | grep -v ";.*" >>"${zone}.db" cat "${ZSK}.key" | grep -v ";.*" >>"${zone}.db"
# Import the ZSK sets of the other providers into their DNSKEY RRset. # Import the ZSK sets of the other providers into their DNSKEY RRset.
@@ -350,9 +350,10 @@ setup step2.enable-dnssec.autosign
TpubN="now-900s" TpubN="now-900s"
# RRSIG TTL: 12 hour (43200 seconds) # RRSIG TTL: 12 hour (43200 seconds)
# zone-propagation-delay: 5 minutes (300 seconds) # zone-propagation-delay: 5 minutes (300 seconds)
# retire-safety: 20 minutes (1200 seconds)
# Already passed time: -900 seconds # Already passed time: -900 seconds
# Total: 42600 seconds # Total: 43800 seconds
TsbmN="now+42600s" TsbmN="now+43800s"
keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}" keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}"
CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2>keygen.out.$zone.1) CSK=$($KEYGEN -k enable-dnssec -l policies/autosign.conf $keytimes $zone 2>keygen.out.$zone.1)
$SETTIME -s -g $O -k $R $TpubN -r $R $TpubN -d $H $TpubN -z $R $TpubN "$CSK" >settime.out.$zone.1 2>&1 $SETTIME -s -g $O -k $R $TpubN -r $R $TpubN -d $H $TpubN -z $R $TpubN "$CSK" >settime.out.$zone.1 2>&1
@@ -364,10 +365,10 @@ $SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $i
# Step 3: # Step 3:
# The zone signatures have been published long enough to become OMNIPRESENT. # The zone signatures have been published long enough to become OMNIPRESENT.
setup step3.enable-dnssec.autosign setup step3.enable-dnssec.autosign
# Passed time since publications: 42600 + 900 = 43500 seconds. # Passed time since publications: 43800 + 900 = 44700 seconds.
TpubN="now-43500s" TpubN="now-44700s"
# The key is secure for using in chain of trust when the DNSKEY is OMNIPRESENT. # The key is secure for using in chain of trust when the DNSKEY is OMNIPRESENT.
TcotN="now-42600s" TcotN="now-43800s"
# We can submit the DS now. # We can submit the DS now.
TsbmN="now" TsbmN="now"
keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}" keytimes="-P ${TpubN} -P sync ${TsbmN} -A ${TpubN}"
+41 -41
View File
@@ -127,9 +127,9 @@ setup step2.algorithm-roll.kasp
# The time passed since the new algorithm keys have been introduced is 3 hours. # The time passed since the new algorithm keys have been introduced is 3 hours.
TactN="now-3h" TactN="now-3h"
TpubN1="now-3h" TpubN1="now-3h"
# Tsbm(N+1) = TpubN1 + Ipub = now + TTLsig + Dprp = # Tsbm(N+1) = TpubN1 + Ipub = now + TTLsig + Dprp + publish-safety =
# now - 3h + 6h + 1h = now + 4h # now - 3h + 6h + 1h + 1h = now + 5h
TsbmN1="now+4h" TsbmN1="now+5h"
ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I now" ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I now"
zsk1times="-P ${TactN} -A ${TactN} -I now" zsk1times="-P ${TactN} -A ${TactN} -I now"
ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
@@ -156,11 +156,11 @@ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infil
# Step 3: # Step 3:
# The zone signatures are also OMNIPRESENT. # The zone signatures are also OMNIPRESENT.
setup step3.algorithm-roll.kasp setup step3.algorithm-roll.kasp
# The time passed since the new algorithm keys have been introduced is 7 hours. # The time passed since the new algorithm keys have been introduced is 9 hours.
TactN="now-7h" TactN="now-9h"
TretN="now-3h" TretN="now-6h"
TpubN1="now-7h" TpubN1="now-9h"
TsbmN1="now" TsbmN1="now-1h"
ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
@@ -188,11 +188,11 @@ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infil
# The DS is swapped and can become OMNIPRESENT. # The DS is swapped and can become OMNIPRESENT.
setup step4.algorithm-roll.kasp setup step4.algorithm-roll.kasp
# The time passed since the DS has been swapped is 29 hours. # The time passed since the DS has been swapped is 29 hours.
TactN="now-36h" TactN="now-38h"
TretN="now-33h" TretN="now-35h"
TpubN1="now-36h" TpubN1="now-38h"
TsbmN1="now-29h" TsbmN1="now-30h"
TactN1="now-27h" TactN1="now-29h"
ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
@@ -220,12 +220,12 @@ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infil
# The DNSKEY is removed long enough to be HIDDEN. # The DNSKEY is removed long enough to be HIDDEN.
setup step5.algorithm-roll.kasp setup step5.algorithm-roll.kasp
# The time passed since the DNSKEY has been removed is 2 hours. # The time passed since the DNSKEY has been removed is 2 hours.
TactN="now-38h" TactN="now-40h"
TretN="now-35h" TretN="now-37h"
TremN="now-2h" TremN="now-2h"
TpubN1="now-38h" TpubN1="now-40h"
TsbmN1="now-31h" TsbmN1="now-32h"
TactN1="now-29h" TactN1="now-31h"
ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
@@ -253,13 +253,13 @@ $SIGNER -S -x -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $infil
# The RRSIGs have been removed long enough to be HIDDEN. # The RRSIGs have been removed long enough to be HIDDEN.
setup step6.algorithm-roll.kasp setup step6.algorithm-roll.kasp
# Additional time passed: 7h. # Additional time passed: 7h.
TactN="now-45h" TactN="now-47h"
TretN="now-42h" TretN="now-44h"
TremN="now-7h" TremN="now-7h"
TpubN1="now-45h" TpubN1="now-47h"
TsbmN1="now-38h" TsbmN1="now-39h"
TactN1="now-36h" TactN1="now-38h"
TdeaN="now-7h" TdeaN="now-9h"
ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" ksk1times="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}" zsk1times="-P ${TactN} -A ${TactN} -I ${TretN}"
ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}" ksk2times="-P ${TpubN1} -A ${TpubN1} -P sync ${TsbmN1}"
@@ -324,11 +324,11 @@ $SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $in
# Step 3: # Step 3:
# The zone signatures are also OMNIPRESENT. # The zone signatures are also OMNIPRESENT.
setup step3.csk-algorithm-roll.kasp setup step3.csk-algorithm-roll.kasp
# The time passed since the new algorithm keys have been introduced is 7 hours. # The time passed since the new algorithm keys have been introduced is 9 hours.
TactN="now-7h" TactN="now-9h"
TretN="now-3h" TretN="now-6h"
TpubN1="now-7h" TpubN1="now-9h"
TactN1="now-3h" TactN1="now-6h"
csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
newtimes="-P ${TpubN1} -A ${TpubN1}" newtimes="-P ${TpubN1} -A ${TpubN1}"
CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1) CSK1=$($KEYGEN -k csk-algoroll -l policies/csk1.conf $csktimes $zone 2>keygen.out.$zone.1)
@@ -347,10 +347,10 @@ $SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $in
# The DS is swapped and can become OMNIPRESENT. # The DS is swapped and can become OMNIPRESENT.
setup step4.csk-algorithm-roll.kasp setup step4.csk-algorithm-roll.kasp
# The time passed since the DS has been swapped is 29 hours. # The time passed since the DS has been swapped is 29 hours.
TactN="now-36h" TactN="now-38h"
TretN="now-33h" TretN="now-35h"
TpubN1="now-36h" TpubN1="now-38h"
TactN1="now-33h" TactN1="now-35h"
TsubN1="now-29h" TsubN1="now-29h"
csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
newtimes="-P ${TpubN1} -A ${TpubN1}" newtimes="-P ${TpubN1} -A ${TpubN1}"
@@ -370,11 +370,11 @@ $SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $in
# The DNSKEY is removed long enough to be HIDDEN. # The DNSKEY is removed long enough to be HIDDEN.
setup step5.csk-algorithm-roll.kasp setup step5.csk-algorithm-roll.kasp
# The time passed since the DNSKEY has been removed is 2 hours. # The time passed since the DNSKEY has been removed is 2 hours.
TactN="now-38h" TactN="now-40h"
TretN="now-35h" TretN="now-37h"
TremN="now-2h" TremN="now-2h"
TpubN1="now-38h" TpubN1="now-40h"
TactN1="now-35h" TactN1="now-37h"
TsubN1="now-31h" TsubN1="now-31h"
csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
newtimes="-P ${TpubN1} -A ${TpubN1}" newtimes="-P ${TpubN1} -A ${TpubN1}"
@@ -394,12 +394,12 @@ $SIGNER -S -x -z -s now-1h -e now+2w -o $zone -O raw -f "${zonefile}.signed" $in
# The RRSIGs have been removed long enough to be HIDDEN. # The RRSIGs have been removed long enough to be HIDDEN.
setup step6.csk-algorithm-roll.kasp setup step6.csk-algorithm-roll.kasp
# Additional time passed: 7h. # Additional time passed: 7h.
TactN="now-45h" TactN="now-47h"
TretN="now-42h" TretN="now-44h"
TdeaN="now-9h" TdeaN="now-9h"
TremN="now-7h" TremN="now-7h"
TpubN1="now-45h" TpubN1="now-47h"
TactN1="now-42h" TactN1="now-44h"
TsubN1="now-38h" TsubN1="now-38h"
csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}" csktimes="-P ${TactN} -A ${TactN} -P sync ${TactN} -I ${TretN}"
newtimes="-P ${TpubN1} -A ${TpubN1}" newtimes="-P ${TpubN1} -A ${TpubN1}"
+125 -120
View File
@@ -275,8 +275,9 @@ set_keytimes_csk_policy() {
set_keytime "KEY1" "ACTIVE" "${created}" set_keytime "KEY1" "ACTIVE" "${created}"
# The DS can be published if the DNSKEY and RRSIG records are # The DS can be published if the DNSKEY and RRSIG records are
# OMNIPRESENT. This happens after max-zone-ttl (1d) plus # OMNIPRESENT. This happens after max-zone-ttl (1d) plus
# zone-propagation-delay (300s) = 86400 + 300 = 86700. # publish-safety (1h) plus zone-propagation-delay (300s) =
set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 86700 # 86400 + 3600 + 300 = 90300.
set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 90300
# Key lifetime is unlimited, so not setting RETIRED and REMOVED. # Key lifetime is unlimited, so not setting RETIRED and REMOVED.
} }
@@ -768,8 +769,9 @@ set_keytimes_algorithm_policy() {
# The DS can be published if the DNSKEY and RRSIG records are # The DS can be published if the DNSKEY and RRSIG records are
# OMNIPRESENT. This happens after max-zone-ttl (1d) plus # OMNIPRESENT. This happens after max-zone-ttl (1d) plus
# zone-propagation-delay (300s) = 86400 + 300 = 86700. # publish-safety (1h) plus zone-propagation-delay (300s) =
set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 86700 # 86400 + 3600 + 300 = 90300.
set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 90300
# Key lifetime is 10 years, 315360000 seconds. # Key lifetime is 10 years, 315360000 seconds.
set_addkeytime "KEY1" "RETIRED" "${published}" 315360000 set_addkeytime "KEY1" "RETIRED" "${published}" 315360000
# The key is removed after the retire time plus DS TTL (1d), # The key is removed after the retire time plus DS TTL (1d),
@@ -1718,10 +1720,10 @@ published=$(awk '{print $3}' <published.test${n}.key1)
set_keytime "KEY1" "PUBLISHED" "${published}" set_keytime "KEY1" "PUBLISHED" "${published}"
set_keytime "KEY1" "ACTIVE" "${published}" set_keytime "KEY1" "ACTIVE" "${published}"
published=$(key_get KEY1 PUBLISHED) published=$(key_get KEY1 PUBLISHED)
# The DS can be published if the zone is fully signed. # The DS can be published if the DNSKEY and RRSIG records are OMNIPRESENT.
# This happens after max-zone-ttl (1d) plus # This happens after max-zone-ttl (1d) plus publish-safety (1h) plus
# zone-propagation-delay (300s) = 86400 + 300 = 86700. # zone-propagation-delay (300s) = 86400 + 3600 + 300 = 90300.
set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 86700 set_addkeytime "KEY1" "SYNCPUBLISH" "${published}" 90300
# Key lifetime is 6 months, 315360000 seconds. # Key lifetime is 6 months, 315360000 seconds.
set_addkeytime "KEY1" "RETIRED" "${published}" 16070400 set_addkeytime "KEY1" "RETIRED" "${published}" 16070400
# The key is removed after the retire time plus DS TTL (1d), parent # The key is removed after the retire time plus DS TTL (1d), parent
@@ -2484,9 +2486,9 @@ set_keytime "KEY1" "PUBLISHED" "${created}"
set_keytime "KEY1" "ACTIVE" "${created}" set_keytime "KEY1" "ACTIVE" "${created}"
# - The DS can be published if the DNSKEY and RRSIG records are # - The DS can be published if the DNSKEY and RRSIG records are
# OMNIPRESENT. This happens after max-zone-ttl (12h) plus # OMNIPRESENT. This happens after max-zone-ttl (12h) plus
# plus zone-propagation-delay (5m) = # publish-safety (5m) plus zone-propagation-delay (5m) =
# 43200 + 300 = 43500. # 43200 + 300 + 300 = 43800.
set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 43500 set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 43800
# - Key lifetime is unlimited, so not setting RETIRED and REMOVED. # - Key lifetime is unlimited, so not setting RETIRED and REMOVED.
# Various signing policy checks. # Various signing policy checks.
@@ -2554,7 +2556,7 @@ check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
created=$(key_get KEY1 CREATED) created=$(key_get KEY1 CREATED)
set_addkeytime "KEY1" "PUBLISHED" "${created}" -900 set_addkeytime "KEY1" "PUBLISHED" "${created}" -900
set_addkeytime "KEY1" "ACTIVE" "${created}" -900 set_addkeytime "KEY1" "ACTIVE" "${created}" -900
set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 42600 set_addkeytime "KEY1" "SYNCPUBLISH" "${created}" 43800
# Continue signing policy checks. # Continue signing policy checks.
check_keytimes check_keytimes
@@ -2564,8 +2566,8 @@ dnssec_verify
# Next key event is when the zone signatures become OMNIPRESENT: max-zone-ttl # Next key event is when the zone signatures become OMNIPRESENT: max-zone-ttl
# plus zone propagation delay plus retire safety minus the already elapsed # plus zone propagation delay plus retire safety minus the already elapsed
# 900 seconds: 12h + 300s + 20m - 900 = 43500 - 900 = 42600 seconds # 900 seconds: 12h + 300s + 20m - 900 = 44700 - 900 = 43800 seconds
check_next_key_event 42600 check_next_key_event 43800
# #
# Zone: step3.enable-dnssec.autosign. # Zone: step3.enable-dnssec.autosign.
@@ -2582,10 +2584,10 @@ check_keys
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
# Set expected key times: # Set expected key times:
# - The key was published and activated 43500 seconds ago (with settime). # - The key was published and activated 44700 seconds ago (with settime).
created=$(key_get KEY1 CREATED) created=$(key_get KEY1 CREATED)
set_addkeytime "KEY1" "PUBLISHED" "${created}" -43500 set_addkeytime "KEY1" "PUBLISHED" "${created}" -44700
set_addkeytime "KEY1" "ACTIVE" "${created}" -43500 set_addkeytime "KEY1" "ACTIVE" "${created}" -44700
set_keytime "KEY1" "SYNCPUBLISH" "${created}" set_keytime "KEY1" "SYNCPUBLISH" "${created}"
# Continue signing policy checks. # Continue signing policy checks.
@@ -2601,8 +2603,8 @@ check_cdslog "$DIR" "$ZONE" KEY1
rndc_checkds "$SERVER" "$DIR" KEY1 "now" "published" "$ZONE" rndc_checkds "$SERVER" "$DIR" KEY1 "now" "published" "$ZONE"
# Next key event is when the DS can move to the OMNIPRESENT state. This occurs # Next key event is when the DS can move to the OMNIPRESENT state. This occurs
# when the parent propagation delay have passed, plus the DS TTL and retire # when the parent propagation delay have passed, plus the DS TTL and retire
# safety delay: 1h + 2h = 3h = 10800 seconds # safety delay: 1h + 2h + 20m = 3h20m = 12000 seconds
check_next_key_event 10800 check_next_key_event 12000
# #
# Zone: step4.enable-dnssec.autosign. # Zone: step4.enable-dnssec.autosign.
@@ -4386,9 +4388,9 @@ check_subdomain
dnssec_verify dnssec_verify
# Next key event is when the DS becomes HIDDEN. This happens after the # Next key event is when the DS becomes HIDDEN. This happens after the
# parent propagation delay, and DS TTL: # parent propagation delay, retire safety delay, and DS TTL:
# 1h + 1d = 25h = 90000 seconds. # 1h + 1h + 1d = 26h = 93600 seconds.
check_next_key_event 90000 check_next_key_event 93600
# #
# Zone: step2.going-insecure.kasp # Zone: step2.going-insecure.kasp
@@ -4454,8 +4456,8 @@ dnssec_verify
# Next key event is when the DS becomes HIDDEN. This happens after the # Next key event is when the DS becomes HIDDEN. This happens after the
# parent propagation delay, retire safety delay, and DS TTL: # parent propagation delay, retire safety delay, and DS TTL:
# 1h + 1d = 25h = 90000 seconds. # 1h + 1h + 1d = 26h = 93600 seconds.
check_next_key_event 90000 check_next_key_event 93600
# #
# Zone: step2.going-insecure-dynamic.kasp # Zone: step2.going-insecure-dynamic.kasp
@@ -4649,11 +4651,12 @@ set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
created=$(key_get KEY3 CREATED) created=$(key_get KEY3 CREATED)
set_keytime "KEY3" "PUBLISHED" "${created}" set_keytime "KEY3" "PUBLISHED" "${created}"
set_keytime "KEY3" "ACTIVE" "${created}" set_keytime "KEY3" "ACTIVE" "${created}"
# - It takes TTLsig + Dprp to propagate the zone. # - It takes TTLsig + Dprp + publish-safety hours to propagate the zone.
# TTLsig: 6h (39600 seconds) # TTLsig: 6h (39600 seconds)
# Dprp: 1h (3600 seconds) # Dprp: 1h (3600 seconds)
# Ipub: 7h (25200 seconds) # publish-safety: 1h (3600 seconds)
Ipub=25200 # Ipub: 8h (28800 seconds)
Ipub=28800
set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${Ipub}" set_addkeytime "KEY3" "SYNCPUBLISH" "${created}" "${Ipub}"
# - The new ZSK is published and activated. # - The new ZSK is published and activated.
created=$(key_get KEY4 CREATED) created=$(key_get KEY4 CREATED)
@@ -4722,12 +4725,12 @@ dnssec_verify
# Next key event is when all zone signatures are signed with the new # Next key event is when all zone signatures are signed with the new
# algorithm. This is the max-zone-ttl plus zone propagation delay # algorithm. This is the max-zone-ttl plus zone propagation delay
# 6h + 1h. But three hours have already passed (the time it took to # plus retire safety: 6h + 1h + 2h. But three hours have already passed
# make the DNSKEY omnipresent), so the next event should be scheduled # (the time it took to make the DNSKEY omnipresent), so the next event
# in 4 hour: 14400 seconds. Prevent intermittent # should be scheduled in 6 hour: 21600 seconds. Prevent intermittent
# false positives on slow platforms by subtracting the number of seconds # false positives on slow platforms by subtracting the number of seconds
# which passed between key creation and invoking 'rndc reconfig'. # which passed between key creation and invoking 'rndc reconfig'.
next_time=$((14400 - time_passed)) next_time=$((21600 - time_passed))
check_next_key_event $next_time check_next_key_event $next_time
# #
@@ -4750,28 +4753,28 @@ check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
check_cdslog "$DIR" "$ZONE" KEY3 check_cdslog "$DIR" "$ZONE" KEY3
# Set expected key times: # Set expected key times:
# - The old keys were activated 7 hours ago (25200 seconds). # - The old keys were activated 9 hours ago (32400 seconds).
rollover_predecessor_keytimes -25200 rollover_predecessor_keytimes -32400
# - And retired 3 hours ago (10800 seconds). # - And retired 6 hours ago (21600 seconds).
created=$(key_get KEY1 CREATED) created=$(key_get KEY1 CREATED)
set_addkeytime "KEY1" "RETIRED" "${created}" -10800 set_addkeytime "KEY1" "RETIRED" "${created}" -21600
retired=$(key_get KEY1 RETIRED) retired=$(key_get KEY1 RETIRED)
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}" set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
created=$(key_get KEY2 CREATED) created=$(key_get KEY2 CREATED)
set_addkeytime "KEY2" "RETIRED" "${created}" -10800 set_addkeytime "KEY2" "RETIRED" "${created}" -21600
retired=$(key_get KEY2 RETIRED) retired=$(key_get KEY2 RETIRED)
set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}" set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
# - The new keys are published 7 hours ago. # - The new keys are published 9 hours ago.
created=$(key_get KEY3 CREATED) created=$(key_get KEY3 CREATED)
set_addkeytime "KEY3" "PUBLISHED" "${created}" -25200 set_addkeytime "KEY3" "PUBLISHED" "${created}" -32400
set_addkeytime "KEY3" "ACTIVE" "${created}" -25200 set_addkeytime "KEY3" "ACTIVE" "${created}" -32400
published=$(key_get KEY3 PUBLISHED) published=$(key_get KEY3 PUBLISHED)
set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub} set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
created=$(key_get KEY4 CREATED) created=$(key_get KEY4 CREATED)
set_addkeytime "KEY4" "PUBLISHED" "${created}" -25200 set_addkeytime "KEY4" "PUBLISHED" "${created}" -32400
set_addkeytime "KEY4" "ACTIVE" "${created}" -25200 set_addkeytime "KEY4" "ACTIVE" "${created}" -32400
# Continue signing policy checks. # Continue signing policy checks.
check_keytimes check_keytimes
@@ -4784,9 +4787,9 @@ dnssec_verify
rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE" rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE"
rndc_checkds "$SERVER" "$DIR" KEY3 "now" "published" "$ZONE" rndc_checkds "$SERVER" "$DIR" KEY3 "now" "published" "$ZONE"
# Next key event is when the DS becomes OMNIPRESENT. This happens after the # Next key event is when the DS becomes OMNIPRESENT. This happens after the
# parent propagation delay, and DS TTL: # parent propagation delay, retire safety delay, and DS TTL:
# 1h + 2h = 3h = 10800 seconds. # 1h + 2h + 2h = 5h = 18000 seconds.
check_next_key_event 10800 check_next_key_event 18000
# #
# Zone: step4.algorithm-roll.kasp # Zone: step4.algorithm-roll.kasp
@@ -4813,29 +4816,29 @@ wait_for_done_signing
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
# Set expected key times: # Set expected key times:
# - The old keys were activated 36 hours ago (129600 seconds). # - The old keys were activated 38 hours ago (136800 seconds).
rollover_predecessor_keytimes -129600 rollover_predecessor_keytimes -136800
# - And retired 33 hours ago (118800 seconds). # - And retired 35 hours ago (126000 seconds).
created=$(key_get KEY1 CREATED) created=$(key_get KEY1 CREATED)
set_addkeytime "KEY1" "RETIRED" "${created}" -118800 set_addkeytime "KEY1" "RETIRED" "${created}" -126000
retired=$(key_get KEY1 RETIRED) retired=$(key_get KEY1 RETIRED)
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}" set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
created=$(key_get KEY2 CREATED) created=$(key_get KEY2 CREATED)
set_addkeytime "KEY2" "RETIRED" "${created}" -118800 set_addkeytime "KEY2" "RETIRED" "${created}" -126000
retired=$(key_get KEY2 RETIRED) retired=$(key_get KEY2 RETIRED)
set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}" set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
# - The new keys are published 36 hours ago. # - The new keys are published 38 hours ago.
created=$(key_get KEY3 CREATED) created=$(key_get KEY3 CREATED)
set_addkeytime "KEY3" "PUBLISHED" "${created}" -129600 set_addkeytime "KEY3" "PUBLISHED" "${created}" -136800
set_addkeytime "KEY3" "ACTIVE" "${created}" -129600 set_addkeytime "KEY3" "ACTIVE" "${created}" -136800
published=$(key_get KEY3 PUBLISHED) published=$(key_get KEY3 PUBLISHED)
set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub} set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
created=$(key_get KEY4 CREATED) created=$(key_get KEY4 CREATED)
set_addkeytime "KEY4" "PUBLISHED" "${created}" -129600 set_addkeytime "KEY4" "PUBLISHED" "${created}" -136800
set_addkeytime "KEY4" "ACTIVE" "${created}" -129600 set_addkeytime "KEY4" "ACTIVE" "${created}" -136800
# Continue signing policy checks. # Continue signing policy checks.
check_keytimes check_keytimes
@@ -4864,29 +4867,29 @@ wait_for_done_signing
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
# Set expected key times: # Set expected key times:
# - The old keys were activated 38 hours ago (136800 seconds) # - The old keys were activated 40 hours ago (144000 seconds)
rollover_predecessor_keytimes -136800 rollover_predecessor_keytimes -144000
# - And retired 35 hours ago (126000 seconds). # - And retired 37 hours ago (133200 seconds).
created=$(key_get KEY1 CREATED) created=$(key_get KEY1 CREATED)
set_addkeytime "KEY1" "RETIRED" "${created}" -126000 set_addkeytime "KEY1" "RETIRED" "${created}" -133200
retired=$(key_get KEY1 RETIRED) retired=$(key_get KEY1 RETIRED)
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}" set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
created=$(key_get KEY2 CREATED) created=$(key_get KEY2 CREATED)
set_addkeytime "KEY2" "RETIRED" "${created}" -126000 set_addkeytime "KEY2" "RETIRED" "${created}" -133200
retired=$(key_get KEY2 RETIRED) retired=$(key_get KEY2 RETIRED)
set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}" set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
# The new keys are published 40 hours ago. # The new keys are published 40 hours ago.
created=$(key_get KEY3 CREATED) created=$(key_get KEY3 CREATED)
set_addkeytime "KEY3" "PUBLISHED" "${created}" -136800 set_addkeytime "KEY3" "PUBLISHED" "${created}" -144000
set_addkeytime "KEY3" "ACTIVE" "${created}" -136800 set_addkeytime "KEY3" "ACTIVE" "${created}" -144000
published=$(key_get KEY3 PUBLISHED) published=$(key_get KEY3 PUBLISHED)
set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub} set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
created=$(key_get KEY4 CREATED) created=$(key_get KEY4 CREATED)
set_addkeytime "KEY4" "PUBLISHED" "${created}" -136800 set_addkeytime "KEY4" "PUBLISHED" "${created}" -144000
set_addkeytime "KEY4" "ACTIVE" "${created}" -136800 set_addkeytime "KEY4" "ACTIVE" "${created}" -144000
# Continue signing policy checks. # Continue signing policy checks.
check_keytimes check_keytimes
@@ -4895,12 +4898,12 @@ check_subdomain
dnssec_verify dnssec_verify
# Next key event is when the RSASHA1 signatures become HIDDEN. This happens # Next key event is when the RSASHA1 signatures become HIDDEN. This happens
# after the max-zone-ttl plus zone propagation delay (6h + 1h) # after the max-zone-ttl plus zone propagation delay plus retire safety
# minus the time already passed since the UNRETENTIVE state has # (6h + 1h + 2h) minus the time already passed since the UNRETENTIVE state has
# been reached (2h): 7h - 2h = 5h = 18000 seconds. Prevent intermittent # been reached (2h): 9h - 2h = 7h = 25200 seconds. Prevent intermittent
# false positives on slow platforms by subtracting the number of seconds # false positives on slow platforms by subtracting the number of seconds
# which passed between key creation and invoking 'rndc reconfig'. # which passed between key creation and invoking 'rndc reconfig'.
next_time=$((18000 - time_passed)) next_time=$((25200 - time_passed))
check_next_key_event $next_time check_next_key_event $next_time
# #
@@ -4918,29 +4921,29 @@ wait_for_done_signing
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
# Set expected key times: # Set expected key times:
# - The old keys were activated 45 hours ago (162000 seconds) # - The old keys were activated 47 hours ago (169200 seconds)
rollover_predecessor_keytimes -162000 rollover_predecessor_keytimes -169200
# - And retired 42 hours ago (151200 seconds). # - And retired 44 hours ago (158400 seconds).
created=$(key_get KEY1 CREATED) created=$(key_get KEY1 CREATED)
set_addkeytime "KEY1" "RETIRED" "${created}" -151200 set_addkeytime "KEY1" "RETIRED" "${created}" -158400
retired=$(key_get KEY1 RETIRED) retired=$(key_get KEY1 RETIRED)
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}" set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretKSK}"
created=$(key_get KEY2 CREATED) created=$(key_get KEY2 CREATED)
set_addkeytime "KEY2" "RETIRED" "${created}" -151200 set_addkeytime "KEY2" "RETIRED" "${created}" -158400
retired=$(key_get KEY2 RETIRED) retired=$(key_get KEY2 RETIRED)
set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}" set_addkeytime "KEY2" "REMOVED" "${retired}" "${IretZSK}"
# The new keys are published 47 hours ago. # The new keys are published 47 hours ago.
created=$(key_get KEY3 CREATED) created=$(key_get KEY3 CREATED)
set_addkeytime "KEY3" "PUBLISHED" "${created}" -162000 set_addkeytime "KEY3" "PUBLISHED" "${created}" -169200
set_addkeytime "KEY3" "ACTIVE" "${created}" -162000 set_addkeytime "KEY3" "ACTIVE" "${created}" -169200
published=$(key_get KEY3 PUBLISHED) published=$(key_get KEY3 PUBLISHED)
set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub} set_addkeytime "KEY3" "SYNCPUBLISH" "${published}" ${Ipub}
created=$(key_get KEY4 CREATED) created=$(key_get KEY4 CREATED)
set_addkeytime "KEY4" "PUBLISHED" "${created}" -162000 set_addkeytime "KEY4" "PUBLISHED" "${created}" -169200
set_addkeytime "KEY4" "ACTIVE" "${created}" -162000 set_addkeytime "KEY4" "ACTIVE" "${created}" -169200
# Continue signing policy checks. # Continue signing policy checks.
check_keytimes check_keytimes
@@ -5023,8 +5026,9 @@ set_keytime "KEY2" "ACTIVE" "${created}"
# - It takes TTLsig + Dprp + publish-safety hours to propagate the zone. # - It takes TTLsig + Dprp + publish-safety hours to propagate the zone.
# TTLsig: 6h (39600 seconds) # TTLsig: 6h (39600 seconds)
# Dprp: 1h (3600 seconds) # Dprp: 1h (3600 seconds)
# Ipub: 7h (25200 seconds) # publish-safety: 1h (3600 seconds)
Ipub=25200 # Ipub: 8h (28800 seconds)
Ipub=28800
set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" "${Ipub}" set_addkeytime "KEY2" "SYNCPUBLISH" "${created}" "${Ipub}"
# Continue signing policy checks. # Continue signing policy checks.
@@ -5078,13 +5082,14 @@ check_apex
check_subdomain check_subdomain
dnssec_verify dnssec_verify
# Next key event is when all zone signatures are signed with the new algorithm. # Next key event is when all zone signatures are signed with the new
# This is the max-zone-ttl plus zone propagation delay: 6h + 1h. But three # algorithm. This is the max-zone-ttl plus zone propagation delay
# hours have already passed (the time it took to make the DNSKEY omnipresent), # plus retire safety: 6h + 1h + 2h. But three hours have already passed
# so the next event should be scheduled in 4 hour: 14400 seconds. Prevent # (the time it took to make the DNSKEY omnipresent), so the next event
# intermittent false positives on slow platforms by subtracting the number of # should be scheduled in 6 hour: 21600 seconds. Prevent intermittent
# seconds which passed between key creation and invoking 'rndc reconfig'. # false positives on slow platforms by subtracting the number of seconds
next_time=$((14400 - time_passed)) # which passed between key creation and invoking 'rndc reconfig'.
next_time=$((21600 - time_passed))
check_next_key_event $next_time check_next_key_event $next_time
# #
@@ -5109,17 +5114,17 @@ check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
check_cdslog "$DIR" "$ZONE" KEY2 check_cdslog "$DIR" "$ZONE" KEY2
# Set expected key times: # Set expected key times:
# - The old key was activated 7 hours ago (25200 seconds). # - The old key was activated 9 hours ago (32400 seconds).
csk_rollover_predecessor_keytimes -25200 csk_rollover_predecessor_keytimes -32400
# - And was retired 3 hours ago (10800 seconds). # - And was retired 6 hours ago (21600 seconds).
created=$(key_get KEY1 CREATED) created=$(key_get KEY1 CREATED)
set_addkeytime "KEY1" "RETIRED" "${created}" -10800 set_addkeytime "KEY1" "RETIRED" "${created}" -21600
retired=$(key_get KEY1 RETIRED) retired=$(key_get KEY1 RETIRED)
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}" set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
# - The new key was published 9 hours ago. # - The new key was published 9 hours ago.
created=$(key_get KEY2 CREATED) created=$(key_get KEY2 CREATED)
set_addkeytime "KEY2" "PUBLISHED" "${created}" -25200 set_addkeytime "KEY2" "PUBLISHED" "${created}" -32400
set_addkeytime "KEY2" "ACTIVE" "${created}" -25200 set_addkeytime "KEY2" "ACTIVE" "${created}" -32400
published=$(key_get KEY2 PUBLISHED) published=$(key_get KEY2 PUBLISHED)
set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}" set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" "${Ipub}"
@@ -5133,9 +5138,9 @@ dnssec_verify
rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE" rndc_checkds "$SERVER" "$DIR" KEY1 "now" "withdrawn" "$ZONE"
rndc_checkds "$SERVER" "$DIR" KEY2 "now" "published" "$ZONE" rndc_checkds "$SERVER" "$DIR" KEY2 "now" "published" "$ZONE"
# Next key event is when the DS becomes OMNIPRESENT. This happens after the # Next key event is when the DS becomes OMNIPRESENT. This happens after the
# parent propagation delay, and DS TTL: # parent propagation delay, retire safety delay, and DS TTL:
# 1h + 2h = 3h = 10800 seconds. # 1h + 2h + 2h = 5h = 18000 seconds.
check_next_key_event 10800 check_next_key_event 18000
# #
# Zone: step4.csk-algorithm-roll.kasp # Zone: step4.csk-algorithm-roll.kasp
@@ -5159,17 +5164,17 @@ wait_for_done_signing
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
# Set expected key times: # Set expected key times:
# - The old keys were activated 36 hours ago (129600 seconds). # - The old key was activated 38 hours ago (136800 seconds)
csk_rollover_predecessor_keytimes -129600 csk_rollover_predecessor_keytimes -136800
# - And retired 33 hours ago (118800 seconds). # - And retired 35 hours ago (126000 seconds).
created=$(key_get KEY1 CREATED) created=$(key_get KEY1 CREATED)
set_addkeytime "KEY1" "RETIRED" "${created}" -118800 set_addkeytime "KEY1" "RETIRED" "${created}" -126000
retired=$(key_get KEY1 RETIRED) retired=$(key_get KEY1 RETIRED)
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}" set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
# - The new key was published 36 hours ago. # - The new key was published 38 hours ago.
created=$(key_get KEY2 CREATED) created=$(key_get KEY2 CREATED)
set_addkeytime "KEY2" "PUBLISHED" "${created}" -129600 set_addkeytime "KEY2" "PUBLISHED" "${created}" -136800
set_addkeytime "KEY2" "ACTIVE" "${created}" -129600 set_addkeytime "KEY2" "ACTIVE" "${created}" -136800
published=$(key_get KEY2 PUBLISHED) published=$(key_get KEY2 PUBLISHED)
set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub} set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub}
@@ -5199,17 +5204,17 @@ wait_for_done_signing
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
# Set expected key times: # Set expected key times:
# - The old key was activated 38 hours ago (136800 seconds) # - The old key was activated 40 hours ago (144000 seconds)
csk_rollover_predecessor_keytimes -136800 csk_rollover_predecessor_keytimes -144000
# - And retired 35 hours ago (126000 seconds). # - And retired 37 hours ago (133200 seconds).
created=$(key_get KEY1 CREATED) created=$(key_get KEY1 CREATED)
set_addkeytime "KEY1" "RETIRED" "${created}" -126000 set_addkeytime "KEY1" "RETIRED" "${created}" -133200
retired=$(key_get KEY1 RETIRED) retired=$(key_get KEY1 RETIRED)
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}" set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
# - The new key was published 38 hours ago. # - The new key was published 40 hours ago.
created=$(key_get KEY2 CREATED) created=$(key_get KEY2 CREATED)
set_addkeytime "KEY2" "PUBLISHED" "${created}" -136800 set_addkeytime "KEY2" "PUBLISHED" "${created}" -144000
set_addkeytime "KEY2" "ACTIVE" "${created}" -136800 set_addkeytime "KEY2" "ACTIVE" "${created}" -144000
published=$(key_get KEY2 PUBLISHED) published=$(key_get KEY2 PUBLISHED)
set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub} set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub}
@@ -5220,12 +5225,12 @@ check_subdomain
dnssec_verify dnssec_verify
# Next key event is when the RSASHA1 signatures become HIDDEN. This happens # Next key event is when the RSASHA1 signatures become HIDDEN. This happens
# after the max-zone-ttl plus zone propagation delay (6h + 1h) minus the # after the max-zone-ttl plus zone propagation delay plus retire safety
# time already passed since the UNRETENTIVE state has been reached (2h): # (6h + 1h + 2h) minus the time already passed since the UNRETENTIVE state has
# 7h - 2h = 5h = 18000 seconds. Prevent intermittent false positives on slow # been reached (2h): 9h - 2h = 7h = 25200 seconds. Prevent intermittent
# platforms by subtracting the number of seconds which passed between key # false positives on slow platforms by subtracting the number of seconds
# creation and invoking 'rndc reconfig'. # which passed between key creation and invoking 'rndc reconfig'.
next_time=$((18000 - time_passed)) next_time=$((25200 - time_passed))
check_next_key_event $next_time check_next_key_event $next_time
# #
@@ -5243,17 +5248,17 @@ wait_for_done_signing
check_dnssecstatus "$SERVER" "$POLICY" "$ZONE" check_dnssecstatus "$SERVER" "$POLICY" "$ZONE"
# Set expected key times: # Set expected key times:
# - The old keys were activated 45 hours ago (162000 seconds) # - The old keys were activated 47 hours ago (169200 seconds)
csk_rollover_predecessor_keytimes -162000 csk_rollover_predecessor_keytimes -169200
# - And retired 42 hours ago (151200 seconds). # - And retired 44 hours ago (158400 seconds).
created=$(key_get KEY1 CREATED) created=$(key_get KEY1 CREATED)
set_addkeytime "KEY1" "RETIRED" "${created}" -151200 set_addkeytime "KEY1" "RETIRED" "${created}" -158400
retired=$(key_get KEY1 RETIRED) retired=$(key_get KEY1 RETIRED)
set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}" set_addkeytime "KEY1" "REMOVED" "${retired}" "${IretCSK}"
# - The new key was published 47 hours ago. # - The new key was published 47 hours ago.
created=$(key_get KEY2 CREATED) created=$(key_get KEY2 CREATED)
set_addkeytime "KEY2" "PUBLISHED" "${created}" -162000 set_addkeytime "KEY2" "PUBLISHED" "${created}" -169200
set_addkeytime "KEY2" "ACTIVE" "${created}" -162000 set_addkeytime "KEY2" "ACTIVE" "${created}" -169200
published=$(key_get KEY2 PUBLISHED) published=$(key_get KEY2 PUBLISHED)
set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub} set_addkeytime "KEY2" "SYNCPUBLISH" "${published}" ${Ipub}
@@ -1,17 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 30 SOA ns2.good. hostmaster.arpa. 2018050100 1 1 1 1
@ 30 NS ns2.good.
8.2.6.0 60 NS ns3.good.
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0 1 PTR nee.com.
+436 -91
View File
@@ -1,111 +1,456 @@
""" # Copyright (C) Internet Systems Consortium, Inc. ("ISC")
Copyright (C) Internet Systems Consortium, Inc. ("ISC") #
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
SPDX-License-Identifier: MPL-2.0 from __future__ import print_function
import os
import sys
import signal
import socket
import select
from datetime import datetime, timedelta
import time
import functools
This Source Code Form is subject to the terms of the Mozilla Public import dns, dns.message, dns.query, dns.flags
License, v. 2.0. If a copy of the MPL was not distributed with this from dns.rdatatype import *
file, you can obtain one at https://mozilla.org/MPL/2.0/. from dns.rdataclass import *
from dns.rcode import *
See the COPYRIGHT file distributed with this work for additional from dns.name import *
information regarding copyright ownership.
"""
from typing import AsyncGenerator
import dns.message
import dns.name
import dns.rcode
import dns.rdataclass
import dns.rdatatype
from isctest.asyncserver import (
AsyncDnsServer,
DnsResponseSend,
DomainHandler,
QueryContext,
ResponseAction,
)
from qmin_ans import (
DelayedResponseHandler,
EntRcodeChanger,
QueryLogHandler,
log_query,
)
class QueryLogger(QueryLogHandler): # Log query to file
domains = ["1.0.0.2.ip6.arpa.", "fwd.", "good."] def logquery(type, qname):
with open("qlog", "a") as f:
f.write("%s %s\n", type, qname)
class BadHandler(EntRcodeChanger): def endswith(domain, labels):
domains = ["bad."] return domain.endswith("." + labels) or domain == labels
rcode = dns.rcode.NXDOMAIN
class UglyHandler(EntRcodeChanger): ############################################################################
domains = ["ugly."] # Respond to a DNS query.
rcode = dns.rcode.FORMERR # For good. it serves:
# ns2.good. IN A 10.53.0.2
# zoop.boing.good. NS ns3.good.
# ns3.good. IN A 10.53.0.3
# too.many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.good. A 192.0.2.2
# it responds properly (with NODATA empty response) to non-empty terminals
#
# For slow. it works the same as for good., but each response is delayed by 400 milliseconds
#
# For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals
#
# For ugly. it works the same as for good., but returns garbage to non-empty terminals
#
# For 1.0.0.2.ip6.arpa it serves
# 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. IN PTR nee.com.
# 8.2.6.0.1.0.0.2.ip6.arpa IN NS ns3.good
# 1.0.0.2.ip6.arpa. IN NS ns2.good
# ip6.arpa. IN NS ns2.good
#
# For stale. it serves:
# a.b. NS ns.a.b.stale.
# ns.a.b.stale. IN A 10.53.0.3
# b. NS ns.b.stale.
# ns.b.stale. IN A 10.53.0.4
############################################################################
def create_response(msg):
m = dns.message.from_wire(msg)
qname = m.question[0].name.to_text()
lqname = qname.lower()
labels = lqname.split(".")
# get qtype
rrtype = m.question[0].rdtype
typename = dns.rdatatype.to_text(rrtype)
if typename == "A" or typename == "AAAA":
typename = "ADDR"
bad = False
ugly = False
slow = False
# log this query
with open("query.log", "a") as f:
f.write("%s %s\n" % (typename, lqname))
print("%s %s" % (typename, lqname), end=" ")
r = dns.message.make_response(m)
r.set_rcode(NOERROR)
if endswith(lqname, "1.0.0.2.ip6.arpa."):
# Direct query - give direct answer
if endswith(lqname, "8.2.6.0.1.0.0.2.ip6.arpa."):
# Delegate to ns3
r.authority.append(
dns.rrset.from_text(
"8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns3.good."
)
)
r.additional.append(
dns.rrset.from_text("ns3.good.", 60, IN, A, "10.53.0.3")
)
elif (
lqname
== "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa."
and rrtype == PTR
):
# Direct query - give direct answer
r.answer.append(
dns.rrset.from_text(
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.",
1,
IN,
PTR,
"nee.com.",
)
)
r.flags |= dns.flags.AA
elif lqname == "1.0.0.2.ip6.arpa." and rrtype == NS:
# NS query at the apex
r.answer.append(
dns.rrset.from_text("1.0.0.2.ip6.arpa.", 30, IN, NS, "ns2.good.")
)
r.flags |= dns.flags.AA
elif endswith(
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.",
lqname,
):
# NODATA answer
r.authority.append(
dns.rrset.from_text(
"1.0.0.2.ip6.arpa.",
30,
IN,
SOA,
"ns2.good. hostmaster.arpa. 2018050100 1 1 1 1",
)
)
else:
# NXDOMAIN
r.authority.append(
dns.rrset.from_text(
"1.0.0.2.ip6.arpa.",
30,
IN,
SOA,
"ns2.good. hostmaster.arpa. 2018050100 1 1 1 1",
)
)
r.set_rcode(NXDOMAIN)
return r
elif endswith(lqname, "ip6.arpa."):
if lqname == "ip6.arpa." and rrtype == NS:
# NS query at the apex
r.answer.append(dns.rrset.from_text("ip6.arpa.", 30, IN, NS, "ns2.good."))
r.flags |= dns.flags.AA
elif endswith("1.0.0.2.ip6.arpa.", lqname):
# NODATA answer
r.authority.append(
dns.rrset.from_text(
"ip6.arpa.",
30,
IN,
SOA,
"ns2.good. hostmaster.arpa. 2018050100 1 1 1 1",
)
)
else:
# NXDOMAIN
r.authority.append(
dns.rrset.from_text(
"ip6.arpa.",
30,
IN,
SOA,
"ns2.good. hostmaster.arpa. 2018050100 1 1 1 1",
)
)
r.set_rcode(NXDOMAIN)
return r
elif endswith(lqname, "stale."):
if endswith(lqname, "a.b.stale."):
# Delegate to ns.a.b.stale.
r.authority.append(
dns.rrset.from_text("a.b.stale.", 2, IN, NS, "ns.a.b.stale.")
)
r.additional.append(
dns.rrset.from_text("ns.a.b.stale.", 2, IN, A, "10.53.0.3")
)
elif endswith(lqname, "b.stale."):
# Delegate to ns.b.stale.
r.authority.append(
dns.rrset.from_text("b.stale.", 2, IN, NS, "ns.b.stale.")
)
r.additional.append(
dns.rrset.from_text("ns.b.stale.", 2, IN, A, "10.53.0.4")
)
elif lqname == "stale." and rrtype == NS:
# NS query at the apex.
r.answer.append(dns.rrset.from_text("stale.", 2, IN, NS, "ns2.stale."))
r.flags |= dns.flags.AA
elif lqname == "stale." and rrtype == SOA:
# SOA query at the apex.
r.answer.append(
dns.rrset.from_text(
"stale.", 2, IN, SOA, "ns2.stale. hostmaster.stale. 1 2 3 4 5"
)
)
r.flags |= dns.flags.AA
elif lqname == "stale.":
# NODATA answer
r.authority.append(
dns.rrset.from_text(
"stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5"
)
)
r.flags |= dns.flags.AA
elif lqname == "ns2.stale.":
if rrtype == A:
r.additional.append(
dns.rrset.from_text("ns.b.stale.", 2, IN, A, "10.53.0.2")
)
else:
r.authority.append(
dns.rrset.from_text(
"stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5"
)
)
r.flags |= dns.flags.AA
else:
# NXDOMAIN
r.authority.append(
dns.rrset.from_text(
"stale.", 2, IN, SOA, "ns2.stale. hostmaster.arpa. 1 2 3 4 5"
)
)
r.set_rcode(NXDOMAIN)
return r
elif endswith(lqname, "bad."):
bad = True
suffix = "bad."
lqname = lqname[:-4]
elif endswith(lqname, "ugly."):
ugly = True
suffix = "ugly."
lqname = lqname[:-5]
elif endswith(lqname, "good."):
suffix = "good."
lqname = lqname[:-5]
elif endswith(lqname, "slow."):
slow = True
suffix = "slow."
lqname = lqname[:-5]
elif endswith(lqname, "fwd."):
suffix = "fwd."
lqname = lqname[:-4]
else:
r.set_rcode(REFUSED)
return r
# Good/bad/ugly differs only in how we treat non-empty terminals
if endswith(lqname, "zoop.boing."):
r.authority.append(
dns.rrset.from_text("zoop.boing." + suffix, 1, IN, NS, "ns3." + suffix)
)
elif (
lqname == "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z."
and rrtype == A
):
r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.2"))
r.flags |= dns.flags.AA
elif lqname == "" and rrtype == NS:
r.answer.append(dns.rrset.from_text(suffix, 30, IN, NS, "ns2." + suffix))
r.flags |= dns.flags.AA
elif lqname == "ns2.":
r.flags |= dns.flags.AA
if rrtype == A:
r.answer.append(
dns.rrset.from_text("ns2." + suffix, 30, IN, A, "10.53.0.2")
)
elif rrtype == AAAA:
r.answer.append(
dns.rrset.from_text(
"ns2." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::2"
)
)
else:
r.authority.append(
dns.rrset.from_text(
suffix,
30,
IN,
SOA,
"ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1",
)
)
elif lqname == "ns3.":
r.flags |= dns.flags.AA
if rrtype == A:
r.answer.append(
dns.rrset.from_text("ns3." + suffix, 30, IN, A, "10.53.0.3")
)
elif lqname == "ns3." and rrtype == AAAA:
r.answer.append(
dns.rrset.from_text(
"ns3." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::3"
)
)
else:
r.authority.append(
dns.rrset.from_text(
suffix,
30,
IN,
SOA,
"ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1",
)
)
elif lqname == "ns4.":
r.flags |= dns.flags.AA
if rrtype == A:
r.answer.append(
dns.rrset.from_text("ns4." + suffix, 30, IN, A, "10.53.0.4")
)
elif rrtype == AAAA:
r.answer.append(
dns.rrset.from_text(
"ns4." + suffix, 30, IN, AAAA, "fd92:7065:b8e:ffff::4"
)
)
else:
r.authority.append(
dns.rrset.from_text(
suffix,
30,
IN,
SOA,
"ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1",
)
)
elif lqname == "a.bit.longer.ns.name." and rrtype == A:
r.answer.append(
dns.rrset.from_text("a.bit.longer.ns.name." + suffix, 1, IN, A, "10.53.0.4")
)
r.flags |= dns.flags.AA
elif lqname == "a.bit.longer.ns.name." and rrtype == AAAA:
r.answer.append(
dns.rrset.from_text(
"a.bit.longer.ns.name." + suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::4"
)
)
r.flags |= dns.flags.AA
else:
r.authority.append(
dns.rrset.from_text(
suffix,
1,
IN,
SOA,
"ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1",
)
)
if bad or not (
endswith("icky.icky.icky.ptang.zoop.boing.", lqname)
or endswith(
"many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.",
lqname,
)
or endswith("a.bit.longer.ns.name.", lqname)
):
r.set_rcode(NXDOMAIN)
if ugly:
r.set_rcode(FORMERR)
if slow:
time.sleep(0.2)
return r
class SlowHandler(DelayedResponseHandler): def sigterm(signum, frame):
domains = ["slow."] print("Shutting down now...")
delay = 0.2 os.remove("ans.pid")
running = False
sys.exit(0)
def send_delegation( ############################################################################
qctx: QueryContext, zone_cut: dns.name.Name, target_addr: str # Main
) -> ResponseAction: #
""" # Set up responder and control channel, open the pid file, and start
Delegate `zone_cut` to a single in-bailiwick name server, `ns.<zone_cut>`, # the main loop, listening for queries on the query channel or commands
with a single IPv4 glue record (provided in `target_addr`) included in the # on the control channel and acting on them.
ADDITIONAL section. ############################################################################
""" ip4 = "10.53.0.2"
ns_name = "ns." + zone_cut.to_text() ip6 = "fd92:7065:b8e:ffff::2"
ns_rrset = dns.rrset.from_text(
zone_cut, 2, dns.rdataclass.IN, dns.rdatatype.NS, ns_name
)
a_rrset = dns.rrset.from_text(
ns_name, 2, dns.rdataclass.IN, dns.rdatatype.A, target_addr
)
response = dns.message.make_response(qctx.query) try:
response.set_rcode(dns.rcode.NOERROR) port = int(os.environ["PORT"])
response.authority.append(ns_rrset) except:
response.additional.append(a_rrset) port = 5300
return DnsResponseSend(response, authoritative=False) query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
query4_socket.bind((ip4, port))
havev6 = True
try:
query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
try:
query6_socket.bind((ip6, port))
except:
query6_socket.close()
havev6 = False
except:
havev6 = False
class StaleHandler(DomainHandler): signal.signal(signal.SIGTERM, sigterm)
"""
`a.b.stale` is a subdomain of `b.stale` and these two subdomains need to be
delegated to different name servers. Therefore, their delegations cannot
be placed in the zone file because the zone cut at `b.stale` would occlude
the one at `a.b.stale`. Generate these delegations dynamically depending
on the QNAME.
"""
domains = ["stale."] f = open("ans.pid", "w")
pid = os.getpid()
print(pid, file=f)
f.close()
async def get_responses( running = True
self, qctx: QueryContext
) -> AsyncGenerator[ResponseAction, None]:
log_query(qctx)
a_b_stale = dns.name.from_text("a.b.stale.")
b_stale = dns.name.from_text("b.stale.")
if qctx.qname.is_subdomain(a_b_stale):
yield send_delegation(qctx, a_b_stale, "10.53.0.3")
elif qctx.qname.is_subdomain(b_stale):
yield send_delegation(qctx, b_stale, "10.53.0.4")
print("Listening on %s port %d" % (ip4, port))
if havev6:
print("Listening on %s port %d" % (ip6, port))
print("Ctrl-c to quit")
if __name__ == "__main__": if havev6:
server = AsyncDnsServer() input = [query4_socket, query6_socket]
server.install_response_handler(QueryLogger()) else:
server.install_response_handler(BadHandler()) input = [query4_socket]
server.install_response_handler(UglyHandler())
server.install_response_handler(SlowHandler()) while running:
server.install_response_handler(StaleHandler()) try:
server.run() inputready, outputready, exceptready = select.select(input, [], [])
except select.error as e:
break
except socket.error as e:
break
except KeyboardInterrupt:
break
for s in inputready:
if s == query4_socket or s == query6_socket:
print(
"Query received on %s" % (ip4 if s == query4_socket else ip6), end=" "
)
# Handle incoming queries
msg = s.recvfrom(65535)
rsp = create_response(msg[0])
if rsp:
print(dns.rcode.to_text(rsp.rcode()))
s.sendto(rsp.to_wire(), msg[1])
else:
print("NO RESPONSE")
if not running:
break
-1
View File
@@ -1 +0,0 @@
good.db
-1
View File
@@ -1 +0,0 @@
good.db
-26
View File
@@ -1,26 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns2 hostmaster.arpa. 2018050100 1 1 1 1
@ 30 NS ns2
ns2 30 A 10.53.0.2
30 AAAA fd92:7065:b8e:ffff::2
zoop.boing 30 NS ns3
ns3 30 A 10.53.0.3
30 AAAA fd92:7065:b8e:ffff::3
ns4 30 A 10.53.0.4
30 AAAA fd92:7065:b8e:ffff::4
a.bit.longer.ns.name 1 A 10.53.0.4
1 AAAA fd92:7065:b8e:ffff::4
-1
View File
@@ -1 +0,0 @@
good.db
-15
View File
@@ -1,15 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 2 SOA ns2 hostmaster.stale. 1 2 3 4 5
@ 2 NS ns2
ns2 2 A 10.53.0.2
2 AAAA fd92:7065:b8e:ffff::2
-1
View File
@@ -1 +0,0 @@
good.db
@@ -1,15 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 30 SOA ns3.good. hostmaster.arpa. 2018050100 1 1 1 1
@ 30 NS ns3.good.
1.1.1.1 60 NS ns4.good.
-15
View File
@@ -1,15 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns hostmaster.a.b.stale. 1 2 3 4 5
@ 1 NS ns
@ 1 TXT "peekaboo"
ns 1 A 10.53.0.3
+273 -34
View File
@@ -1,46 +1,285 @@
""" # Copyright (C) Internet Systems Consortium, Inc. ("ISC")
Copyright (C) Internet Systems Consortium, Inc. ("ISC") #
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
SPDX-License-Identifier: MPL-2.0 from __future__ import print_function
import os
import sys
import signal
import socket
import select
from datetime import datetime, timedelta
import time
import functools
This Source Code Form is subject to the terms of the Mozilla Public import dns, dns.message, dns.query, dns.flags
License, v. 2.0. If a copy of the MPL was not distributed with this from dns.rdatatype import *
file, you can obtain one at https://mozilla.org/MPL/2.0/. from dns.rdataclass import *
from dns.rcode import *
See the COPYRIGHT file distributed with this work for additional from dns.name import *
information regarding copyright ownership.
"""
import dns.rcode
from isctest.asyncserver import AsyncDnsServer
from qmin_ans import DelayedResponseHandler, EntRcodeChanger, QueryLogHandler
class QueryLogger(QueryLogHandler): # Log query to file
domains = ["8.2.6.0.1.0.0.2.ip6.arpa.", "a.b.stale.", "zoop.boing.good."] def logquery(type, qname):
with open("qlog", "a") as f:
f.write("%s %s\n", type, qname)
class ZoopBoingBadHandler(EntRcodeChanger): def endswith(domain, labels):
domains = ["zoop.boing.bad."] return domain.endswith("." + labels) or domain == labels
rcode = dns.rcode.NXDOMAIN
class ZoopBoingUglyHandler(EntRcodeChanger): ############################################################################
domains = ["zoop.boing.ugly."] # Respond to a DNS query.
rcode = dns.rcode.FORMERR # For good. it serves:
# zoop.boing.good. NS ns3.good.
# icky.ptang.zoop.boing.good. NS a.bit.longer.ns.name.good.
# it responds properly (with NODATA empty response) to non-empty terminals
#
# For slow. it works the same as for good., but each response is delayed by 400 milliseconds
#
# For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals
#
# For ugly. it works the same as for good., but returns garbage to non-empty terminals
#
# For stale. it serves:
# a.b.stale. IN TXT peekaboo (resolver did not do qname minimization)
############################################################################
def create_response(msg):
m = dns.message.from_wire(msg)
qname = m.question[0].name.to_text()
lqname = qname.lower()
labels = lqname.split(".")
suffix = ""
# get qtype
rrtype = m.question[0].rdtype
typename = dns.rdatatype.to_text(rrtype)
if typename == "A" or typename == "AAAA":
typename = "ADDR"
bad = False
ugly = False
slow = False
# log this query
with open("query.log", "a") as f:
f.write("%s %s\n" % (typename, lqname))
print("%s %s" % (typename, lqname), end=" ")
r = dns.message.make_response(m)
r.set_rcode(NOERROR)
ip6req = False
if endswith(lqname, "bad."):
bad = True
suffix = "bad."
lqname = lqname[:-4]
elif endswith(lqname, "ugly."):
ugly = True
suffix = "ugly."
lqname = lqname[:-5]
elif endswith(lqname, "good."):
suffix = "good."
lqname = lqname[:-5]
elif endswith(lqname, "slow."):
slow = True
suffix = "slow."
lqname = lqname[:-5]
elif endswith(lqname, "8.2.6.0.1.0.0.2.ip6.arpa."):
ip6req = True
elif endswith(lqname, "a.b.stale."):
if lqname == "a.b.stale.":
r.flags |= dns.flags.AA
if rrtype == TXT:
# Direct query.
r.answer.append(dns.rrset.from_text(lqname, 1, IN, TXT, "peekaboo"))
elif rrtype == NS:
# NS a.b.
r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.a.b.stale."))
r.additional.append(
dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3")
)
elif rrtype == SOA:
# SOA a.b.
r.answer.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
)
)
else:
# NODATA.
r.authority.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
)
)
elif lqname == "ns.a.b.stale.":
r.flags |= dns.flags.AA
if rrtype == A:
r.answer.append(
dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3")
)
else:
r.authority.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
)
)
else:
r.flags |= dns.flags.AA
r.authority.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
)
)
r.set_rcode(NXDOMAIN)
# NXDOMAIN.
return r
else:
r.set_rcode(REFUSED)
return r
# Good/bad differs only in how we treat non-empty terminals
if lqname == "zoop.boing." and rrtype == NS:
r.answer.append(
dns.rrset.from_text(lqname + suffix, 1, IN, NS, "ns3." + suffix)
)
r.flags |= dns.flags.AA
elif endswith(lqname, "icky.ptang.zoop.boing."):
r.authority.append(
dns.rrset.from_text(
"icky.ptang.zoop.boing." + suffix,
1,
IN,
NS,
"a.bit.longer.ns.name." + suffix,
)
)
elif endswith("icky.ptang.zoop.boing.", lqname):
r.authority.append(
dns.rrset.from_text(
"zoop.boing." + suffix,
1,
IN,
SOA,
"ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1",
)
)
if bad:
r.set_rcode(NXDOMAIN)
if ugly:
r.set_rcode(FORMERR)
elif endswith(lqname, "zoop.boing."):
r.authority.append(
dns.rrset.from_text(
"zoop.boing." + suffix,
1,
IN,
SOA,
"ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1",
)
)
r.set_rcode(NXDOMAIN)
elif ip6req:
r.authority.append(
dns.rrset.from_text(
"1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", 60, IN, NS, "ns4.good."
)
)
r.additional.append(dns.rrset.from_text("ns4.good.", 60, IN, A, "10.53.0.4"))
else:
r.set_rcode(REFUSED)
if slow:
time.sleep(0.4)
return r
class ZoopBoingSlowHandler(DelayedResponseHandler): def sigterm(signum, frame):
domains = ["zoop.boing.slow."] print("Shutting down now...")
delay = 0.4 os.remove("ans.pid")
running = False
sys.exit(0)
if __name__ == "__main__": ############################################################################
server = AsyncDnsServer() # Main
server.install_response_handler(QueryLogger()) #
server.install_response_handler(ZoopBoingBadHandler()) # Set up responder and control channel, open the pid file, and start
server.install_response_handler(ZoopBoingUglyHandler()) # the main loop, listening for queries on the query channel or commands
server.install_response_handler(ZoopBoingSlowHandler()) # on the control channel and acting on them.
server.run() ############################################################################
ip4 = "10.53.0.3"
ip6 = "fd92:7065:b8e:ffff::3"
try:
port = int(os.environ["PORT"])
except:
port = 5300
query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
query4_socket.bind((ip4, port))
havev6 = True
try:
query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
try:
query6_socket.bind((ip6, port))
except:
query6_socket.close()
havev6 = False
except:
havev6 = False
signal.signal(signal.SIGTERM, sigterm)
f = open("ans.pid", "w")
pid = os.getpid()
print(pid, file=f)
f.close()
running = True
print("Listening on %s port %d" % (ip4, port))
if havev6:
print("Listening on %s port %d" % (ip6, port))
print("Ctrl-c to quit")
if havev6:
input = [query4_socket, query6_socket]
else:
input = [query4_socket]
while running:
try:
inputready, outputready, exceptready = select.select(input, [], [])
except select.error as e:
break
except socket.error as e:
break
except KeyboardInterrupt:
break
for s in inputready:
if s == query4_socket or s == query6_socket:
print(
"Query received on %s" % (ip4 if s == query4_socket else ip6), end=" "
)
# Handle incoming queries
msg = s.recvfrom(65535)
rsp = create_response(msg[0])
if rsp:
print(dns.rcode.to_text(rsp.rcode()))
s.sendto(rsp.to_wire(), msg[1])
else:
print("NO RESPONSE")
if not running:
break
@@ -1,14 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns3.bad. hostmaster.arpa. 2018050100 1 1 1 1
@ 1 NS ns3.bad.
icky.ptang 1 NS a.bit.longer.ns.name.bad.
@@ -1,14 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns3.good. hostmaster.arpa. 2018050100 1 1 1 1
@ 1 NS ns3.good.
icky.ptang 1 NS a.bit.longer.ns.name.good.
@@ -1,14 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns3.slow. hostmaster.arpa. 2018050100 1 1 1 1
@ 1 NS ns3.slow.
icky.ptang 1 NS a.bit.longer.ns.name.slow.
@@ -1,14 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns3.ugly. hostmaster.arpa. 2018050100 1 1 1 1
@ 1 NS ns3.ugly.
icky.ptang 1 NS a.bit.longer.ns.name.ugly.
@@ -1,15 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 30 SOA ns4.good. hostmaster.arpa. 2018050100 1 1 1 1
@ 30 NS ns4.good.
test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4 1 TXT "long_ip6_name"
-15
View File
@@ -1,15 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns hostmaster.a.b.stale. 1 2 3 4 5
@ 1 NS ns
ns 1 A 10.53.0.4
@ 1 TXT "hooray"
+331 -79
View File
@@ -1,93 +1,345 @@
""" # Copyright (C) Internet Systems Consortium, Inc. ("ISC")
Copyright (C) Internet Systems Consortium, Inc. ("ISC") #
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
SPDX-License-Identifier: MPL-2.0 from __future__ import print_function
import os
import sys
import signal
import socket
import select
from datetime import datetime, timedelta
import time
import functools
This Source Code Form is subject to the terms of the Mozilla Public import dns, dns.message, dns.query, dns.flags
License, v. 2.0. If a copy of the MPL was not distributed with this from dns.rdatatype import *
file, you can obtain one at https://mozilla.org/MPL/2.0/. from dns.rdataclass import *
from dns.rcode import *
See the COPYRIGHT file distributed with this work for additional from dns.name import *
information regarding copyright ownership.
"""
from typing import AsyncGenerator
import dns.rcode
from isctest.asyncserver import (
AsyncDnsServer,
DnsResponseSend,
DomainHandler,
QueryContext,
ResponseAction,
)
from qmin_ans import DelayedResponseHandler, EntRcodeChanger, QueryLogHandler, log_query
class QueryLogger(QueryLogHandler): # Log query to file
domains = [ def logquery(type, qname):
"1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.", with open("qlog", "a") as f:
"icky.ptang.zoop.boing.good.", f.write("%s %s\n", type, qname)
]
class StaleHandler(DomainHandler): def endswith(domain, labels):
""" return domain.endswith("." + labels) or domain == labels
The test code relies on this server returning non-minimal (i.e. including
address records in the ADDITIONAL section) responses to NS queries for
`b.stale` and `a.b.stale`. While this logic (returning non-minimal
responses to NS queries) could be implemented in AsyncDnsServer itself,
doing so breaks a lot of other checks in this system test. Therefore, only
these two zones behave in this particular way, thanks to a custom response
handler implemented below.
"""
domains = ["b.stale", "a.b.stale"]
async def get_responses(
self, qctx: QueryContext
) -> AsyncGenerator[ResponseAction, None]:
log_query(qctx)
if qctx.qtype == dns.rdatatype.NS:
assert qctx.zone
assert qctx.response.answer[0]
for nameserver in qctx.response.answer[0]:
if not nameserver.target.is_subdomain(qctx.response.answer[0].name):
continue
glue_a = qctx.zone.get_rrset(nameserver.target, dns.rdatatype.A)
if glue_a:
qctx.response.additional.append(glue_a)
glue_aaaa = qctx.zone.get_rrset(nameserver.target, dns.rdatatype.AAAA)
if glue_aaaa:
qctx.response.additional.append(glue_aaaa)
yield DnsResponseSend(qctx.response)
class IckyPtangZoopBoingBadHandler(EntRcodeChanger): ############################################################################
domains = ["icky.ptang.zoop.boing.bad."] # Respond to a DNS query.
rcode = dns.rcode.NXDOMAIN # For good. it serves:
# icky.ptang.zoop.boing.good. NS a.bit.longer.ns.name.
# icky.icky.icky.ptang.zoop.boing.good. A 192.0.2.1
# more.icky.icky.icky.ptang.zoop.boing.good. A 192.0.2.2
# it responds properly (with NODATA empty response) to non-empty terminals
#
# For slow. it works the same as for good., but each response is delayed by 400 milliseconds
#
# For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals
#
# For ugly. it works the same as for good., but returns garbage to non-empty terminals
#
# For stale. it serves:
# a.b.stale. IN TXT hooray (resolver did do qname minimization)
############################################################################
def create_response(msg):
m = dns.message.from_wire(msg)
qname = m.question[0].name.to_text()
lqname = qname.lower()
labels = lqname.split(".")
suffix = ""
# get qtype
rrtype = m.question[0].rdtype
typename = dns.rdatatype.to_text(rrtype)
if typename == "A" or typename == "AAAA":
typename = "ADDR"
bad = False
slow = False
ugly = False
# log this query
with open("query.log", "a") as f:
f.write("%s %s\n" % (typename, lqname))
print("%s %s" % (typename, lqname), end=" ")
r = dns.message.make_response(m)
r.set_rcode(NOERROR)
ip6req = False
if endswith(lqname, "bad."):
bad = True
suffix = "bad."
lqname = lqname[:-4]
elif endswith(lqname, "ugly."):
ugly = True
suffix = "ugly."
lqname = lqname[:-5]
elif endswith(lqname, "good."):
suffix = "good."
lqname = lqname[:-5]
elif endswith(lqname, "slow."):
slow = True
suffix = "slow."
lqname = lqname[:-5]
elif endswith(lqname, "1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa."):
ip6req = True
elif endswith(lqname, "b.stale."):
if lqname == "a.b.stale.":
r.flags |= dns.flags.AA
if rrtype == TXT:
# Direct query.
r.answer.append(dns.rrset.from_text(lqname, 1, IN, TXT, "hooray"))
elif rrtype == NS:
# NS a.b.
# This is only returned if a query for b.stale/NS has been made
r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.a.b.stale."))
r.additional.append(
dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.4")
)
elif rrtype == SOA:
# SOA a.b.
r.answer.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
)
)
else:
# NODATA.
r.authority.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
)
)
elif lqname == "ns.a.b.stale.":
r.flags |= dns.flags.AA
if rrtype == A:
r.answer.append(
dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.4")
)
else:
# NODATA.
r.authority.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "a.b.stale. hostmaster.a.b.stale. 1 2 3 4 5"
)
)
elif lqname == "b.stale.":
r.flags |= dns.flags.AA
if rrtype == NS:
# NS b.
r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.b.stale."))
r.additional.append(
dns.rrset.from_text("ns.b.stale.", 1, IN, A, "10.53.0.4")
)
elif rrtype == SOA:
# SOA b.
r.answer.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5"
)
)
else:
# NODATA.
r.authority.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5"
)
)
elif lqname == "ns.b.stale.":
r.flags |= dns.flags.AA
if rrtype == A:
# SOA a.b.
r.answer.append(
dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.4")
)
else:
# NODATA.
r.authority.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5"
)
)
else:
r.authority.append(
dns.rrset.from_text(
lqname, 1, IN, SOA, "b.stale. hostmaster.b.stale. 1 2 3 4 5"
)
)
r.set_rcode(NXDOMAIN)
# NXDOMAIN.
return r
else:
r.set_rcode(REFUSED)
return r
# Good/bad differs only in how we treat non-empty terminals
if lqname == "icky.icky.icky.ptang.zoop.boing." and rrtype == A:
r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.1"))
r.flags |= dns.flags.AA
elif lqname == "more.icky.icky.icky.ptang.zoop.boing." and rrtype == A:
r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.2"))
r.flags |= dns.flags.AA
elif lqname == "icky.ptang.zoop.boing." and rrtype == NS:
r.answer.append(
dns.rrset.from_text(
lqname + suffix, 1, IN, NS, "a.bit.longer.ns.name." + suffix
)
)
r.flags |= dns.flags.AA
elif endswith(lqname, "icky.ptang.zoop.boing."):
r.authority.append(
dns.rrset.from_text(
"icky.ptang.zoop.boing." + suffix,
1,
IN,
SOA,
"ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1",
)
)
if bad or not endswith("more.icky.icky.icky.ptang.zoop.boing.", lqname):
r.set_rcode(NXDOMAIN)
if ugly:
r.set_rcode(FORMERR)
elif ip6req:
r.flags |= dns.flags.AA
if (
lqname
== "test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa."
and rrtype == TXT
):
r.answer.append(
dns.rrset.from_text(
"test1.test2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.",
1,
IN,
TXT,
"long_ip6_name",
)
)
elif endswith(
"0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.0.9.4.1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.",
lqname,
):
# NODATA answer
r.authority.append(
dns.rrset.from_text(
"1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.",
60,
IN,
SOA,
"ns4.good. hostmaster.arpa. 2018050100 120 30 320 16",
)
)
else:
# NXDOMAIN
r.authority.append(
dns.rrset.from_text(
"1.1.1.1.8.2.6.0.1.0.0.2.ip6.arpa.",
60,
IN,
SOA,
"ns4.good. hostmaster.arpa. 2018050100 120 30 320 16",
)
)
r.set_rcode(NXDOMAIN)
else:
r.set_rcode(REFUSED)
if slow:
time.sleep(0.4)
return r
class IckyPtangZoopBoingUglyHandler(EntRcodeChanger): def sigterm(signum, frame):
domains = ["icky.ptang.zoop.boing.ugly."] print("Shutting down now...")
rcode = dns.rcode.FORMERR os.remove("ans.pid")
running = False
sys.exit(0)
class IckyPtangZoopBoingSlowHandler(DelayedResponseHandler): ############################################################################
domains = ["icky.ptang.zoop.boing.slow."] # Main
delay = 0.4 #
# Set up responder and control channel, open the pid file, and start
# the main loop, listening for queries on the query channel or commands
# on the control channel and acting on them.
############################################################################
ip4 = "10.53.0.4"
ip6 = "fd92:7065:b8e:ffff::4"
try:
port = int(os.environ["PORT"])
except:
port = 5300
if __name__ == "__main__": query4_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server = AsyncDnsServer() query4_socket.bind((ip4, port))
server.install_response_handler(QueryLogger())
server.install_response_handler(StaleHandler()) havev6 = True
server.install_response_handler(IckyPtangZoopBoingBadHandler()) try:
server.install_response_handler(IckyPtangZoopBoingUglyHandler()) query6_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
server.install_response_handler(IckyPtangZoopBoingSlowHandler()) try:
server.run() query6_socket.bind((ip6, port))
except:
query6_socket.close()
havev6 = False
except:
havev6 = False
signal.signal(signal.SIGTERM, sigterm)
f = open("ans.pid", "w")
pid = os.getpid()
print(pid, file=f)
f.close()
running = True
print("Listening on %s port %d" % (ip4, port))
if havev6:
print("Listening on %s port %d" % (ip6, port))
print("Ctrl-c to quit")
if havev6:
input = [query4_socket, query6_socket]
else:
input = [query4_socket]
while running:
try:
inputready, outputready, exceptready = select.select(input, [], [])
except select.error as e:
break
except socket.error as e:
break
except KeyboardInterrupt:
break
for s in inputready:
if s == query4_socket or s == query6_socket:
print(
"Query received on %s" % (ip4 if s == query4_socket else ip6), end=" "
)
# Handle incoming queries
msg = s.recvfrom(65535)
rsp = create_response(msg[0])
if rsp:
print(dns.rcode.to_text(rsp.rcode()))
s.sendto(rsp.to_wire(), msg[1])
else:
print("NO RESPONSE")
if not running:
break
-16
View File
@@ -1,16 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns hostmaster.b.stale. 1 2 3 4 5
@ 1 NS ns
ns 1 A 10.53.0.4
a 1 NS ns.a
ns.a 1 A 10.53.0.4
@@ -1,15 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns4.bad. hostmaster.arpa. 2018050100 1 1 1 1
@ 1 NS a.bit.longer.ns.name.bad.
icky.icky 1 A 192.0.2.1
more.icky.icky 1 A 192.0.2.2
@@ -1,15 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns4.good. hostmaster.arpa. 2018050100 1 1 1 1
@ 1 NS a.bit.longer.ns.name.good.
icky.icky 1 A 192.0.2.1
more.icky.icky 1 A 192.0.2.2
@@ -1,15 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns4.slow. hostmaster.arpa. 2018050100 1 1 1 1
@ 1 NS a.bit.longer.ns.name.slow.
icky.icky 1 A 192.0.2.1
more.icky.icky 1 A 192.0.2.2
@@ -1,15 +0,0 @@
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; SPDX-License-Identifier: MPL-2.0
;
; 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 https://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
@ 1 SOA ns4.ugly. hostmaster.arpa. 2018050100 1 1 1 1
@ 1 NS a.bit.longer.ns.name.ugly.
icky.icky 1 A 192.0.2.1
more.icky.icky 1 A 192.0.2.2
-107
View File
@@ -1,107 +0,0 @@
"""
Copyright (C) Internet Systems Consortium, Inc. ("ISC")
SPDX-License-Identifier: MPL-2.0
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 https://mozilla.org/MPL/2.0/.
See the COPYRIGHT file distributed with this work for additional
information regarding copyright ownership.
"""
from typing import AsyncGenerator
import abc
import dns.rcode
import dns.rdataclass
import dns.rdatatype
from isctest.asyncserver import (
DnsResponseSend,
DomainHandler,
QueryContext,
ResponseAction,
)
from isctest.compat import dns_rcode
def log_query(qctx: QueryContext) -> None:
"""
Log a received DNS query to a text file inspected by `tests.sh`. AAAA and
A queries are logged identically because the relative order in which they
are received does not matter.
"""
qname = qctx.qname.to_text()
qtype = dns.rdatatype.to_text(qctx.qtype)
if qtype in ("A", "AAAA"):
qtype = "ADDR"
with open("query.log", "a", encoding="utf-8") as query_log:
print(f"{qtype} {qname}", file=query_log)
class QueryLogHandler(DomainHandler):
"""
Log all received DNS queries to a text file. Use the zone file for
preparing responses.
"""
async def get_responses(
self, qctx: QueryContext
) -> AsyncGenerator[ResponseAction, None]:
log_query(qctx)
yield DnsResponseSend(qctx.response)
class EntRcodeChanger(DomainHandler):
"""
Log all received DNS queries to a text file. Use the zone file for
preparing responses, but override the RCODE returned for empty
non-terminals (ENTs) to the value specified by the child class. This
emulates broken authoritative servers.
"""
@property
@abc.abstractmethod
def rcode(self) -> dns_rcode:
raise NotImplementedError
async def get_responses(
self, qctx: QueryContext
) -> AsyncGenerator[ResponseAction, None]:
assert qctx.zone
log_query(qctx)
if (
qctx.response.rcode() == dns.rcode.NOERROR
and not qctx.response.answer
and qctx.response.authority
and qctx.response.authority[0].rdtype == dns.rdatatype.SOA
and not qctx.zone.get_node(qctx.qname)
):
qctx.response.set_rcode(self.rcode)
yield DnsResponseSend(qctx.response)
class DelayedResponseHandler(DomainHandler):
"""
Log all received DNS queries to a text file. Use the zone file for
preparing responses, but delay sending every answer by the amount of time
specified (in seconds) by the child class. This emulates network delays.
"""
@property
@abc.abstractmethod
def delay(self) -> float:
raise NotImplementedError
async def get_responses(
self, qctx: QueryContext
) -> AsyncGenerator[ResponseAction, None]:
log_query(qctx)
yield DnsResponseSend(qctx.response, delay=self.delay)
-20
View File
@@ -43,12 +43,6 @@ grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret)) status=$((status + ret))
rndccmd 10.53.0.1 stats || ret=1 # Get the responses, RTT and timeout statistics before the following timeout tests
grep -F 'responses received' ns1/named.stats >ns1/named.stats.responses-before || true
grep -F 'queries with RTT' ns1/named.stats >ns1/named.stats.rtt-before || true
grep -F 'query timeouts' ns1/named.stats >ns1/named.stats.timeouts-before || true
mv ns1/named.stats ns1/named.stats-before
# 'resolver-query-timeout' is set to 5 seconds in ns1, so dig with a lower # 'resolver-query-timeout' is set to 5 seconds in ns1, so dig with a lower
# timeout value should give up earlier than that. # timeout value should give up earlier than that.
n=$((n + 1)) n=$((n + 1))
@@ -72,20 +66,6 @@ grep -F "EDE: 22 (No Reachable Authority)" dig.out.ns1.test${n} >/dev/null || re
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret)) status=$((status + ret))
n=$((n + 1))
echo_i "checking that the timeout didn't skew the resolver responses counters and did update the timeout counter ($n)"
ret=0
rndccmd 10.53.0.1 stats || ret=1
grep -F 'responses received' ns1/named.stats >ns1/named.stats.responses-after || true
grep -F 'queries with RTT' ns1/named.stats >ns1/named.stats.rtt-after || true
grep -F 'query timeouts' ns1/named.stats >ns1/named.stats.timeouts-after || true
mv ns1/named.stats ns1/named.stats-after
diff ns1/named.stats.responses-before ns1/named.stats.responses-after >/dev/null || ret=1
diff ns1/named.stats.rtt-before ns1/named.stats.rtt-after >/dev/null || ret=1
diff ns1/named.stats.timeouts-before ns1/named.stats.timeouts-after >/dev/null && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
# 'resolver-query-timeout' is set to 5 seconds in ns1, so named should # 'resolver-query-timeout' is set to 5 seconds in ns1, so named should
# interrupt the non-responsive query and send a SERVFAIL answer before dig's # interrupt the non-responsive query and send a SERVFAIL answer before dig's
# own timeout fires, which is set to 7 seconds. This time, exampleudp.net is # own timeout fires, which is set to 7 seconds. This time, exampleudp.net is
@@ -21,7 +21,6 @@ pytestmark = pytest.mark.extra_artifacts(
"nextpart.out.*", "nextpart.out.*",
"ans*/ans.run", "ans*/ans.run",
"ans*/query.log", "ans*/query.log",
"ns1/named.stats*",
"ns4/tld.db", "ns4/tld.db",
"ns5/trusted.conf", "ns5/trusted.conf",
"ns6/K*", "ns6/K*",
+2 -3
View File
@@ -264,8 +264,7 @@ sub construct_ns_command {
foreach my $t_option( foreach my $t_option(
"dropedns", "ednsformerr", "ednsnotimp", "ednsrefused", "dropedns", "ednsformerr", "ednsnotimp", "ednsrefused",
"cookiealwaysvalid", "noaa", "noedns", "nosoa", "noaa", "noedns", "nosoa", "maxudp512", "maxudp1460",
"maxudp512", "maxudp1460",
) { ) {
if (-e "$testdir/$server/named.$t_option") { if (-e "$testdir/$server/named.$t_option") {
$command .= "-T $t_option " $command .= "-T $t_option "
@@ -324,7 +323,7 @@ sub construct_ans_command {
} }
if (-e "$testdir/$server/ans.py") { if (-e "$testdir/$server/ans.py") {
$ENV{'PYTHONPATH'} = $testdir . ":" . $builddir; $ENV{'PYTHONPATH'} = $testdir . ":" . $ENV{'srcdir'};
$command = "$PYTHON -u ans.py 10.53.0.$n $queryport"; $command = "$PYTHON -u ans.py 10.53.0.$n $queryport";
} elsif (-e "$testdir/$server/ans.pl") { } elsif (-e "$testdir/$server/ans.pl") {
$command = "$PERL ans.pl"; $command = "$PERL ans.pl";
-1
View File
@@ -18,7 +18,6 @@ Changelog
development. Regular users should refer to :ref:`Release Notes <relnotes>` development. Regular users should refer to :ref:`Release Notes <relnotes>`
for changes relevant to them. for changes relevant to them.
.. include:: ../changelog/changelog-9.21.6.rst
.. include:: ../changelog/changelog-9.21.5.rst .. include:: ../changelog/changelog-9.21.5.rst
.. include:: ../changelog/changelog-9.21.4.rst .. include:: ../changelog/changelog-9.21.4.rst
.. include:: ../changelog/changelog-9.21.3.rst .. include:: ../changelog/changelog-9.21.3.rst
-1
View File
@@ -218,7 +218,6 @@ latex_logo = "isc-logo.pdf"
linkcheck_timeout = 10 linkcheck_timeout = 10
linkcheck_ignore = [ linkcheck_ignore = [
"http://127.0.0.1", "http://127.0.0.1",
"https://dl.acm.org",
"https://gitlab.isc.org", "https://gitlab.isc.org",
"https://kb.isc.org", "https://kb.isc.org",
"https://simpleicon.com/", "https://simpleicon.com/",
-1
View File
@@ -47,7 +47,6 @@ The list of known issues affecting the latest version in the 9.21 branch can be
found at found at
https://gitlab.isc.org/isc-projects/bind9/-/wikis/Known-Issues-in-BIND-9.21 https://gitlab.isc.org/isc-projects/bind9/-/wikis/Known-Issues-in-BIND-9.21
.. include:: ../notes/notes-9.21.6.rst
.. include:: ../notes/notes-9.21.5.rst .. include:: ../notes/notes-9.21.5.rst
.. include:: ../notes/notes-9.21.4.rst .. include:: ../notes/notes-9.21.4.rst
.. include:: ../notes/notes-9.21.3.rst .. include:: ../notes/notes-9.21.3.rst
-478
View File
@@ -1,478 +0,0 @@
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
..
.. SPDX-License-Identifier: MPL-2.0
..
.. 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 https://mozilla.org/MPL/2.0/.
..
.. See the COPYRIGHT file distributed with this work for additional
.. information regarding copyright ownership.
BIND 9.21.6
-----------
New Features
~~~~~~~~~~~~
- Implement the min-transfer-rate-in configuration option.
``a282f1ba3f``
A new option 'min-transfer-rate-in <bytes> <minutes>' has been added
to the view and zone configurations. It can abort incoming zone
transfers which run very slowly due to network related issues, for
example. The default value is set to 10240 bytes in 5 minutes.
:gl:`#3914` :gl:`!9098`
- Add digest methods for SIG and RRSIG. ``fd48df20f3``
ZONEMD digests RRSIG records and potentially digests SIG record. Add
digests methods for both record types. :gl:`#5219` :gl:`!10217`
- Add HTTPS record query to host command line tool. ``d34414c47b``
The host command was extended to also query for the HTTPS RR type by
default. :gl:`!8642`
Removed Features
~~~~~~~~~~~~~~~~
- Clean up unnecessary code in qpcache. ``74c9ff384e``
Removed some code from the cache database implementation that was left
over from before it and the zone database implementation were
separated. :gl:`!9991`
- Cleanup isc/util.h header and friends. ``239712df16``
Cleanup short list macros from <isc/util.h>, remove two unused
headers, move locking macros to respective headers and use only the
C11 static assertion. :gl:`!10196`
- Remove check for the mandatory IPv6 support. ``daa9c17905``
IPv6 Advanced Socket API (:rfc:`3542`) is a hard requirement, remove
the autoconf check to speed up the ./configure run a little bit.
:gl:`!10201`
- Remove log initialization checks from named. ``1b3e7f52ec``
Logging initialization check is now redundant as there is a default
global log context created during libisc's constructor.
`isc_log` calls can safely be made at any time outside libisc's
constructor. :gl:`!10186`
Feature Changes
~~~~~~~~~~~~~~~
- Refactor and simplify isc_symtab. ``5559539eb0``
This commit does several changes to isc_symtab:
1. Rewrite the isc_symtab to internally use isc_hashmap instead of
hand-stiched hashtable.
2. Create a new isc_symtab_define_and_return() api, which returns
the already defined symvalue on ISC_R_EXISTS; this allows users of
the API to skip the isc_symtab_lookup()+isc_symtab_define() calls
and directly call isc_symtab_define_and_return().
3. Merge isccc_symtab into isc_symtab - the only missing function
was isccc_symtab_foreach() that was merged into isc_symtab API.
4. Add full set of unit tests for the isc_symtab API. :gl:`#5103`
:gl:`!9921`
- Drop malformed notify messages early instead of decompressing them.
``7fce7707db``
The DNS header shows if a message has multiple questions or invalid
NOTIFY sections. We can drop these messages early, right after parsing
the question. This matches RFC 9619 for multi-question messages and
Unbound's handling of NOTIFY. We still parse the question to include
it in our FORMERR response.
Add drop_msg_early() function to check for these conditions: -
Messages with more than one question, as required by RFC 9619 - NOTIFY
query messages containing answer sections (like Unbound) - NOTIFY
messages containing authority sections (like Unbound) :gl:`#5158`,
#3656 :gl:`!10056`
- Cleanup parts of the isc_mem API. ``4ba1ccfa2e``
This MR changes custom attach/detach implementation with refcount
macros, replaces isc_mem_destroy() with isc_mem_detach(), and does
various small cleanups. :gl:`!9456`
- Move the library initialization and shutdown to executables.
``6e0c1f151c``
Instead of relying on unreliable order of execution of the library
constructors and destructors, move them to individual binaries. The
advantage is that the execution time and order will remain constant
and will not depend on the dynamic load dependency solver.
:gl:`!10069`
- Reduce memory used to store DNS names. ``24db1b1a8a``
The memory used to internally store the DNS names has been reduced.
:gl:`!10140`
- Unify fips handling to isc_crypto and make the toggle one way.
``3de629d6b7``
Since algorithm fetching is handled purely in libisc, FIPS mode
toggling can be purely done in within the library instead of provider
fetching in the binary for OpenSSL >=3.0.
Disabling FIPS mode isn't a realistic requirement and isn't done
anywhere in the codebase. Make the FIPS mode toggle enable-only to
reflect the situation. :gl:`!9920`
Bug Fixes
~~~~~~~~~
- Prevent a reference leak when using plugins. ``5604d3a44e``
The `NS_QUERY_DONE_BEGIN` and `NS_QUERY_DONE_SEND` plugin hooks could
cause a reference leak if they returned `NS_HOOK_RETURN` without
cleaning up the query context properly. :gl:`#2094` :gl:`!9971`
- Fix isc_quota bug. ``742d379d88``
Running jobs which were entered into the isc_quota queue is the
responsibility of the isc_quota_release() function, which, when
releasing a previously acquired quota, checks whether the queue is
empty, and if it's not, it runs a job from the queue without touching
the 'quota->used' counter. This mechanism is susceptible to a possible
hangup of a newly queued job in case when between the time a decision
has been made to queue it (because used >= max) and the time it was
actually queued, the last quota was released. Since there is no more
quotas to be released (unless arriving in the future), the newly
entered job will be stuck in the queue.
Fix the issue by adding checks in both isc_quota_release() and
isc_quota_acquire_cb() to make sure that the described hangup does not
happen. Also see code comments. :gl:`#4965` :gl:`!10082`
- Fix dual-stack-servers configuration option. ``6af708f3b0``
The dual-stack-servers configuration option was not working as
expected; the specified servers were not being used when they should
have been, leading to resolution failures. This has been fixed.
:gl:`#5019` :gl:`!9708`
- Implement sig0key-checks-limit and sig0message-checks-limit.
``d78ebff861``
Previously a hard-coded limitation of maximum two key or message
verification checks were introduced when checking the message's SIG(0)
signature. It was done in order to protect against possible DoS
attacks. The logic behind choosing the number 2 was that more than a
single key should only be required during key rotations, and in that
case two keys are enough. But later it became apparent that there are
other use cases too where even more keys are required, see issue
number #5050 in GitLab.
This change introduces two new configuration options for the views,
`sig0key-checks-limit` and `sig0message-checks-limit`, which define
how many keys are allowed to be checked to find a matching key, and
how many message verifications are allowed to take place once a
matching key has been found. The latter protects against expensive
cryptographic operations when there are keys with colliding tags and
algorithm numbers, with default being 2, and the former protects
against a bit less expensive key parsing operations and defaults to
16. :gl:`#5050` :gl:`!9967`
- Fix the data race causing a permanent active client increase.
``479c366c2b``
Previously, a data race could cause a newly created fetch context for
a new client to be used before it had been fully initialized, which
would cause the query to become stuck; queries for the same data would
be either paused indefinitely or dropped because of the
`clients-per-query` limit. This has been fixed. :gl:`#5053`
:gl:`!10146`
- Fix deferred validation of unsigned DS and DNSKEY records.
``ebf1606f38``
When processing a query with the "checking disabled" bit set (CD=1),
`named` stores the unvalidated result in the cache, marked "pending".
When the same query is sent with CD=0, the cached data is validated,
and either accepted as an answer, or ejected from the cache as
invalid. This deferred validation was not attempted for DS and DNSKEY
records if they had no cached signatures, causing spurious validation
failures. We now complete the deferred validation in this scenario.
Also, if deferred validation fails, we now re-query the data to find
out whether the zone has been corrected since the invalid data was
cached. :gl:`#5066` :gl:`!10104`
- When recording an rr trace, use libtool. ``6320586df0``
When a system test is run with the `USE_RR` environment variable set
to 1, an `rr` trace is now correctly generated for each instance of
`named`. :gl:`#5079` :gl:`!10197`
- Do not cache signatures for rejected data. ``fc3a4d6f89``
The cache has been updated so that if new data is rejected - for
example, because there was already existing data at a higher trust
level - then its covering RRSIG will also be rejected. :gl:`#5132`
:gl:`!9999`
- Fix wrong logging severity in do_nsfetch() ``1f6a16e6d0``
ISC_LOG_WARNING was used while ISC_LOG_DEBUG(3) was implied.
:gl:`#5145` :gl:`!10017`
- Fix RPZ race condition during a reconfiguration. ``5ba811bea2``
With RPZ in use, `named` could terminate unexpectedly because of a
race condition when a reconfiguration command was received using
`rndc`. This has been fixed. :gl:`#5146` :gl:`!10079`
- "CNAME and other data check" not applied to all types. ``b694acbe45``
An incorrect optimization caused "CNAME and other data" errors not to
be detected if certain types were at the same node as a CNAME. This
has been fixed. :gl:`#5150` :gl:`!10033`
- Use named Service Parameter Keys (SvcParamKeys) by default.
``3f61a87be3``
When converting SVCB records to text representation `named` now uses
named `SvcParamKeys` values unless backward-compatible mode is
activated, in which case the values which were not defined initially
in RFC9460 and were added later (see [1]) are converted to opaque
"keyNNNN" syntax, like, for example, "key7" instead of "dohpath".
Also a new `+[no]svcparamkeycompat` option is implemented for `dig`,
which enables the backward-compatible mode and uses the opaque syntax,
if required for interoperability with other software or scripts. By
default, the compatibility mode is disabled.
[1] https://www.iana.org/assignments/dns-svcb/dns-svcb.xhtml
:gl:`#5156` :gl:`!10085`
- Relax private DNSKEY and RRSIG constraints. ``1bc7016d7a``
DNSKEY, KEY, RRSIG and SIG constraints have been relaxed to allow
empty key and signature material after the algorithm identifier for
PRIVATEOID and PRIVATEDNS. It is arguable whether this falls within
the expected use of these types as no key material is shared and the
signatures are ineffective but these are private algorithms and they
can be totally insecure. :gl:`#5167` :gl:`!10083`
- Delete dead nodes when committing a new version. ``67255da4b3``
In the qpzone implementation of `dns_db_closeversion()`, if there are
changed nodes that have no remaining data, delete them. :gl:`#5169`
:gl:`!10089`
- Revert "Delete dead nodes when committing a new version"
``b652d5327c``
This reverts commit 67255da4b376f65138b299dcd5eb6a3b7f9735a9,
reversing changes made to 74c9ff384e695d1b27fa365d1fee84576f869d4c.
:gl:`#5169` :gl:`!10224`
- Fix dns_qp_insert() checks in qpzone. ``d6b63210a8``
Remove code in the QP zone database to handle failures of
`dns_qp_insert()` which can't actually happen. :gl:`#5171`
:gl:`!10088`
- Remove NSEC/DS/NSEC3 RRSIG check from dns_message_parse.
``f0785fedf1``
Previously, when parsing responses, named incorrectly rejected
responses without matching RRSIG records for NSEC/DS/NSEC3 records in
the authority section. This rejection, if appropriate, should have
been left for the validator to determine and has been fixed.
:gl:`#5185` :gl:`!10125`
- Fix TTL issue with ANY queries processed through RPZ "passthru"
``23c1fbc609``
Answers to an "ANY" query which were processed by the RPZ "passthru"
policy had the response-policy's `max-policy-ttl` value unexpectedly
applied. This has been fixed. :gl:`#5187` :gl:`!10176`
- Save time when creating a slab from another slab. ``cf981ab13b``
The `dns_rdataslab_fromrdataset()` function creates a slab from an
rdataset. If the source rdataset already uses a slab, then no
processing is necessary; we can just copy the existing slab to a new
location. :gl:`#5188` :gl:`!10162`
- Dnssec-signzone needs to check for a NULL key when setting offline.
``26f8ee7229``
dnssec-signzone could dereference a NULL key pointer when resigning a
zone. This has been fixed. :gl:`#5192` :gl:`!10161`
- Acquire the database reference before possibly last node release.
``c4868b5bd9``
Acquire the database reference in the detachnode() to prevent the last
reference to be release while the NODE_LOCK being locked. The
NODE_LOCK is locked/unlocked inside the RCU critical section, thus it
is most probably this should not pose a problem as the database uses
call_rcu memory reclamation, but this it is still safer to acquire the
reference before releasing the node. :gl:`#5194` :gl:`!10155`
- Fix a logic error in cache_name() ``02ef8ff01c``
A change in 6aba56ae8 (checking whether a rejected RRset was identical
to the data it would have replaced, so that we could still cache a
signature) inadvertently introduced cases where processing of a
response would continue when previously it would have been skipped.
:gl:`#5197` :gl:`!10157`
- Fix a bug in the statistics channel when querying zone transfers
information. ``e02d73e7e3``
When querying zone transfers information from the statistics channel
there was a rare possibility that `named` could terminate unexpectedly
if a zone transfer was in a state when transferring from all the
available primary servers had failed earlier. This has been fixed.
:gl:`#5198` :gl:`!10182`
- Fix assertion failure when dumping recursing clients. ``796b662b92``
Previously, if a new counter was added to the hashtable while dumping
recursing clients via the `rndc recursing` command, and
`fetches-per-zone` was enabled, an assertion failure could occur. This
has been fixed. :gl:`#5200` :gl:`!10164`
- Validating ADB fetches could cause a crash in import_rdataset()
``49ccbe857a``
Previously, in some cases, the resolver could return rdatasets of type
CNAME or DNAME without the result code being set to `DNS_R_CNAME` or
`DNS_R_DNAME`. This could trigger an assertion failure in the ADB. The
resolver error has been fixed. :gl:`#5201` :gl:`!10172`
- Call isc__iterated_hash_initialize in isc__work_cb. ``f3458fdf43``
isc_iterated_hash didn't work in offloaded threads as the per thread
initialisation has not been done. This has been fixed. :gl:`#5214`
:gl:`!10206`
- Fix a bug in get_request_transport_type() ``db5166ab99``
When `dns_remote_done()` is true, calling `dns_remote_curraddr()`
asserts. Add a `dns_remote_curraddr()` check before calling
`dns_remote_curraddr()`. :gl:`#5215` :gl:`!10222`
- Clean up dns_rdataslab module. ``948f8d7a98``
Rdata slabs used in the QP databases are usually prepended with a slab
header, but are sometimes "raw", containing only the rdata and no
header. Previously, to allow for them to be used both ways, functions
that operated on them took a `reservelen` argument, which would be set
to either the header length or to zero, and skipped over that many
bytes at the beginning of the buffer. Most such functions were never
used on the raw form. To make the code clearer, each of these
functions now operates on full slabs with headers, and an alternate
"raw" version of the function has been added in cases where that was
needed.
In addition, the `dns_rdataslab_merge()` and `_subtract()` functions
have been rewritten for clarity and efficiency, and a minor bug has
been fixed in `dns_rdataslab_equal()` and `_equalx()`, which could
cause an incorrect result if both slabs being compared had zero
length. :gl:`!10084`
- Dump the active resolver fetches from dns_resolver_dumpfetches()
``5d0c347e75``
Previously, active resolver fetches were only dumped when the
`fetches-per-zone` configuration option was enabled. Now, active
resolver fetches are dumped along with the number of
`clients-per-server` counters per resolver fetch. :gl:`!10107`
- Fix the foundname vs dcname madness in qpcache_findzonecut()
``4e68dbf194``
The qpcache_findzonecut() accepts two "foundnames": 'foundname' and
'dcname' could be NULL. Originally, when 'dcname' would be NULL, the
'dcname' would be set to 'foundname' which basically means that we
were copying the .ndata over itself for no apparent reason.
:gl:`!10049`
- Post [CVE-2024-12705] Performance Drop Fixes, Part 2. ``c8104daf8d``
This merge request addresses several key performance bottlenecks in
the DoH (DNS over HTTPS) implementation by introducing significant
optimizations and improvements.
### Key Improvements
1. **Simplification and Optimisation of `http_do_bio()` Function**:
- The code flow in the `http_do_bio()` function has been significantly
simplified. 2. **Flushing HTTP Write Buffer on Outgoing DNS
Messages**: - The buffer is flushed and a send operation is
performed when there is an outgoing DNS message. 3. **Bumping Active
Streams Processing Limit**: - The total number of active streams
has been increased to 60% of the total streams limit.
These changes collectively enhance the performance and reliability of
the DoH implementation, making it more efficient and robust for
handling high-load scenarios, particularly noticeable in long runs (>=
1h) of `stress:long:rpz:doh+udp:linux:*` tests. It improves perf. for
tests for BIND 9.18, but it likely will have a positive but less
pronounced effect on newer versions as well.
In essence, the merge request fixes three bottlenecks stacked upon
each other.
*It is a logical continuation of the merge requests !10109.* !10109,
unfortunately, did not completely [address the performance drop in
9.18](https://gitlab.isc.org/isc-projects/bind9/-/pipelines/221545)
for longer runs of the stress test. This merge request [addresses
that](https://gitlab.isc.org/isc-projects/bind9/-/pipelines/223661).
**P.S.**
The origin of the fixes is, in fact, the branch in !10193. So this MR
is a ... *forward port* of them. :gl:`!10192`
- Post [CVE-2024-12705] Performance Drop Fixes. ``3033d127d2``
This merge request fixes a [performance
drop](https://gitlab.isc.org/isc-projects/bind9/-/pipelines/216728)
after merging the fixes for #4795, in particular in 9.18.
The MR [fixes the
problem](https://gitlab.isc.org/isc-projects/bind9/-/pipelines/219825)
without affecting performance for the newer versions, in particular
for [the development version](https://gitlab.isc.org/isc-projects/bind
9/-/pipelines/220619). :gl:`!10109`
- Remove 'target' from dns_adb. ``764eb65cf6``
When a server name turns out to be a CNAME or DNAME, the ADB does not
use it, but the `dns_adbname` structure still stored a copy of the
target name. This is unnecessary and the code has been removed.
:gl:`!10149`
- Simplify some dns_name API calls. ``e16560a650``
Several functions in the `dns_name` module have had parameters
removed, that were rarely or never used: - `dns_name_fromtext()` and
`dns_name_concatenate()` no longer take a target buffer. -
`dns_name_towire()` no longer takes a compression offset pointer; this
is now part of the compression context. - `dns_name_towire()` with a
`NULL` compression context will copy name data directly into a buffer
with no processing. :gl:`!10152`
- Sync the TSAN CC, CFLAGS and LDFLAGS in the respdiff:tsan job.
``22b5442722``
:gl:`!10209`
-186
View File
@@ -1,186 +0,0 @@
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
..
.. SPDX-License-Identifier: MPL-2.0
..
.. 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 https://mozilla.org/MPL/2.0/.
..
.. See the COPYRIGHT file distributed with this work for additional
.. information regarding copyright ownership.
Notes for BIND 9.21.6
---------------------
New Features
~~~~~~~~~~~~
- Implement the :any:`min-transfer-rate-in` configuration option.
A new option :any:`min-transfer-rate-in` has been added
to the view and zone configurations. It can abort incoming zone
transfers that run very slowly due to network-related issues, for
example. The default value is 10240 bytes in five minutes.
:gl:`#3914`
- Add HTTPS record query to :iscman:`host` command line tool.
The :iscman:`host` command was extended to also query for the HTTPS RR
type by default.
- Implement :any:`sig0key-checks-limit` and :any:`sig0message-checks-limit`.
Previously, a hard-coded limitation of a maximum of two key or message
verification checks was introduced when checking a message's ``SIG(0)``
signature, to protect against possible DoS
attacks. Two as a maximum was chosen so that more than a
single key should only be required during key rotations, and in that
case two keys are enough. It later became apparent that there are
other use cases where even more keys are required; see the related GitLab issue for examples.
This change introduces two new configuration options for the views:
:any:`sig0key-checks-limit` and :any:`sig0message-checks-limit`. They define
how many keys can be checked to find a matching key, and
how many message verifications are allowed to take place once a
matching key has been found. The former provides
slightly less "expensive" key parsing operations and defaults to
16. The latter protects against expensive
cryptographic operations when there are keys with colliding tags and
algorithm numbers; the default is 2. :gl:`#5050`
Feature Changes
~~~~~~~~~~~~~~~
- Drop malformed notify messages early instead of decompressing them.
The DNS header shows whether a message has multiple questions or invalid
NOTIFY sections. :iscman:`named` can now drop these messages early, right after parsing
the question, to match :rfc:`9619` for multi-question messages and
Unbound's handling of NOTIFY. Questions are still parsed to be included
in BIND's FORMERR response.
Add ``drop_msg_early()`` function to check for these conditions:
- Messages with more than one question, as required by :rfc:`9619`
- NOTIFY query messages containing answer sections (like Unbound)
:gl:`#5158`
- Reduce memory used to store DNS names.
The memory used to internally store the DNS names has been reduced
by no longer caching certain fields from an internal data structure.
Bug Fixes
~~~~~~~~~
- Fix :any:`dual-stack-servers` configuration option.
The :any:`dual-stack-servers` configuration option was not working as
expected; the specified servers were not being used when they should
have been, leading to resolution failures. This has been fixed.
:gl:`#5019`
- Fix a data race causing a permanent active client increase.
Previously, a data race could cause a newly created fetch context for
a new client to be used before it had been fully initialized, which
would cause the query to become stuck; queries for the same data would
be either paused indefinitely or dropped because of the
:any:`clients-per-query` limit. This has been fixed. :gl:`#5053`
- Fix deferred validation of unsigned DS and DNSKEY records.
When processing a query with the "checking disabled" bit set (CD=1),
:iscman:`named` stores the invalidated result in the cache, marked "pending".
When the same query is sent with CD=0, the cached data is validated
and either accepted as an answer, or ejected from the cache as
invalid. This deferred validation was not attempted for DS and DNSKEY
records if they had no cached signatures, causing spurious validation
failures. The deferred validation is now completed in this scenario.
Also, if deferred validation fails, the data is now re-queried to find
out whether the zone has been corrected since the invalid data was
cached. :gl:`#5066`
- Fix RPZ race condition during a reconfiguration.
With RPZ in use, :iscman:`named` could terminate unexpectedly because of a
race condition when a reconfiguration command was received using
:iscman:`rndc`. This has been fixed. :gl:`#5146`
- "CNAME and other data check" not applied to all types.
An incorrect optimization caused "CNAME and other data" errors not to
be detected if certain types were at the same node as a CNAME. This
has been fixed. :gl:`#5150`
- Use named Service Parameter Keys (``SvcParamKeys``) by default.
When converting SVCB records to text representation, :iscman:`named` now uses
named ``SvcParamKeys`` values unless backward-compatible mode is
activated. In that case, values which were not defined initially
in :rfc:`9460` and were added later (see [1]) are converted to opaque
"keyNNNN" syntax, e.g. "key7" instead of "dohpath".
Also a new ``+[no]svcparamkeycompat`` option is implemented for :iscman:`dig`,
which enables the backward-compatible mode and uses the opaque syntax,
if required for interoperability with other software or scripts. By
default, the compatibility mode is disabled.
[1] https://www.iana.org/assignments/dns-svcb/dns-svcb.xhtml
:gl:`#5156`
- Relax private DNSKEY and RRSIG constraints.
DNSKEY, KEY, RRSIG, and SIG constraints have been relaxed to allow
empty key and signature material after the algorithm identifier for
PRIVATEOID and PRIVATEDNS. It is arguable whether this falls within
the expected use of these types, as no key material is shared and the
signatures are ineffective, but these are private algorithms and they
can be totally insecure. :gl:`#5167`
- Remove NSEC/DS/NSEC3 RRSIG check from ``dns_message_parse()``.
Previously, when parsing responses, :iscman:`named` incorrectly rejected
responses without matching RRSIG records for NSEC/DS/NSEC3 records in
the authority section. This rejection, if appropriate, should have
been left for the validator to determine and has been fixed.
:gl:`#5185`
- Fix TTL issue with ANY queries processed through RPZ "passthru".
Answers to an "ANY" query which were processed by the RPZ "passthru"
policy had the response-policy's ``max-policy-ttl`` value unexpectedly
applied. This has been fixed. :gl:`#5187`
- :iscman:`dnssec-signzone` needs to check for a NULL key when setting offline.
:iscman:`dnssec-signzone` could dereference a NULL key pointer when resigning
a zone. This has been fixed. :gl:`#5192`
- Fix a bug in the statistics channel when querying zone transfer
information.
When querying zone transfer information from the statistics channel,
there was a rare possibility that :iscman:`named` could terminate unexpectedly
if a zone transfer was in a state when transferring from all the
available primary servers had failed earlier. This has been fixed.
:gl:`#5198`
- Fix assertion failure when dumping recursing clients.
Previously, if a new counter was added to the hash table while dumping
recursing clients via the :option:`rndc recursing` command, and
:any:`fetches-per-zone` was enabled, an assertion failure could occur. This
has been fixed. :gl:`#5200`
- Dump the active resolver fetches from ``dns_resolver_dumpfetches()``
Previously, active resolver fetches were only dumped when the
:any:`fetches-per-zone` configuration option was enabled. Now, active
resolver fetches are dumped along with the number of
:any:`clients-per-query` counters per resolver fetch.
+2
View File
@@ -136,6 +136,7 @@ libdns_la_HEADERS = \
include/dns/view.h \ include/dns/view.h \
include/dns/xfrin.h \ include/dns/xfrin.h \
include/dns/zone.h \ include/dns/zone.h \
include/dns/zonekey.h \
include/dns/zoneverify.h \ include/dns/zoneverify.h \
include/dns/zt.h include/dns/zt.h
@@ -254,6 +255,7 @@ libdns_la_SOURCES = \
zone.c \ zone.c \
zone_p.h \ zone_p.h \
zoneverify.c \ zoneverify.c \
zonekey.c \
zt.c zt.c
if HAVE_GSSAPI if HAVE_GSSAPI
+5 -5
View File
@@ -1076,11 +1076,11 @@ new_adbfetch(dns_adb_t *adb) {
dns_adbfetch_t *fetch = NULL; dns_adbfetch_t *fetch = NULL;
fetch = isc_mem_get(adb->hmctx, sizeof(*fetch)); fetch = isc_mem_get(adb->hmctx, sizeof(*fetch));
*fetch = (dns_adbfetch_t){ *fetch = (dns_adbfetch_t){ 0 };
.magic = DNS_ADBFETCH_MAGIC,
};
dns_rdataset_init(&fetch->rdataset); dns_rdataset_init(&fetch->rdataset);
fetch->magic = DNS_ADBFETCH_MAGIC;
return fetch; return fetch;
} }
@@ -2909,7 +2909,6 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone, bool no_validation,
* createfetch to find deepest cached name when we're providing * createfetch to find deepest cached name when we're providing
* domain and nameservers. * domain and nameservers.
*/ */
dns_adbname_ref(adbname);
result = dns_resolver_createfetch( result = dns_resolver_createfetch(
adb->res, adbname->name, type, name, nameservers, NULL, NULL, 0, adb->res, adbname->name, type, name, nameservers, NULL, NULL, 0,
options, depth, qc, gqc, isc_loop(), fetch_callback, adbname, options, depth, qc, gqc, isc_loop(), fetch_callback, adbname,
@@ -2917,10 +2916,11 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone, bool no_validation,
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
DP(ENTER_LEVEL, "fetch_name: createfetch failed with %s", DP(ENTER_LEVEL, "fetch_name: createfetch failed with %s",
isc_result_totext(result)); isc_result_totext(result));
dns_adbname_unref(adbname);
goto cleanup; goto cleanup;
} }
dns_adbname_ref(adbname);
if (type == dns_rdatatype_a) { if (type == dns_rdatatype_a) {
adbname->fetch_a = fetch; adbname->fetch_a = fetch;
inc_resstats(adb, dns_resstatscounter_gluefetchv4); inc_resstats(adb, dns_resstatscounter_gluefetchv4);
-35
View File
@@ -1101,41 +1101,6 @@ dns_dnssec_signs(dns_rdata_t *rdata, const dns_name_t *name,
return false; return false;
} }
bool
dns_dnssec_iszonekey(dns_rdata_dnskey_t *key) {
return (key->flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
(key->flags & DNS_KEYTYPE_NOAUTH) == 0 &&
(key->protocol == DNS_KEYPROTO_DNSSEC ||
key->protocol == DNS_KEYPROTO_ANY);
}
bool
dns_dnssec_haszonekey(dns_rdataset_t *keyset) {
isc_result_t result;
REQUIRE(keyset != NULL);
if (keyset->type != dns_rdatatype_dnskey) {
return false;
}
for (result = dns_rdataset_first(keyset); result == ISC_R_SUCCESS;
result = dns_rdataset_next(keyset))
{
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_dnskey_t key;
dns_rdataset_current(keyset, &rdata);
dns_rdata_tostruct(&rdata, &key, NULL); /* can't fail */
if (dns_dnssec_iszonekey(&key)) {
return true;
}
}
return false;
}
void void
dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey, dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
dns_dnsseckey_t **dkp) { dns_dnsseckey_t **dkp) {
+19 -8
View File
@@ -162,7 +162,8 @@ computeid(dst_key_t *key);
static isc_result_t static isc_result_t
frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
unsigned int protocol, dns_rdataclass_t rdclass, unsigned int protocol, dns_rdataclass_t rdclass,
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp); isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
dst_key_t **keyp);
static isc_result_t static isc_result_t
algorithm_status(unsigned int alg); algorithm_status(unsigned int alg);
@@ -720,6 +721,13 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
isc_result_t isc_result_t
dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass, dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
return dst_key_fromdns_ex(name, rdclass, source, mctx, false, keyp);
}
isc_result_t
dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
dst_key_t **keyp) {
uint8_t alg, proto; uint8_t alg, proto;
uint32_t flags, extflags; uint32_t flags, extflags;
dst_key_t *key = NULL; dst_key_t *key = NULL;
@@ -748,7 +756,7 @@ dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
} }
result = frombuffer(name, alg, flags, proto, rdclass, source, mctx, result = frombuffer(name, alg, flags, proto, rdclass, source, mctx,
&key); no_rdata, &key);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
return result; return result;
} }
@@ -767,7 +775,7 @@ dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
isc_result_t result; isc_result_t result;
result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx, result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx,
&key); false, &key);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
return result; return result;
} }
@@ -2259,7 +2267,8 @@ computeid(dst_key_t *key) {
static isc_result_t static isc_result_t
frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
unsigned int protocol, dns_rdataclass_t rdclass, unsigned int protocol, dns_rdataclass_t rdclass,
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
dst_key_t **keyp) {
dst_key_t *key; dst_key_t *key;
isc_result_t ret; isc_result_t ret;
@@ -2281,10 +2290,12 @@ frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
return DST_R_UNSUPPORTEDALG; return DST_R_UNSUPPORTEDALG;
} }
ret = key->func->fromdns(key, source); if (!no_rdata) {
if (ret != ISC_R_SUCCESS) { ret = key->func->fromdns(key, source);
dst_key_free(&key); if (ret != ISC_R_SUCCESS) {
return ret; dst_key_free(&key);
return ret;
}
} }
} }
-18
View File
@@ -242,24 +242,6 @@ dns_dnssec_signs(dns_rdata_t *rdata, const dns_name_t *name,
* rrset. dns_dnssec_signs() works on any rrset. * rrset. dns_dnssec_signs() works on any rrset.
*/ */
bool
dns_dnssec_iszonekey(dns_rdata_dnskey_t *key);
/*%<
* Verify that 'key' is a DNSSEC key with the DNS_KEYOWNER_ZONE flag set.
*
* Requires:
*\li 'key' is not NULL.
*/
bool
dns_dnssec_haszonekey(dns_rdataset_t *keyset);
/*%<
* Verify that 'keyset' includes at least one zone key.
*
* Requires:
*\li 'keyset' is not NULL.
*/
void void
dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey, dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
dns_dnsseckey_t **dkp); dns_dnsseckey_t **dkp);
+5 -14
View File
@@ -205,9 +205,9 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
*\li Any other result indicates an error. *\li Any other result indicates an error.
*/ */
isc_result_t bool
dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name, dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
dns_name_t *foundname, bool *wantdnssecp); dns_name_t *foundname);
/*%< /*%<
* Is 'name' at or beneath a trusted key? * Is 'name' at or beneath a trusted key?
* *
@@ -219,20 +219,11 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
* *
*\li 'foundanme' is NULL or is a pointer to an initialized dns_name_t *\li 'foundanme' is NULL or is a pointer to an initialized dns_name_t
* *
*\li '*wantsdnssecp' is a valid bool.
*
* Ensures: * Ensures:
* *
*\li On success, *wantsdnssecp will be true if and only if 'name' *\li Returns true if and only if 'name' is at or beneath a trusted key.
* is at or beneath a trusted key. If 'foundname' is not NULL, then * If 'foundname' is not NULL, then it will be updated to contain
* it will be updated to contain the name of the closest enclosing * the name of the closest enclosing trust anchor.
* trust anchor.
*
* Returns:
*
*\li ISC_R_SUCCESS
*
*\li Any other result is an error.
*/ */
isc_result_t isc_result_t
+9 -11
View File
@@ -54,26 +54,24 @@
isc_result_t isc_result_t
dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl, dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
dns_ttl_t maxttl, dns_rdataset_t *addedrdataset); dns_ttl_t maxttl, bool optout, bool secure,
isc_result_t dns_rdataset_t *addedrdataset);
dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
dns_dbnode_t *node, dns_rdatatype_t covers,
isc_stdtime_t now, dns_ttl_t minttl, dns_ttl_t maxttl,
bool optout, dns_rdataset_t *addedrdataset);
/*%< /*%<
* Convert the authority data from 'message' into a negative cache * Convert the authority data from 'message' into a negative cache
* rdataset, and store it in 'cache' at 'node' with a TTL limited to * rdataset, and store it in 'cache' at 'node' with a TTL limited to
* 'maxttl'. * 'maxttl'.
* *
* \li dns_ncache_add produces a negative cache entry with a trust of no * \li If 'secure' is true and all the records that make up the entry
* more than answer * are secure, then dns_ncache_add produces a negative cache entry
* \li dns_ncache_addoptout produces a negative cache entry which will have * with trust level secure.
* a trust of secure if all the records that make up the entry are secure. * \li If 'secure' is false, the negative cache entry's trust level
* will be capped at answer.
* *
* The 'covers' argument is the RR type whose nonexistence we are caching, * The 'covers' argument is the RR type whose nonexistence we are caching,
* or dns_rdatatype_any when caching a NXDOMAIN response. * or dns_rdatatype_any when caching a NXDOMAIN response.
* *
* 'optout' indicates a DNS_RDATASETATTR_OPTOUT should be set. * 'optout' indicates DNS_RDATASETATTR_OPTOUT should be set. This only
* applies in secure zones; if 'secure' is false, 'optout' is ignored.
* *
* Note: * Note:
*\li If 'addedrdataset' is not NULL, then it will be attached to the added *\li If 'addedrdataset' is not NULL, then it will be attached to the added
+27
View File
@@ -689,3 +689,30 @@ dns_rdataset_equals(const dns_rdataset_t *rdataset1,
* \li 'rdataset1' is a valid rdataset. * \li 'rdataset1' is a valid rdataset.
* \li 'rdataset2' is a valid rdataset. * \li 'rdataset2' is a valid rdataset.
*/ */
/*%
* Returns true if the rdataset is of type 'type', or type RRSIG
* and covers 'type'.
*/
static inline bool
dns_rdataset_matchestype(const dns_rdataset_t *rdataset,
const dns_rdatatype_t type) {
REQUIRE(DNS_RDATASET_VALID(rdataset));
return rdataset->type == type ||
(rdataset->type == dns_rdatatype_rrsig &&
rdataset->covers == type);
}
/*%
* Returns true if the rdataset is of type 'type', or type RRSIG
* and covers 'type'.
*/
static inline bool
dns_rdataset_issigtype(const dns_rdataset_t *rdataset,
const dns_rdatatype_t type) {
REQUIRE(DNS_RDATASET_VALID(rdataset));
return rdataset->type == dns_rdatatype_rrsig &&
rdataset->covers == type;
}
+3 -3
View File
@@ -151,8 +151,8 @@ struct dns_validator {
uint8_t unsupported_digest; uint8_t unsupported_digest;
dns_rdata_t rdata; dns_rdata_t rdata;
bool resume; bool resume;
isc_counter_t *nvalidations; uint32_t *nvalidations;
isc_counter_t *nfails; uint32_t *nfails;
isc_counter_t *qc; isc_counter_t *qc;
isc_counter_t *gqc; isc_counter_t *gqc;
@@ -172,7 +172,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
dns_message_t *message, unsigned int options, dns_message_t *message, unsigned int options,
isc_loop_t *loop, isc_job_cb cb, void *arg, isc_loop_t *loop, isc_job_cb cb, void *arg,
isc_counter_t *nvalidations, isc_counter_t *nfails, uint32_t *nvalidations, uint32_t *nfails,
isc_counter_t *qc, isc_counter_t *gqc, isc_counter_t *qc, isc_counter_t *gqc,
dns_edectx_t *edectx, dns_validator_t **validatorp); dns_edectx_t *edectx, dns_validator_t **validatorp);
/*%< /*%<
+3 -8
View File
@@ -986,13 +986,12 @@ dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp);
*\li ISC_R_NOTFOUND *\li ISC_R_NOTFOUND
*/ */
isc_result_t bool
dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name, dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name,
isc_stdtime_t now, bool checknta, bool *ntap, isc_stdtime_t now, bool checknta, bool *ntap);
bool *secure_domain);
/*%< /*%<
* Is 'name' at or beneath a trusted key, and not covered by a valid * Is 'name' at or beneath a trusted key, and not covered by a valid
* negative trust anchor? Put answer in '*secure_domain'. * negative trust anchor, and DNSSEC validation is enabled?
* *
* If 'checknta' is false, ignore the NTA table in determining * If 'checknta' is false, ignore the NTA table in determining
* whether this is a secure domain. If 'checknta' is not false, and if * whether this is a secure domain. If 'checknta' is not false, and if
@@ -1001,10 +1000,6 @@ dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name,
* *
* Requires: * Requires:
* \li 'view' is valid. * \li 'view' is valid.
*
* Returns:
*\li ISC_R_SUCCESS
*\li Any other value indicates failure
*/ */
bool bool
+41 -30
View File
@@ -818,7 +818,7 @@ dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val);
* val > 0. * val > 0.
*/ */
void isc_result_t
dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource); dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource);
/*%< /*%<
* Set the source address to be used in IPv4 zone transfers. * Set the source address to be used in IPv4 zone transfers.
@@ -826,20 +826,22 @@ dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource);
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'xfrsource' to contain the address. *\li 'xfrsource' to contain the address.
*
* Returns:
*\li #ISC_R_SUCCESS
*/ */
void isc_sockaddr_t *
dns_zone_getxfrsource4(dns_zone_t *zone, isc_sockaddr_t *xfrsource); dns_zone_getxfrsource4(dns_zone_t *zone);
/*%< /*%<
* Returns the source address set by a previous dns_zone_setxfrsource4 * Returns the source address set by a previous dns_zone_setxfrsource4
* call, or the default of inaddr_any, port 0. * call, or the default of inaddr_any, port 0.
* *
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'xfrsource' to not be NULL
*/ */
void isc_result_t
dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource); dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource);
/*%< /*%<
* Set the source address to be used in IPv6 zone transfers. * Set the source address to be used in IPv6 zone transfers.
@@ -847,20 +849,22 @@ dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource);
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'xfrsource' to contain the address. *\li 'xfrsource' to contain the address.
*
* Returns:
*\li #ISC_R_SUCCESS
*/ */
void isc_sockaddr_t *
dns_zone_getxfrsource6(dns_zone_t *zone, isc_sockaddr_t *xfrsource); dns_zone_getxfrsource6(dns_zone_t *zone);
/*%< /*%<
* Returns the source address set by a previous dns_zone_setxfrsource6 * Returns the source address set by a previous dns_zone_setxfrsource6
* call, or the default of in6addr_any, port 0. * call, or the default of in6addr_any, port 0.
* *
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'xfrsource' to not be NULL
*/ */
void isc_result_t
dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc); dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc);
/*%< /*%<
* Set the source address to be used with IPv4 parental DS queries. * Set the source address to be used with IPv4 parental DS queries.
@@ -868,20 +872,22 @@ dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc);
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'parentalsrc' to contain the address. *\li 'parentalsrc' to contain the address.
*
* Returns:
*\li #ISC_R_SUCCESS
*/ */
void isc_sockaddr_t *
dns_zone_getparentalsrc4(dns_zone_t *zone, isc_sockaddr_t *parentalsrc); dns_zone_getparentalsrc4(dns_zone_t *zone);
/*%< /*%<
* Returns the source address set by a previous dns_zone_setparentalsrc4 * Returns the source address set by a previous dns_zone_setparentalsrc4
* call, or the default of inaddr_any, port 0. * call, or the default of inaddr_any, port 0.
* *
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'parentalsrc' to be non NULL.
*/ */
void isc_result_t
dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc); dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc);
/*%< /*%<
* Set the source address to be used with IPv6 parental DS queries. * Set the source address to be used with IPv6 parental DS queries.
@@ -889,20 +895,22 @@ dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc);
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'parentalsrc' to contain the address. *\li 'parentalsrc' to contain the address.
*
* Returns:
*\li #ISC_R_SUCCESS
*/ */
void isc_sockaddr_t *
dns_zone_getparentalsrc6(dns_zone_t *zone, isc_sockaddr_t *parentalsrc); dns_zone_getparentalsrc6(dns_zone_t *zone);
/*%< /*%<
* Returns the source address set by a previous dns_zone_setparentalsrc6 * Returns the source address set by a previous dns_zone_setparentalsrc6
* call, or the default of in6addr_any, port 0. * call, or the default of in6addr_any, port 0.
* *
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'parentalsrc' to be non NULL.
*/ */
void isc_result_t
dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc); dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc);
/*%< /*%<
* Set the source address to be used with IPv4 NOTIFY messages. * Set the source address to be used with IPv4 NOTIFY messages.
@@ -910,20 +918,22 @@ dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc);
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'notifysrc' to contain the address. *\li 'notifysrc' to contain the address.
*
* Returns:
*\li #ISC_R_SUCCESS
*/ */
void isc_sockaddr_t *
dns_zone_getnotifysrc4(dns_zone_t *zone, isc_sockaddr_t *notifysrc); dns_zone_getnotifysrc4(dns_zone_t *zone);
/*%< /*%<
* Returns the source address set by a previous dns_zone_setnotifysrc4 * Returns the source address set by a previous dns_zone_setnotifysrc4
* call, or the default of inaddr_any, port 0. * call, or the default of inaddr_any, port 0.
* *
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'notifysrc' to be non NULL.
*/ */
void isc_result_t
dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc); dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc);
/*%< /*%<
* Set the source address to be used with IPv6 NOTIFY messages. * Set the source address to be used with IPv6 NOTIFY messages.
@@ -931,17 +941,19 @@ dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc);
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'notifysrc' to contain the address. *\li 'notifysrc' to contain the address.
*
* Returns:
*\li #ISC_R_SUCCESS
*/ */
void isc_sockaddr_t *
dns_zone_getnotifysrc6(dns_zone_t *zone, isc_sockaddr_t *notifysrc); dns_zone_getnotifysrc6(dns_zone_t *zone);
/*%< /*%<
* Returns the source address set by a previous dns_zone_setnotifysrc6 * Returns the source address set by a previous dns_zone_setnotifysrc6
* call, or the default of in6addr_any, port 0. * call, or the default of in6addr_any, port 0.
* *
* Require: * Require:
*\li 'zone' to be a valid zone. *\li 'zone' to be a valid zone.
*\li 'notifysrc' to be non NULL.
*/ */
void void
@@ -1516,8 +1528,8 @@ dns_zone_getsigresigninginterval(dns_zone_t *zone);
* \li 'zone' to be a valid zone. * \li 'zone' to be a valid zone.
*/ */
void isc_sockaddr_t
dns_zone_getsourceaddr(dns_zone_t *zone, isc_sockaddr_t *sourceaddr); dns_zone_getsourceaddr(dns_zone_t *zone);
/*%< /*%<
* Get the zone's source address from which it has last contacted the current * Get the zone's source address from which it has last contacted the current
* primary server. * primary server.
@@ -1525,18 +1537,17 @@ dns_zone_getsourceaddr(dns_zone_t *zone, isc_sockaddr_t *sourceaddr);
* Requires: * Requires:
* \li 'zone' to be a valid zone. * \li 'zone' to be a valid zone.
* \li 'zone' has a non-empty primaries list. * \li 'zone' has a non-empty primaries list.
* \li 'sourceaddr' to be non-NULL.
*/ */
isc_result_t isc_result_t
dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *primaryaddr); dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *dest);
/*%< /*%<
* Get the zone's current primary server into '*primaryaddr'. * Get the zone's current primary server into '*dest'.
* *
* Requires: * Requires:
* \li 'zone' to be a valid zone. * \li 'zone' to be a valid zone.
* \li 'zone' has a non-empty primaries list. * \li 'zone' has a non-empty primaries list.
* \li 'primaryaddr' to be non-NULL. * \li 'dest' != NULL.
* *
* Returns: * Returns:
*\li #ISC_R_SUCCESS if the current primary server was found *\li #ISC_R_SUCCESS if the current primary server was found
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
/*! \file dns/zonekey.h */
#include <stdbool.h>
#include <dns/types.h>
bool
dns_zonekey_iszonekey(dns_rdata_t *keyrdata);
/*%<
* Determines if the key record contained in the rdata is a zone key.
*
* Requires:
* 'keyrdata' is not NULL.
*/
+4
View File
@@ -460,6 +460,10 @@ dst_key_tofile(const dst_key_t *key, int type, const char *directory);
*/ */
isc_result_t isc_result_t
dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
dst_key_t **keyp);
isc_result_t
dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass, dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp); isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
/*%< /*%<
+40 -71
View File
@@ -189,19 +189,13 @@ dns_keymgr_settime_syncpublish(dst_key_t *key, dns_kasp_t *kasp, bool first) {
isc_stdtime_t zrrsig_present; isc_stdtime_t zrrsig_present;
dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true); dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
zrrsig_present = published + ttlsig + zrrsig_present = published + ttlsig +
dns_kasp_zonepropagationdelay(kasp); dns_kasp_zonepropagationdelay(kasp) +
dns_kasp_publishsafety(kasp);
if (zrrsig_present > syncpublish) { if (zrrsig_present > syncpublish) {
syncpublish = zrrsig_present; syncpublish = zrrsig_present;
} }
} }
dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncpublish); dst_key_settime(key, DST_TIME_SYNCPUBLISH, syncpublish);
uint32_t lifetime = 0;
ret = dst_key_getnum(key, DST_NUM_LIFETIME, &lifetime);
if (ret == ISC_R_SUCCESS && lifetime > 0) {
dst_key_settime(key, DST_TIME_SYNCDELETE,
(syncpublish + lifetime));
}
} }
/* /*
@@ -249,17 +243,6 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
pub = now; pub = now;
} }
/*
* To calculate phase out times ("Retired", "Removed", ...),
* the key lifetime is required.
*/
uint32_t klifetime = 0;
ret = dst_key_getnum(key->key, DST_NUM_LIFETIME, &klifetime);
if (ret != ISC_R_SUCCESS) {
dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime);
klifetime = lifetime;
}
/* /*
* Calculate prepublication time. * Calculate prepublication time.
*/ */
@@ -289,16 +272,13 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp,
true); true);
syncpub2 = pub + ttlsig + syncpub2 = pub + ttlsig +
dns_kasp_publishsafety(kasp) +
dns_kasp_zonepropagationdelay(kasp); dns_kasp_zonepropagationdelay(kasp);
} }
syncpub = ISC_MAX(syncpub1, syncpub2); syncpub = ISC_MAX(syncpub1, syncpub2);
dst_key_settime(key->key, DST_TIME_SYNCPUBLISH, dst_key_settime(key->key, DST_TIME_SYNCPUBLISH,
syncpub); syncpub);
if (klifetime > 0) {
dst_key_settime(key->key, DST_TIME_SYNCDELETE,
(syncpub + klifetime));
}
} }
} }
@@ -311,6 +291,13 @@ keymgr_prepublication_time(dns_dnsseckey_t *key, dns_kasp_t *kasp,
ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire); ret = dst_key_gettime(key->key, DST_TIME_INACTIVE, &retire);
if (ret != ISC_R_SUCCESS) { if (ret != ISC_R_SUCCESS) {
uint32_t klifetime = 0;
ret = dst_key_getnum(key->key, DST_NUM_LIFETIME, &klifetime);
if (ret != ISC_R_SUCCESS) {
dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime);
klifetime = lifetime;
}
if (klifetime == 0) { if (klifetime == 0) {
/* /*
* No inactive time and no lifetime, * No inactive time and no lifetime,
@@ -411,7 +398,7 @@ keymgr_key_update_lifetime(dns_dnsseckey_t *key, dns_kasp_t *kasp,
/* Initialize lifetime. */ /* Initialize lifetime. */
if (r != ISC_R_SUCCESS) { if (r != ISC_R_SUCCESS) {
dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime); dst_key_setnum(key->key, DST_NUM_LIFETIME, lifetime);
l = lifetime - 1; return;
} }
/* Skip keys that are still hidden or already retiring. */ /* Skip keys that are still hidden or already retiring. */
if (g != OMNIPRESENT) { if (g != OMNIPRESENT) {
@@ -433,7 +420,6 @@ keymgr_key_update_lifetime(dns_dnsseckey_t *key, dns_kasp_t *kasp,
} else { } else {
dst_key_unsettime(key->key, DST_TIME_INACTIVE); dst_key_unsettime(key->key, DST_TIME_INACTIVE);
dst_key_unsettime(key->key, DST_TIME_DELETE); dst_key_unsettime(key->key, DST_TIME_DELETE);
dst_key_unsettime(key->key, DST_TIME_SYNCDELETE);
} }
} }
} }
@@ -1300,7 +1286,6 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
isc_result_t ret; isc_result_t ret;
isc_stdtime_t lastchange, dstime, nexttime = now; isc_stdtime_t lastchange, dstime, nexttime = now;
dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true); dns_ttl_t ttlsig = dns_kasp_zonemaxttl(kasp, true);
uint32_t dsstate;
/* /*
* No need to wait if we move things into an uncertain state. * No need to wait if we move things into an uncertain state.
@@ -1370,12 +1355,15 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
* records. This translates to: * records. This translates to:
* *
* Dsgn + zone-propagation-delay + max-zone-ttl. * Dsgn + zone-propagation-delay + max-zone-ttl.
*
* We will also add the retire-safety interval.
*/ */
nexttime = lastchange + ttlsig + nexttime = lastchange + ttlsig +
dns_kasp_zonepropagationdelay(kasp); dns_kasp_zonepropagationdelay(kasp) +
dns_kasp_retiresafety(kasp);
/* /*
* Only add the sign delay Dsgn and retire-safety if * Only add the sign delay Dsgn if there is an actual
* there is an actual predecessor or successor key. * predecessor or successor key.
*/ */
uint32_t tag; uint32_t tag;
ret = dst_key_getnum(key->key, DST_NUM_PREDECESSOR, ret = dst_key_getnum(key->key, DST_NUM_PREDECESSOR,
@@ -1385,8 +1373,7 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
DST_NUM_SUCCESSOR, &tag); DST_NUM_SUCCESSOR, &tag);
} }
if (ret == ISC_R_SUCCESS) { if (ret == ISC_R_SUCCESS) {
nexttime += dns_kasp_signdelay(kasp) + nexttime += dns_kasp_signdelay(kasp);
dns_kasp_retiresafety(kasp);
} }
break; break;
default: default:
@@ -1412,36 +1399,35 @@ keymgr_transition_time(dns_dnsseckey_t *key, int type,
* This translates to: * This translates to:
* *
* parent-propagation-delay + parent-ds-ttl. * parent-propagation-delay + parent-ds-ttl.
*
* We will also add the retire-safety interval.
*/ */
case OMNIPRESENT: case OMNIPRESENT:
case HIDDEN: /* Make sure DS has been seen in the parent. */
/* Make sure DS has been seen in/withdrawn from the ret = dst_key_gettime(key->key, DST_TIME_DSPUBLISH,
* parent. */ &dstime);
dsstate = next_state == HIDDEN ? DST_TIME_DSDELETE
: DST_TIME_DSPUBLISH;
ret = dst_key_gettime(key->key, dsstate, &dstime);
if (ret != ISC_R_SUCCESS || dstime > now) { if (ret != ISC_R_SUCCESS || dstime > now) {
/* Not yet, try again in an hour. */ /* Not yet, try again in an hour. */
nexttime = now + 3600; nexttime = now + 3600;
} else { } else {
nexttime = nexttime =
dstime + dns_kasp_dsttl(kasp) + dstime + dns_kasp_dsttl(kasp) +
dns_kasp_parentpropagationdelay(kasp); dns_kasp_parentpropagationdelay(kasp) +
/* dns_kasp_retiresafety(kasp);
* Only add the retire-safety if there is an }
* actual predecessor or successor key. break;
*/ case HIDDEN:
uint32_t tag; /* Make sure DS has been withdrawn from the parent. */
ret = dst_key_getnum(key->key, ret = dst_key_gettime(key->key, DST_TIME_DSDELETE,
DST_NUM_PREDECESSOR, &tag); &dstime);
if (ret != ISC_R_SUCCESS) { if (ret != ISC_R_SUCCESS || dstime > now) {
ret = dst_key_getnum(key->key, /* Not yet, try again in an hour. */
DST_NUM_SUCCESSOR, nexttime = now + 3600;
&tag); } else {
} nexttime =
if (ret == ISC_R_SUCCESS) { dstime + dns_kasp_dsttl(kasp) +
nexttime += dns_kasp_retiresafety(kasp); dns_kasp_parentpropagationdelay(kasp) +
} dns_kasp_retiresafety(kasp);
} }
break; break;
default: default:
@@ -1777,9 +1763,7 @@ keymgr_key_rollover(dns_kasp_key_t *kaspkey, dns_dnsseckey_t *active_key,
if (prepub == 0 || prepub > now) { if (prepub == 0 || prepub > now) {
/* No need to start rollover now. */ /* No need to start rollover now. */
if (*nexttime == 0 || prepub < *nexttime) { if (*nexttime == 0 || prepub < *nexttime) {
if (prepub > 0) { *nexttime = prepub;
*nexttime = prepub;
}
} }
return ISC_R_SUCCESS; return ISC_R_SUCCESS;
} }
@@ -2038,20 +2022,6 @@ keymgr_purge_keyfile(dst_key_t *key, int type) {
} }
} }
static bool
dst_key_doublematch(dns_dnsseckey_t *key, dns_kasp_t *kasp) {
int matches = 0;
for (dns_kasp_key_t *kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp));
kkey != NULL; kkey = ISC_LIST_NEXT(kkey, link))
{
if (dns_kasp_key_match(kkey, key)) {
matches++;
}
}
return matches > 1;
}
/* /*
* Examine 'keys' and match 'kasp' policy. * Examine 'keys' and match 'kasp' policy.
* *
@@ -2191,7 +2161,6 @@ dns_keymgr_run(const dns_name_t *origin, dns_rdataclass_t rdclass,
* matches the kasp policy. * matches the kasp policy.
*/ */
if (!dst_key_is_unused(dkey->key) && if (!dst_key_is_unused(dkey->key) &&
!dst_key_doublematch(dkey, kasp) &&
(dst_key_goal(dkey->key) == (dst_key_goal(dkey->key) ==
OMNIPRESENT) && OMNIPRESENT) &&
!keymgr_dep(dkey->key, keyring, !keymgr_dep(dkey->key, keyring,
+5 -9
View File
@@ -530,13 +530,14 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
return result; return result;
} }
isc_result_t bool
dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name, dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
dns_name_t *foundname, bool *wantdnssecp) { dns_name_t *foundname) {
isc_result_t result; isc_result_t result;
dns_qpread_t qpr; dns_qpread_t qpr;
dns_keynode_t *keynode = NULL; dns_keynode_t *keynode = NULL;
void *pval = NULL; void *pval = NULL;
bool secure = false;
/* /*
* Is 'name' at or beneath a trusted key? * Is 'name' at or beneath a trusted key?
@@ -544,7 +545,6 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
REQUIRE(VALID_KEYTABLE(keytable)); REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(dns_name_isabsolute(name)); REQUIRE(dns_name_isabsolute(name));
REQUIRE(wantdnssecp != NULL);
dns_qpmulti_query(keytable->table, &qpr); dns_qpmulti_query(keytable->table, &qpr);
result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL); result = dns_qp_lookup(&qpr, name, NULL, NULL, NULL, &pval, NULL);
@@ -553,16 +553,12 @@ dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
if (foundname != NULL) { if (foundname != NULL) {
dns_name_copy(&keynode->name, foundname); dns_name_copy(&keynode->name, foundname);
} }
*wantdnssecp = true; secure = true;
result = ISC_R_SUCCESS;
} else if (result == ISC_R_NOTFOUND) {
*wantdnssecp = false;
result = ISC_R_SUCCESS;
} }
dns_qpread_destroy(keytable->table, &qpr); dns_qpread_destroy(keytable->table, &qpr);
return result; return secure;
} }
static isc_result_t static isc_result_t
+19 -25
View File
@@ -3105,7 +3105,7 @@ dns_message_checksig_async(dns_message_t *msg, dns_view_t *view,
isc_result_t isc_result_t
dns_message_checksig(dns_message_t *msg, dns_view_t *view) { dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
isc_buffer_t msgb; isc_buffer_t b, msgb;
REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(DNS_MESSAGE_VALID(msg));
@@ -3126,7 +3126,7 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
return dns_tsig_verify(&msgb, msg, NULL, NULL); return dns_tsig_verify(&msgb, msg, NULL, NULL);
} }
} else { } else {
dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_sig_t sig; dns_rdata_sig_t sig;
dns_rdataset_t keyset; dns_rdataset_t keyset;
isc_result_t result; isc_result_t result;
@@ -3134,7 +3134,7 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
result = dns_rdataset_first(msg->sig0); result = dns_rdataset_first(msg->sig0);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
dns_rdataset_current(msg->sig0, &sigrdata); dns_rdataset_current(msg->sig0, &rdata);
/* /*
* This can occur when the message is a dynamic update, since * This can occur when the message is a dynamic update, since
@@ -3143,11 +3143,11 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
* looked for in the additional section, and the dynamic update * looked for in the additional section, and the dynamic update
* meta-records are in the prerequisite and update sections. * meta-records are in the prerequisite and update sections.
*/ */
if (sigrdata.length == 0) { if (rdata.length == 0) {
return ISC_R_UNEXPECTEDEND; return ISC_R_UNEXPECTEDEND;
} }
result = dns_rdata_tostruct(&sigrdata, &sig, NULL); result = dns_rdata_tostruct(&rdata, &sig, NULL);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
return result; return result;
} }
@@ -3191,32 +3191,26 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
message_checks < max_message_checks; message_checks < max_message_checks;
key_checks++, result = dns_rdataset_next(&keyset)) key_checks++, result = dns_rdataset_next(&keyset))
{ {
dns_rdata_t keyrdata = DNS_RDATA_INIT;
dns_rdata_key_t ks;
dst_key_t *key = NULL; dst_key_t *key = NULL;
isc_region_t r;
dns_rdataset_current(&keyset, &keyrdata); dns_rdata_reset(&rdata);
dns_rdata_tostruct(&keyrdata, &ks, NULL); dns_rdataset_current(&keyset, &rdata);
isc_buffer_init(&b, rdata.data, rdata.length);
isc_buffer_add(&b, rdata.length);
if (sig.algorithm != ks.algorithm || result = dst_key_fromdns(&sig.signer, rdata.rdclass, &b,
(ks.protocol != DNS_KEYPROTO_DNSSEC && view->mctx, &key);
ks.protocol != DNS_KEYPROTO_ANY))
{
continue;
}
dns_rdata_toregion(&keyrdata, &r);
if (dst_region_computeid(&r) != sig.keyid) {
continue;
}
result = dns_dnssec_keyfromrdata(&sig.signer, &keyrdata,
view->mctx, &key);
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
continue; continue;
} }
if (dst_key_alg(key) != sig.algorithm ||
dst_key_id(key) != sig.keyid ||
!(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
dst_key_proto(key) == DNS_KEYPROTO_ANY))
{
dst_key_free(&key);
continue;
}
result = dns_dnssec_verifymessage(&msgb, msg, key); result = dns_dnssec_verifymessage(&msgb, msg, key);
dst_key_free(&key); dst_key_free(&key);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
+7 -27
View File
@@ -50,12 +50,6 @@ atomic_getuint8(isc_buffer_t *b) {
return ret; return ret;
} }
static isc_result_t
addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
dns_ttl_t maxttl, bool optout, bool secure,
dns_rdataset_t *addedrdataset);
static isc_result_t static isc_result_t
copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) { copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
isc_result_t result; isc_result_t result;
@@ -107,25 +101,8 @@ copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
isc_result_t isc_result_t
dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl, dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
dns_ttl_t maxttl, dns_rdataset_t *addedrdataset) { dns_ttl_t maxttl, bool optout, bool secure,
return addoptout(message, cache, node, covers, now, minttl, maxttl, dns_rdataset_t *addedrdataset) {
false, false, addedrdataset);
}
isc_result_t
dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
dns_dbnode_t *node, dns_rdatatype_t covers,
isc_stdtime_t now, dns_ttl_t minttl, dns_ttl_t maxttl,
bool optout, dns_rdataset_t *addedrdataset) {
return addoptout(message, cache, node, covers, now, minttl, maxttl,
optout, true, addedrdataset);
}
static isc_result_t
addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t minttl,
dns_ttl_t maxttl, bool optout, bool secure,
dns_rdataset_t *addedrdataset) {
isc_result_t result; isc_result_t result;
isc_buffer_t buffer; isc_buffer_t buffer;
isc_region_t r; isc_region_t r;
@@ -143,14 +120,17 @@ addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
/* /*
* Convert the authority data from 'message' into a negative cache * Convert the authority data from 'message' into a negative cache
* rdataset, and store it in 'cache' at 'node'. * rdataset, and store it in 'cache' at 'node'.
*
* We assume that all data in the authority section has been
* validated by the caller.
*/ */
REQUIRE(message != NULL); REQUIRE(message != NULL);
/* /*
* We assume that all data in the authority section has been * If 'secure' is false, ignore 'optout'.
* validated by the caller.
*/ */
optout = optout && secure;
/* /*
* Initialize the list. * Initialize the list.
+1
View File
@@ -55,6 +55,7 @@
#include <dns/stats.h> #include <dns/stats.h>
#include <dns/time.h> #include <dns/time.h>
#include <dns/view.h> #include <dns/view.h>
#include <dns/zonekey.h>
#include "db_p.h" #include "db_p.h"
#include "qpcache_p.h" #include "qpcache_p.h"
+16 -7
View File
@@ -43,7 +43,6 @@
#include <dns/callbacks.h> #include <dns/callbacks.h>
#include <dns/db.h> #include <dns/db.h>
#include <dns/dbiterator.h> #include <dns/dbiterator.h>
#include <dns/dnssec.h>
#include <dns/fixedname.h> #include <dns/fixedname.h>
#include <dns/masterdump.h> #include <dns/masterdump.h>
#include <dns/name.h> #include <dns/name.h>
@@ -59,6 +58,7 @@
#include <dns/time.h> #include <dns/time.h>
#include <dns/view.h> #include <dns/view.h>
#include <dns/zone.h> #include <dns/zone.h>
#include <dns/zonekey.h>
#include "db_p.h" #include "db_p.h"
#include "qpzone_p.h" #include "qpzone_p.h"
@@ -1143,17 +1143,25 @@ setsecure(dns_db_t *db, qpz_version_t *version, dns_dbnode_t *origin) {
bool hasnsec = false; bool hasnsec = false;
isc_result_t result; isc_result_t result;
version->secure = false;
version->havensec3 = false;
dns_rdataset_init(&keyset); dns_rdataset_init(&keyset);
result = dns_db_findrdataset(db, origin, (dns_dbversion_t *)version, result = dns_db_findrdataset(db, origin, (dns_dbversion_t *)version,
dns_rdatatype_dnskey, 0, 0, &keyset, NULL); dns_rdatatype_dnskey, 0, 0, &keyset, NULL);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
haszonekey = dns_dnssec_haszonekey(&keyset); result = dns_rdataset_first(&keyset);
while (result == ISC_R_SUCCESS) {
dns_rdata_t keyrdata = DNS_RDATA_INIT;
dns_rdataset_current(&keyset, &keyrdata);
if (dns_zonekey_iszonekey(&keyrdata)) {
haszonekey = true;
break;
}
result = dns_rdataset_next(&keyset);
}
dns_rdataset_disassociate(&keyset); dns_rdataset_disassociate(&keyset);
} }
if (!haszonekey) { if (!haszonekey) {
version->secure = false;
version->havensec3 = false;
return; return;
} }
@@ -1173,11 +1181,12 @@ setsecure(dns_db_t *db, qpz_version_t *version, dns_dbnode_t *origin) {
setnsec3parameters(db, version); setnsec3parameters(db, version);
/* /*
* If we don't have a valid NSEC/NSEC3 chain, * Do we have a valid NSEC/NSEC3 chain?
* clear the secure flag.
*/ */
if (version->havensec3 || hasnsec) { if (version->havensec3 || hasnsec) {
version->secure = true; version->secure = true;
} else {
version->secure = false;
} }
} }
+985 -1267
View File
File diff suppressed because it is too large Load Diff
+52 -52
View File
@@ -1011,46 +1011,59 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
static isc_result_t static isc_result_t
select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) { select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
isc_result_t result; isc_result_t result;
dns_rdata_rrsig_t *siginfo = val->siginfo;
isc_buffer_t b;
dns_rdata_t rdata = DNS_RDATA_INIT;
dst_key_t *oldkey = val->key;
bool no_rdata = false;
if (val->key == NULL) { if (oldkey == NULL) {
result = dns_rdataset_first(rdataset); result = dns_rdataset_first(rdataset);
} else { } else {
dst_key_free(&val->key); dst_key_free(&oldkey);
val->key = NULL; val->key = NULL;
result = dns_rdataset_next(rdataset); result = dns_rdataset_next(rdataset);
} }
if (result == ISC_R_NOMORE) { if (result != ISC_R_SUCCESS) {
return ISC_R_NOTFOUND; goto done;
} }
for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { do {
dns_rdata_rrsig_t *siginfo = val->siginfo;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_dnskey_t key;
isc_region_t r;
dns_rdataset_current(rdataset, &rdata); dns_rdataset_current(rdataset, &rdata);
dns_rdata_tostruct(&rdata, &key, NULL); /* can't fail */
if (key.algorithm != siginfo->algorithm || isc_buffer_init(&b, rdata.data, rdata.length);
(key.flags & DNS_KEYFLAG_REVOKE) != 0 || isc_buffer_add(&b, rdata.length);
!dns_dnssec_iszonekey(&key)) INSIST(val->key == NULL);
{ result = dst_key_fromdns_ex(&siginfo->signer, rdata.rdclass, &b,
continue; val->view->mctx, no_rdata,
} &val->key);
dns_rdata_toregion(&rdata, &r);
if (dst_region_computeid(&r) != siginfo->keyid) {
continue;
}
result = dns_dnssec_keyfromrdata(&siginfo->signer, &rdata,
val->view->mctx, &val->key);
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
/* found the key we wanted */ if (siginfo->algorithm ==
break; (dns_secalg_t)dst_key_alg(val->key) &&
siginfo->keyid ==
(dns_keytag_t)dst_key_id(val->key) &&
(dst_key_flags(val->key) & DNS_KEYFLAG_REVOKE) ==
0 &&
dst_key_iszonekey(val->key))
{
if (no_rdata) {
/* Retry with full key */
dns_rdata_reset(&rdata);
dst_key_free(&val->key);
no_rdata = false;
continue;
}
/* This is the key we're looking for. */
goto done;
}
dst_key_free(&val->key);
} }
} dns_rdata_reset(&rdata);
result = dns_rdataset_next(rdataset);
no_rdata = true;
} while (result == ISC_R_SUCCESS);
done:
if (result == ISC_R_NOMORE) { if (result == ISC_R_NOMORE) {
result = ISC_R_NOTFOUND; result = ISC_R_NOTFOUND;
} }
@@ -1232,10 +1245,7 @@ compute_keytag(dns_rdata_t *rdata) {
static bool static bool
over_max_validations(dns_validator_t *val) { over_max_validations(dns_validator_t *val) {
if (val->nvalidations == NULL || if (val->nvalidations == NULL || (*val->nvalidations) > 0) {
isc_counter_used(val->nvalidations) <
isc_counter_getlimit(val->nvalidations))
{
return false; return false;
} }
@@ -1249,14 +1259,14 @@ consume_validation(dns_validator_t *val) {
if (val->nvalidations == NULL) { if (val->nvalidations == NULL) {
return; return;
} }
(void)isc_counter_increment(val->nvalidations); INSIST((*val->nvalidations) > 0);
(*val->nvalidations)--;
} }
static bool static bool
over_max_fails(dns_validator_t *val) { over_max_fails(dns_validator_t *val) {
if (val->nfails == NULL || if (val->nfails == NULL || (*val->nfails) > 0) {
isc_counter_used(val->nfails) < isc_counter_getlimit(val->nfails))
{
return false; return false;
} }
@@ -1270,7 +1280,9 @@ consume_validation_fail(dns_validator_t *val) {
if (val->nfails == NULL) { if (val->nfails == NULL) {
return; return;
} }
(void)isc_counter_increment(val->nfails); INSIST((*val->nfails) > 0);
(*val->nfails)--;
} }
/*% /*%
@@ -3380,7 +3392,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
dns_message_t *message, unsigned int options, dns_message_t *message, unsigned int options,
isc_loop_t *loop, isc_job_cb cb, void *arg, isc_loop_t *loop, isc_job_cb cb, void *arg,
isc_counter_t *nvalidations, isc_counter_t *nfails, uint32_t *nvalidations, uint32_t *nfails,
isc_counter_t *qc, isc_counter_t *gqc, isc_counter_t *qc, isc_counter_t *gqc,
dns_edectx_t *edectx, dns_validator_t **validatorp) { dns_edectx_t *edectx, dns_validator_t **validatorp) {
isc_result_t result = ISC_R_FAILURE; isc_result_t result = ISC_R_FAILURE;
@@ -3412,6 +3424,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
.cb = cb, .cb = cb,
.arg = arg, .arg = arg,
.rdata = DNS_RDATA_INIT, .rdata = DNS_RDATA_INIT,
.nvalidations = nvalidations,
.nfails = nfails,
.edectx = edectx, .edectx = edectx,
}; };
@@ -3421,14 +3435,6 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
dns_message_attach(message, &val->message); dns_message_attach(message, &val->message);
} }
if (nfails != NULL) {
isc_counter_attach(nfails, &val->nfails);
}
if (nvalidations != NULL) {
isc_counter_attach(nvalidations, &val->nvalidations);
}
if (qc != NULL) { if (qc != NULL) {
isc_counter_attach(qc, &val->qc); isc_counter_attach(qc, &val->qc);
} }
@@ -3521,12 +3527,6 @@ destroy_validator(dns_validator_t *val) {
if (val->message != NULL) { if (val->message != NULL) {
dns_message_detach(&val->message); dns_message_detach(&val->message);
} }
if (val->nfails != NULL) {
isc_counter_detach(&val->nfails);
}
if (val->nvalidations != NULL) {
isc_counter_detach(&val->nvalidations);
}
if (val->qc != NULL) { if (val->qc != NULL) {
isc_counter_detach(&val->qc); isc_counter_detach(&val->qc);
} }
+7 -17
View File
@@ -1533,41 +1533,31 @@ dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now, const dns_name_t *name,
return dns_ntatable_covered(view->ntatable_priv, now, name, anchor); return dns_ntatable_covered(view->ntatable_priv, now, name, anchor);
} }
isc_result_t bool
dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name, dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name,
isc_stdtime_t now, bool checknta, bool *ntap, isc_stdtime_t now, bool checknta, bool *ntap) {
bool *secure_domain) {
isc_result_t result;
bool secure = false; bool secure = false;
dns_fixedname_t fn; dns_fixedname_t fn;
dns_name_t *anchor; dns_name_t *anchor;
REQUIRE(DNS_VIEW_VALID(view)); REQUIRE(DNS_VIEW_VALID(view));
if (view->secroots_priv == NULL) { if (!view->enablevalidation || view->secroots_priv == NULL) {
return ISC_R_NOTFOUND; return false;
} }
anchor = dns_fixedname_initname(&fn); anchor = dns_fixedname_initname(&fn);
secure = dns_keytable_issecuredomain(view->secroots_priv, name, anchor);
result = dns_keytable_issecuredomain(view->secroots_priv, name, anchor,
&secure);
if (result != ISC_R_SUCCESS) {
return result;
}
SET_IF_NOT_NULL(ntap, false); SET_IF_NOT_NULL(ntap, false);
if (checknta && secure && view->ntatable_priv != NULL && if (checknta && secure && view->ntatable_priv != NULL &&
dns_ntatable_covered(view->ntatable_priv, now, name, anchor)) dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
{ {
if (ntap != NULL) { SET_IF_NOT_NULL(ntap, true);
*ntap = true;
}
secure = false; secure = false;
} }
*secure_domain = secure; return secure;
return ISC_R_SUCCESS;
} }
void void
+46 -60
View File
@@ -5998,123 +5998,106 @@ dns_zone_getkeyopts(dns_zone_t *zone) {
return atomic_load_relaxed(&zone->keyopts); return atomic_load_relaxed(&zone->keyopts);
} }
void isc_result_t
dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) { dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(xfrsource != NULL);
LOCK_ZONE(zone); LOCK_ZONE(zone);
zone->xfrsource4 = *xfrsource; zone->xfrsource4 = *xfrsource;
UNLOCK_ZONE(zone); UNLOCK_ZONE(zone);
return ISC_R_SUCCESS;
} }
void isc_sockaddr_t *
dns_zone_getxfrsource4(dns_zone_t *zone, isc_sockaddr_t *xfrsource) { dns_zone_getxfrsource4(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(xfrsource != NULL); return &zone->xfrsource4;
LOCK_ZONE(zone);
*xfrsource = zone->xfrsource4;
UNLOCK_ZONE(zone);
} }
void isc_result_t
dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) { dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(xfrsource != NULL);
LOCK_ZONE(zone); LOCK_ZONE(zone);
zone->xfrsource6 = *xfrsource; zone->xfrsource6 = *xfrsource;
UNLOCK_ZONE(zone); UNLOCK_ZONE(zone);
return ISC_R_SUCCESS;
} }
void isc_sockaddr_t *
dns_zone_getxfrsource6(dns_zone_t *zone, isc_sockaddr_t *xfrsource) { dns_zone_getxfrsource6(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(xfrsource != NULL); return &zone->xfrsource6;
LOCK_ZONE(zone);
*xfrsource = zone->xfrsource6;
UNLOCK_ZONE(zone);
} }
void isc_result_t
dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) { dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(parentalsrc != NULL);
LOCK_ZONE(zone); LOCK_ZONE(zone);
zone->parentalsrc4 = *parentalsrc; zone->parentalsrc4 = *parentalsrc;
UNLOCK_ZONE(zone); UNLOCK_ZONE(zone);
return ISC_R_SUCCESS;
} }
void isc_sockaddr_t *
dns_zone_getparentalsrc4(dns_zone_t *zone, isc_sockaddr_t *parentalsrc) { dns_zone_getparentalsrc4(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(parentalsrc != NULL); return &zone->parentalsrc4;
LOCK_ZONE(zone);
*parentalsrc = zone->parentalsrc4;
UNLOCK_ZONE(zone);
} }
void isc_result_t
dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) { dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
LOCK_ZONE(zone); LOCK_ZONE(zone);
zone->parentalsrc6 = *parentalsrc; zone->parentalsrc6 = *parentalsrc;
UNLOCK_ZONE(zone); UNLOCK_ZONE(zone);
return ISC_R_SUCCESS;
} }
void isc_sockaddr_t *
dns_zone_getparentalsrc6(dns_zone_t *zone, isc_sockaddr_t *parentalsrc) { dns_zone_getparentalsrc6(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(parentalsrc != NULL); return &zone->parentalsrc6;
LOCK_ZONE(zone);
*parentalsrc = zone->parentalsrc6;
UNLOCK_ZONE(zone);
} }
void isc_result_t
dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) { dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(notifysrc != NULL);
LOCK_ZONE(zone); LOCK_ZONE(zone);
zone->notifysrc4 = *notifysrc; zone->notifysrc4 = *notifysrc;
UNLOCK_ZONE(zone); UNLOCK_ZONE(zone);
return ISC_R_SUCCESS;
} }
void isc_sockaddr_t *
dns_zone_getnotifysrc4(dns_zone_t *zone, isc_sockaddr_t *notifysrc) { dns_zone_getnotifysrc4(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(notifysrc != NULL); return &zone->notifysrc4;
LOCK_ZONE(zone);
*notifysrc = zone->notifysrc4;
UNLOCK_ZONE(zone);
} }
void isc_result_t
dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) { dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(notifysrc != NULL);
LOCK_ZONE(zone); LOCK_ZONE(zone);
zone->notifysrc6 = *notifysrc; zone->notifysrc6 = *notifysrc;
UNLOCK_ZONE(zone); UNLOCK_ZONE(zone);
return ISC_R_SUCCESS;
} }
void isc_sockaddr_t *
dns_zone_getnotifysrc6(dns_zone_t *zone, isc_sockaddr_t *notifysrc) { dns_zone_getnotifysrc6(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(notifysrc != NULL); return &zone->notifysrc6;
LOCK_ZONE(zone);
*notifysrc = zone->notifysrc6;
UNLOCK_ZONE(zone);
} }
void void
@@ -18388,28 +18371,31 @@ dns_zone_getsigresigninginterval(dns_zone_t *zone) {
return zone->sigresigninginterval; return zone->sigresigninginterval;
} }
void isc_sockaddr_t
dns_zone_getsourceaddr(dns_zone_t *zone, isc_sockaddr_t *sourceaddr) { dns_zone_getsourceaddr(dns_zone_t *zone) {
isc_sockaddr_t sourceaddr;
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(sourceaddr != NULL);
LOCK_ZONE(zone); LOCK_ZONE(zone);
INSIST(dns_remote_count(&zone->primaries) > 0); INSIST(dns_remote_count(&zone->primaries) > 0);
*sourceaddr = zone->sourceaddr; sourceaddr = zone->sourceaddr;
UNLOCK_ZONE(zone); UNLOCK_ZONE(zone);
return sourceaddr;
} }
isc_result_t isc_result_t
dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *primaryaddr) { dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *dest) {
isc_result_t result = ISC_R_NOMORE; isc_result_t result = ISC_R_NOMORE;
REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(primaryaddr != NULL); REQUIRE(dest != NULL);
LOCK_ZONE(zone); LOCK_ZONE(zone);
INSIST(dns_remote_count(&zone->primaries) > 0); INSIST(dns_remote_count(&zone->primaries) > 0);
if (!dns_remote_done(&zone->primaries)) { if (!dns_remote_done(&zone->primaries)) {
*primaryaddr = dns_remote_curraddr(&zone->primaries); *dest = dns_remote_curraddr(&zone->primaries);
result = ISC_R_SUCCESS; result = ISC_R_SUCCESS;
} }
UNLOCK_ZONE(zone); UNLOCK_ZONE(zone);
+54
View File
@@ -0,0 +1,54 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* 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 https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
/*! \file */
#include <stdbool.h>
#include <isc/result.h>
#include <isc/types.h>
#include <isc/util.h>
#include <dns/keyvalues.h>
#include <dns/rdata.h>
#include <dns/rdatastruct.h>
#include <dns/types.h>
#include <dns/zonekey.h>
bool
dns_zonekey_iszonekey(dns_rdata_t *keyrdata) {
isc_result_t result;
dns_rdata_dnskey_t key;
bool iszonekey = true;
REQUIRE(keyrdata != NULL);
result = dns_rdata_tostruct(keyrdata, &key, NULL);
if (result != ISC_R_SUCCESS) {
return false;
}
if ((key.flags & DNS_KEYTYPE_NOAUTH) != 0) {
iszonekey = false;
}
if ((key.flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) {
iszonekey = false;
}
if (key.protocol != DNS_KEYPROTO_DNSSEC &&
key.protocol != DNS_KEYPROTO_ANY)
{
iszonekey = false;
}
return iszonekey;
}
-1
View File
@@ -26,7 +26,6 @@ libisc_la_HEADERS = \
include/isc/file.h \ include/isc/file.h \
include/isc/formatcheck.h \ include/isc/formatcheck.h \
include/isc/fuzz.h \ include/isc/fuzz.h \
include/isc/fxhash.h \
include/isc/getaddresses.h \ include/isc/getaddresses.h \
include/isc/hash.h \ include/isc/hash.h \
include/isc/hashmap.h \ include/isc/hashmap.h \
+9 -19
View File
@@ -131,28 +131,18 @@ isc__ascii_load8(const uint8_t *ptr) {
* Compare `len` bytes at `a` and `b` for case-insensitive equality * Compare `len` bytes at `a` and `b` for case-insensitive equality
*/ */
static inline bool static inline bool
isc_ascii_lowerequal(const uint8_t *restrict a, const uint8_t *restrict b, isc_ascii_lowerequal(const uint8_t *a, const uint8_t *b, unsigned int len) {
unsigned int len) {
uint64_t a8 = 0, b8 = 0; uint64_t a8 = 0, b8 = 0;
if (len >= 8) { while (len >= 8) {
const uint8_t *a_tail = a + len - 8; a8 = isc_ascii_tolower8(isc__ascii_load8(a));
const uint8_t *b_tail = b + len - 8; b8 = isc_ascii_tolower8(isc__ascii_load8(b));
while (len >= 8) { if (a8 != b8) {
a8 = isc_ascii_tolower8(isc__ascii_load8(a)); return false;
b8 = isc_ascii_tolower8(isc__ascii_load8(b));
if (a8 != b8) {
return false;
}
len -= 8;
a += 8;
b += 8;
} }
len -= 8;
a8 = isc_ascii_tolower8(isc__ascii_load8(a_tail)); a += 8;
b8 = isc_ascii_tolower8(isc__ascii_load8(b_tail)); b += 8;
return a8 == b8;
} }
while (len-- > 0) { while (len-- > 0) {
if (isc_ascii_tolower(*a++) != isc_ascii_tolower(*b++)) { if (isc_ascii_tolower(*a++) != isc_ascii_tolower(*b++)) {
return false; return false;
-89
View File
@@ -1,89 +0,0 @@
#pragma once
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the Software), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
/* The constant K from Rust's fxhash */
#define K 0x9e3779b97f4a7c15ull
static inline size_t
rotate_left(size_t x, unsigned int n) {
return (x << n) | (x >> (sizeof(size_t) * 8 - n));
}
static inline size_t
fx_add_to_hash(size_t hash, size_t i) {
return rotate_left(hash, 5) ^ i * K;
}
/*
* Beware: this implementation will use an approximate conversion to lowercase.
* This is ok as fxhash is already not hash-flooding resistant and we use it
* only for config parsing.
*/
static inline size_t
fx_hash_bytes(size_t initial_hash, const uint8_t *restrict bytes, size_t len,
bool case_sensitive) {
size_t hash = initial_hash;
size_t case_mask = case_sensitive
? -1ull
: (0b11011111 * 0x0101010101010101ull);
while (len >= sizeof(size_t)) {
size_t value;
memmove(&value, bytes, sizeof(size_t));
hash = fx_add_to_hash(hash, value & case_mask);
bytes += sizeof(size_t);
len -= sizeof(size_t);
}
/* Will be ignored if sizeof(size_t) <= 4 */
if (len >= 4) {
uint32_t value;
memmove(&value, bytes, sizeof(uint32_t));
hash = fx_add_to_hash(hash, value & case_mask);
bytes += 4;
len -= 4;
}
/* Will be ignored if sizeof(size_t) <= 2 */
if (len >= 2) {
uint16_t value;
memmove(&value, bytes, sizeof(uint16_t));
hash = fx_add_to_hash(hash, value & case_mask);
bytes += 2;
len -= 2;
}
if (len >= 1) {
hash = fx_add_to_hash(hash, bytes[0] & case_mask);
}
return hash;
}
+11 -9
View File
@@ -16,7 +16,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <isc/ascii.h> #include <isc/ascii.h>
#include <isc/fxhash.h>
#include <isc/hash.h> #include <isc/hash.h>
#include <isc/hashmap.h> #include <isc/hashmap.h>
#include <isc/magic.h> #include <isc/magic.h>
@@ -32,9 +31,9 @@ typedef struct elt {
isc_symvalue_t value; isc_symvalue_t value;
} elt_t; } elt_t;
/* 4 bits means 16 entries at creation, which matches the common use of /* 7 bits means 128 entries at creation, which matches the common use of
* symtab */ * symtab */
#define ISC_SYMTAB_INIT_HASH_BITS 4 #define ISC_SYMTAB_INIT_HASH_BITS 7
#define SYMTAB_MAGIC ISC_MAGIC('S', 'y', 'm', 'T') #define SYMTAB_MAGIC ISC_MAGIC('S', 'y', 'm', 'T')
#define VALID_SYMTAB(st) ISC_MAGIC_VALID(st, SYMTAB_MAGIC) #define VALID_SYMTAB(st) ISC_MAGIC_VALID(st, SYMTAB_MAGIC)
@@ -123,7 +122,7 @@ elt__match(void *node, const void *key0, bool case_sensitive) {
if (case_sensitive) { if (case_sensitive) {
return memcmp(elt->key, key->key, key->size) == 0; return memcmp(elt->key, key->key, key->size) == 0;
} else { } else {
return isc_ascii_lowerequal(elt->key, key->key, key->size); return isc_ascii_lowercmp(elt->key, key->key, key->size) == 0;
} }
} }
@@ -137,11 +136,14 @@ elt_match_nocase(void *node, const void *key) {
return elt__match(node, key, false); return elt__match(node, key, false);
} }
static inline uint32_t static uint32_t
elt_hash(elt_t *restrict elt, bool case_sensitive) { elt_hash(elt_t *elt, bool case_sensitive) {
const uint8_t *ptr = elt->key; isc_hash32_t hash;
size_t len = elt->size;
return fx_hash_bytes(0, ptr, len, case_sensitive); isc_hash32_init(&hash);
isc_hash32_hash(&hash, elt->key, elt->size, case_sensitive);
isc_hash32_hash(&hash, &elt->type, sizeof(elt->type), false);
return isc_hash32_finalize(&hash);
} }
isc_result_t isc_result_t
+1 -13
View File
@@ -1290,7 +1290,6 @@ process_cookie(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
isc_stdtime_t now; isc_stdtime_t now;
uint32_t when; uint32_t when;
isc_buffer_t db; isc_buffer_t db;
bool alwaysvalid;
/* /*
* If we have already seen a cookie option skip this cookie option. * If we have already seen a cookie option skip this cookie option.
@@ -1336,22 +1335,11 @@ process_cookie(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
when = isc_buffer_getuint32(buf); when = isc_buffer_getuint32(buf);
isc_buffer_forward(buf, 8); isc_buffer_forward(buf, 8);
/*
* For '-T cookiealwaysvalid' still process everything to not skew any
* performance tests involving cookies, but make sure that the cookie
* check passes in the end, given the cookie was structurally correct.
*/
alwaysvalid = ns_server_getoption(client->manager->sctx,
NS_SERVER_COOKIEALWAYSVALID);
/* /*
* Allow for a 5 minute clock skew between servers sharing a secret. * Allow for a 5 minute clock skew between servers sharing a secret.
* Only accept COOKIE if we have talked to the client in the last hour. * Only accept COOKIE if we have talked to the client in the last hour.
*/ */
now = isc_stdtime_now(); now = isc_stdtime_now();
if (alwaysvalid) {
now = when;
}
if (isc_serial_gt(when, (now + 300)) /* In the future. */ || if (isc_serial_gt(when, (now + 300)) /* In the future. */ ||
isc_serial_lt(when, (now - 3600)) /* In the past. */) isc_serial_lt(when, (now - 3600)) /* In the past. */)
{ {
@@ -1364,7 +1352,7 @@ process_cookie(ns_client_t *client, isc_buffer_t *buf, size_t optlen) {
isc_buffer_init(&db, dbuf, sizeof(dbuf)); isc_buffer_init(&db, dbuf, sizeof(dbuf));
compute_cookie(client, when, client->manager->sctx->secret, &db); compute_cookie(client, when, client->manager->sctx->secret, &db);
if (isc_safe_memequal(old, dbuf, COOKIE_SIZE) || alwaysvalid) { if (isc_safe_memequal(old, dbuf, COOKIE_SIZE)) {
ns_stats_increment(client->manager->sctx->nsstats, ns_stats_increment(client->manager->sctx->nsstats,
ns_statscounter_cookiematch); ns_statscounter_cookiematch);
client->attributes |= NS_CLIENTATTR_HAVECOOKIE; client->attributes |= NS_CLIENTATTR_HAVECOOKIE;
+18 -19
View File
@@ -32,25 +32,24 @@
#include <ns/types.h> #include <ns/types.h>
#define NS_SERVER_LOGQUERIES 0x00000001U /*%< log queries */ #define NS_SERVER_LOGQUERIES 0x00000001U /*%< log queries */
#define NS_SERVER_NOAA 0x00000002U /*%< -T noaa */ #define NS_SERVER_NOAA 0x00000002U /*%< -T noaa */
#define NS_SERVER_NOSOA 0x00000004U /*%< -T nosoa */ #define NS_SERVER_NOSOA 0x00000004U /*%< -T nosoa */
#define NS_SERVER_NONEAREST 0x00000008U /*%< -T nonearest */ #define NS_SERVER_NONEAREST 0x00000008U /*%< -T nonearest */
#define NS_SERVER_NOEDNS 0x00000020U /*%< -T noedns */ #define NS_SERVER_NOEDNS 0x00000020U /*%< -T noedns */
#define NS_SERVER_DROPEDNS 0x00000040U /*%< -T dropedns */ #define NS_SERVER_DROPEDNS 0x00000040U /*%< -T dropedns */
#define NS_SERVER_NOTCP 0x00000080U /*%< -T notcp */ #define NS_SERVER_NOTCP 0x00000080U /*%< -T notcp */
#define NS_SERVER_DISABLE4 0x00000100U /*%< -6 */ #define NS_SERVER_DISABLE4 0x00000100U /*%< -6 */
#define NS_SERVER_DISABLE6 0x00000200U /*%< -4 */ #define NS_SERVER_DISABLE6 0x00000200U /*%< -4 */
#define NS_SERVER_FIXEDLOCAL 0x00000400U /*%< -T fixedlocal */ #define NS_SERVER_FIXEDLOCAL 0x00000400U /*%< -T fixedlocal */
#define NS_SERVER_SIGVALINSECS 0x00000800U /*%< -T sigvalinsecs */ #define NS_SERVER_SIGVALINSECS 0x00000800U /*%< -T sigvalinsecs */
#define NS_SERVER_EDNSFORMERR 0x00001000U /*%< -T ednsformerr (STD13) */ #define NS_SERVER_EDNSFORMERR 0x00001000U /*%< -T ednsformerr (STD13) */
#define NS_SERVER_EDNSNOTIMP 0x00002000U /*%< -T ednsnotimp */ #define NS_SERVER_EDNSNOTIMP 0x00002000U /*%< -T ednsnotimp */
#define NS_SERVER_EDNSREFUSED 0x00004000U /*%< -T ednsrefused */ #define NS_SERVER_EDNSREFUSED 0x00004000U /*%< -T ednsrefused */
#define NS_SERVER_TRANSFERINSECS 0x00008000U /*%< -T transferinsecs */ #define NS_SERVER_TRANSFERINSECS 0x00008000U /*%< -T transferinsecs */
#define NS_SERVER_TRANSFERSLOWLY 0x00010000U /*%< -T transferslowly */ #define NS_SERVER_TRANSFERSLOWLY 0x00010000U /*%< -T transferslowly */
#define NS_SERVER_TRANSFERSTUCK 0x00020000U /*%< -T transferstuck */ #define NS_SERVER_TRANSFERSTUCK 0x00020000U /*%< -T transferstuck */
#define NS_SERVER_LOGRESPONSES 0x00040000U /*%< log responses */ #define NS_SERVER_LOGRESPONSES 0x00040000U /*%< log responses */
#define NS_SERVER_COOKIEALWAYSVALID 0x00080000U /*%< -T cookiealwaysvalid */
/*% /*%
* Type for callback function to get hostname. * Type for callback function to get hostname.
+11 -19
View File
@@ -2420,33 +2420,25 @@ get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(keyrdataset)) for (; result == ISC_R_SUCCESS; result = dns_rdataset_next(keyrdataset))
{ {
dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_dnskey_t key; isc_buffer_t b;
isc_region_t r;
dns_rdataset_current(keyrdataset, &rdata); dns_rdataset_current(keyrdataset, &rdata);
dns_rdata_tostruct(&rdata, &key, NULL); /* can't fail */ isc_buffer_init(&b, rdata.data, rdata.length);
isc_buffer_add(&b, rdata.length);
if (rrsig->algorithm != key.algorithm || result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
!dns_dnssec_iszonekey(&key)) client->manager->mctx, keyp);
if (result != ISC_R_SUCCESS) {
continue;
}
if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
dst_key_iszonekey(*keyp))
{ {
continue;
}
dns_rdata_toregion(&rdata, &r);
if (dst_region_computeid(&r) != rrsig->keyid) {
continue;
}
result = dns_dnssec_keyfromrdata(&rrsig->signer, &rdata,
client->manager->mctx, keyp);
if (result == ISC_R_SUCCESS) {
secure = true; secure = true;
break; break;
} }
dst_key_free(keyp); dst_key_free(keyp);
} }
return secure; return secure;
} }
+19 -39
View File
@@ -535,7 +535,6 @@ ISC_LOOP_TEST_IMPL(find) {
/* check issecuredomain() */ /* check issecuredomain() */
ISC_LOOP_TEST_IMPL(issecuredomain) { ISC_LOOP_TEST_IMPL(issecuredomain) {
bool issecure;
const char **n; const char **n;
const char *names[] = { "example.com", "sub.example.com", const char *names[] = { "example.com", "sub.example.com",
"null.example", "sub.null.example", NULL }; "null.example", "sub.null.example", NULL };
@@ -550,22 +549,16 @@ ISC_LOOP_TEST_IMPL(issecuredomain) {
* of installing a null key). * of installing a null key).
*/ */
for (n = names; *n != NULL; n++) { for (n = names; *n != NULL; n++) {
assert_int_equal(dns_keytable_issecuredomain(keytable, assert_true(dns_keytable_issecuredomain(keytable, str2name(*n),
str2name(*n), NULL, NULL));
&issecure),
ISC_R_SUCCESS);
assert_true(issecure);
} }
/* /*
* If the key table has no entry (not even a null one) for a domain or * If the key table has no entry (not even a null one) for a domain or
* any of its ancestors, that domain is considered insecure. * any of its ancestors, that domain is considered insecure.
*/ */
assert_int_equal(dns_keytable_issecuredomain(keytable, assert_false(dns_keytable_issecuredomain(
str2name("example.org"), keytable, str2name("example.org"), NULL));
NULL, &issecure),
ISC_R_SUCCESS);
assert_false(issecure);
destroy_tables(); destroy_tables();
@@ -595,7 +588,7 @@ ISC_LOOP_TEST_IMPL(dump) {
/* check negative trust anchors */ /* check negative trust anchors */
ISC_LOOP_TEST_IMPL(nta) { ISC_LOOP_TEST_IMPL(nta) {
isc_result_t result; isc_result_t result;
bool issecure, covered; bool covered;
dns_fixedname_t fn; dns_fixedname_t fn;
dns_name_t *keyname = dns_fixedname_name(&fn); dns_name_t *keyname = dns_fixedname_name(&fn);
unsigned char digest[ISC_MAX_MD_SIZE]; unsigned char digest[ISC_MAX_MD_SIZE];
@@ -626,20 +619,15 @@ ISC_LOOP_TEST_IMPL(nta) {
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
/* Should be secure */ /* Should be secure */
result = dns_view_issecuredomain(myview, assert_true(dns_view_issecuredomain(
str2name("test.secure.example"), now, myview, str2name("test.secure.example"), now, true, &covered));
true, &covered, &issecure);
assert_int_equal(result, ISC_R_SUCCESS);
assert_false(covered); assert_false(covered);
assert_true(issecure);
/* Should not be secure */ /* Should not be secure */
result = dns_view_issecuredomain(myview, assert_false(dns_view_issecuredomain(myview,
str2name("test.insecure.example"), now, str2name("test.insecure.example"),
true, &covered, &issecure); now, true, &covered));
assert_int_equal(result, ISC_R_SUCCESS);
assert_true(covered); assert_true(covered);
assert_false(issecure);
/* NTA covered */ /* NTA covered */
covered = dns_view_ntacovers(myview, now, str2name("insecure.example"), covered = dns_view_ntacovers(myview, now, str2name("insecure.example"),
@@ -652,38 +640,30 @@ ISC_LOOP_TEST_IMPL(nta) {
assert_false(covered); assert_false(covered);
/* As of now + 2, the NTA should be clear */ /* As of now + 2, the NTA should be clear */
result = dns_view_issecuredomain(myview, assert_true(dns_view_issecuredomain(myview,
str2name("test.insecure.example"), str2name("test.insecure.example"),
now + 2, true, &covered, &issecure); now + 2, true, &covered));
assert_int_equal(result, ISC_R_SUCCESS);
assert_false(covered); assert_false(covered);
assert_true(issecure);
/* Now check deletion */ /* Now check deletion */
result = dns_view_issecuredomain(myview, str2name("test.new.example"), assert_true(dns_view_issecuredomain(
now, true, &covered, &issecure); myview, str2name("test.new.example"), now, true, &covered));
assert_int_equal(result, ISC_R_SUCCESS);
assert_false(covered); assert_false(covered);
assert_true(issecure);
result = dns_ntatable_add(ntatable, str2name("new.example"), false, now, result = dns_ntatable_add(ntatable, str2name("new.example"), false, now,
3600); 3600);
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
result = dns_view_issecuredomain(myview, str2name("test.new.example"), assert_false(dns_view_issecuredomain(
now, true, &covered, &issecure); myview, str2name("test.new.example"), now, true, &covered));
assert_int_equal(result, ISC_R_SUCCESS);
assert_true(covered); assert_true(covered);
assert_false(issecure);
result = dns_ntatable_delete(ntatable, str2name("new.example")); result = dns_ntatable_delete(ntatable, str2name("new.example"));
assert_int_equal(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
result = dns_view_issecuredomain(myview, str2name("test.new.example"), assert_true(dns_view_issecuredomain(
now, true, &covered, &issecure); myview, str2name("test.new.example"), now, true, &covered));
assert_int_equal(result, ISC_R_SUCCESS);
assert_false(covered); assert_false(covered);
assert_true(issecure);
isc_loopmgr_shutdown(loopmgr); isc_loopmgr_shutdown(loopmgr);