summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/bin/named/query.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/bin/named/query.c')
-rw-r--r--contrib/bind9/bin/named/query.c180
1 files changed, 132 insertions, 48 deletions
diff --git a/contrib/bind9/bin/named/query.c b/contrib/bind9/bin/named/query.c
index 10a7d6d..9e67f2d 100644
--- a/contrib/bind9/bin/named/query.c
+++ b/contrib/bind9/bin/named/query.c
@@ -25,6 +25,7 @@
#include <isc/hex.h>
#include <isc/mem.h>
+#include <isc/serial.h>
#include <isc/stats.h>
#include <isc/util.h>
@@ -2775,11 +2776,12 @@ query_add_cname(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
*/
static void
mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
- isc_uint32_t ttl, dns_rdataset_t *rdataset,
+ dns_rdata_rrsig_t *rrsig, dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset)
{
isc_result_t result;
dns_dbnode_t *node = NULL;
+ isc_stdtime_t now;
rdataset->trust = dns_trust_secure;
sigrdataset->trust = dns_trust_secure;
@@ -2790,17 +2792,10 @@ mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
result = dns_db_findnode(db, name, ISC_TRUE, &node);
if (result != ISC_R_SUCCESS)
return;
- /*
- * Bound the validated ttls then minimise.
- */
- if (sigrdataset->ttl > ttl)
- sigrdataset->ttl = ttl;
- if (rdataset->ttl > ttl)
- rdataset->ttl = ttl;
- if (rdataset->ttl > sigrdataset->ttl)
- rdataset->ttl = sigrdataset->ttl;
- else
- sigrdataset->ttl = rdataset->ttl;
+
+ isc_stdtime_get(&now);
+ dns_rdataset_trimttl(rdataset, sigrdataset, rrsig, now,
+ client->view->acceptexpired);
(void)dns_db_addrdataset(db, node, NULL, client->now, rdataset,
0, NULL);
@@ -2925,8 +2920,7 @@ validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
client->view->acceptexpired)) {
dst_key_free(&key);
dns_rdataset_disassociate(&keyrdataset);
- mark_secure(client, db, name,
- rrsig.originalttl,
+ mark_secure(client, db, name, &rrsig,
rdataset, sigrdataset);
return (ISC_TRUE);
}
@@ -3802,6 +3796,13 @@ rpz_clean(dns_zone_t **zonep, dns_db_t **dbp, dns_dbnode_t **nodep,
dns_rdataset_disassociate(*rdatasetp);
}
+static void
+rpz_match_clear(dns_rpz_st_t *st)
+{
+ rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
+ st->m.version = NULL;
+}
+
static inline isc_result_t
rpz_ready(ns_client_t *client, dns_zone_t **zonep, dns_db_t **dbp,
dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp)
@@ -3821,10 +3822,9 @@ static void
rpz_st_clear(ns_client_t *client) {
dns_rpz_st_t *st = client->query.rpz_st;
- rpz_clean(&st->m.zone, &st->m.db, &st->m.node, NULL);
- st->m.version = NULL;
if (st->m.rdataset != NULL)
query_putrdataset(client, &st->m.rdataset);
+ rpz_match_clear(st);
rpz_clean(NULL, &st->r.db, NULL, NULL);
if (st->r.ns_rdataset != NULL)
@@ -3974,6 +3974,9 @@ rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset,
for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
rpz != NULL;
rpz = ISC_LIST_NEXT(rpz, link)) {
+ if (!RECURSIONOK(client) && rpz->recursive_only)
+ continue;
+
/*
* Do not check policy zones that cannot replace a policy
* already known to match.
@@ -4002,9 +4005,8 @@ rpz_rewrite_ip(ns_client_t *client, dns_rdataset_t *rdataset,
* hit, if any. Note the domain name and quality of the
* best hit.
*/
- (void)dns_db_rpz_findips(rpz, rpz_type, zone, db, version,
- rdataset, st,
- client->query.rpz_st->qname);
+ dns_db_rpz_findips(rpz, rpz_type, zone, db, version,
+ rdataset, st, client->query.rpz_st->qname);
rpz_clean(&zone, &db, NULL, NULL);
}
return (ISC_R_SUCCESS);
@@ -4109,8 +4111,8 @@ rpz_rewrite_rrsets(ns_client_t *client, dns_rpz_type_t rpz_type,
*/
static isc_result_t
rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
- dns_name_t *sname, dns_rpz_type_t rpz_type, dns_zone_t **zonep,
- dns_db_t **dbp, dns_dbversion_t **versionp,
+ dns_name_t *sname, dns_rpz_zone_t *rpz, dns_rpz_type_t rpz_type,
+ dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,
dns_dbnode_t **nodep, dns_rdataset_t **rdatasetp,
dns_rpz_policy_t *policyp)
{
@@ -4149,7 +4151,7 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
if (result != ISC_R_SUCCESS) {
dns_db_detachnode(*dbp, nodep);
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL, rpz_type,
- qnamef, "allrdatasets()", result);
+ qnamef, "allrdatasets() ", result);
*policyp = DNS_RPZ_POLICY_ERROR;
return (DNS_R_SERVFAIL);
}
@@ -4166,7 +4168,7 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
if (result != ISC_R_SUCCESS) {
if (result != ISC_R_NOMORE) {
rpz_log_fail(client, DNS_RPZ_ERROR_LEVEL,
- rpz_type, qnamef, "rdatasetiter",
+ rpz_type, qnamef, "rdatasetiter ",
result);
*policyp = DNS_RPZ_POLICY_ERROR;
return (DNS_R_SERVFAIL);
@@ -4194,7 +4196,7 @@ rpz_find(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qnamef,
if ((*rdatasetp)->type != dns_rdatatype_cname) {
policy = DNS_RPZ_POLICY_RECORD;
} else {
- policy = dns_rpz_decode_cname(*rdatasetp, sname);
+ policy = dns_rpz_decode_cname(rpz, *rdatasetp, sname);
if ((policy == DNS_RPZ_POLICY_RECORD ||
policy == DNS_RPZ_POLICY_WILDCNAME) &&
qtype != dns_rdatatype_cname &&
@@ -4265,6 +4267,9 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
for (rpz = ISC_LIST_HEAD(client->view->rpz_zones);
rpz != NULL;
rpz = ISC_LIST_NEXT(rpz, link)) {
+ if (!RECURSIONOK(client) && rpz->recursive_only)
+ continue;
+
/*
* Do not check policy zones that cannot replace a policy
* already known to match.
@@ -4310,11 +4315,11 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
}
/*
- * See if the policy record exists.
+ * See if the policy record exists and get its policy.
*/
- result = rpz_find(client, qtype, rpz_qname, qname, rpz_type,
- &zone, &db, &version, &node, rdatasetp,
- &policy);
+ result = rpz_find(client, qtype, rpz_qname, qname, rpz,
+ rpz_type, &zone, &db, &version, &node,
+ rdatasetp, &policy);
switch (result) {
case DNS_R_NXDOMAIN:
case DNS_R_EMPTYNAME:
@@ -4350,8 +4355,7 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
continue;
}
- rpz_clean(&st->m.zone, &st->m.db, &st->m.node,
- &st->m.rdataset);
+ rpz_match_clear(st);
st->m.rpz = rpz;
st->m.type = rpz_type;
st->m.prefix = 0;
@@ -4365,9 +4369,11 @@ rpz_rewrite_name(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qname,
trdataset = st->m.rdataset;
st->m.rdataset = *rdatasetp;
*rdatasetp = trdataset;
- st->m.ttl = st->m.rdataset->ttl;
+ st->m.ttl = ISC_MIN(st->m.rdataset->ttl,
+ rpz->max_policy_ttl);
} else {
- st->m.ttl = DNS_RPZ_TTL_DEFAULT;
+ st->m.ttl = ISC_MIN(DNS_RPZ_TTL_DEFAULT,
+ rpz->max_policy_ttl);
}
st->m.node = node;
node = NULL;
@@ -4462,13 +4468,13 @@ rpz_rewrite(ns_client_t *client, dns_rdatatype_t qtype, isc_result_t qresult,
case DNS_R_BROKENCHAIN:
rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL3, DNS_RPZ_TYPE_QNAME,
client->query.qname,
- "stop on qresult in rpz_rewrite()",
+ "stop on qresult in rpz_rewrite() ",
qresult);
return (ISC_R_SUCCESS);
default:
rpz_log_fail(client, DNS_RPZ_DEBUG_LEVEL1, DNS_RPZ_TYPE_QNAME,
client->query.qname,
- "stop on unrecognized qresult in rpz_rewrite()",
+ "stop on unrecognized qresult in rpz_rewrite() ",
qresult);
return (ISC_R_SUCCESS);
}
@@ -4647,10 +4653,11 @@ cleanup:
if (st->m.policy == DNS_RPZ_POLICY_MISS ||
st->m.policy == DNS_RPZ_POLICY_PASSTHRU ||
st->m.policy == DNS_RPZ_POLICY_ERROR) {
- if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU)
+ if (st->m.policy == DNS_RPZ_POLICY_PASSTHRU &&
+ result != DNS_R_DELEGATION)
rpz_log_rewrite(client, "", st->m.policy, st->m.type,
st->qname);
- rpz_clean(&st->m.zone, &st->m.db, &st->m.node, &st->m.rdataset);
+ rpz_match_clear(st);
}
if (st->m.policy == DNS_RPZ_POLICY_ERROR) {
st->m.type = DNS_RPZ_TYPE_BAD;
@@ -4664,6 +4671,64 @@ cleanup:
}
/*
+ * See if response policy zone rewriting is allowed a lack of interest
+ * by the client in DNSSEC or a lack of signatures.
+ */
+static isc_boolean_t
+rpz_ck_dnssec(ns_client_t *client, isc_result_t result,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ dns_fixedname_t fixed;
+ dns_name_t *found;
+ dns_rdataset_t trdataset;
+ dns_rdatatype_t type;
+
+ if (client->view->rpz_break_dnssec)
+ return (ISC_TRUE);
+ /*
+ * sigrdataset == NULL if and only !WANTDNSSEC(client)
+ */
+ if (sigrdataset == NULL)
+ return (ISC_TRUE);
+ if (dns_rdataset_isassociated(sigrdataset))
+ return (ISC_FALSE);
+
+ /*
+ * We are happy to rewrite nothing.
+ */
+ if (rdataset == NULL || !dns_rdataset_isassociated(rdataset))
+ return (ISC_TRUE);
+ /*
+ * Do not rewrite if there is any sign of signatures.
+ */
+ if (rdataset->type == dns_rdatatype_nsec ||
+ rdataset->type == dns_rdatatype_nsec3 ||
+ rdataset->type == dns_rdatatype_rrsig)
+ return (ISC_FALSE);
+
+ /*
+ * Look for a signature in a negative cache rdataset.
+ */
+ if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) == 0)
+ return (ISC_TRUE);
+ dns_fixedname_init(&fixed);
+ found = dns_fixedname_name(&fixed);
+ dns_rdataset_init(&trdataset);
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_ncache_current(rdataset, found, &trdataset);
+ type = trdataset.type;
+ dns_rdataset_disassociate(&trdataset);
+ if (type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3 ||
+ type == dns_rdatatype_rrsig)
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+/*
* Add a CNAME to the query response, including translating foo.evil.com and
* *.evil.com CNAME *.example.com
* to
@@ -4707,7 +4772,8 @@ rpz_add_cname(ns_client_t *client, dns_rpz_st_t *st,
* Turn off DNSSEC because the results of a
* response policy zone cannot verify.
*/
- client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC;
+ client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
+ DNS_MESSAGEFLAG_AD);
return (ISC_R_SUCCESS);
}
@@ -5117,10 +5183,12 @@ dns64_ttl(dns_db_t *db, dns_dbversion_t *version) {
isc_result_t result;
isc_uint32_t ttl = ISC_UINT32_MAX;
+ dns_rdataset_init(&rdataset);
+
result = dns_db_getoriginnode(db, &node);
if (result != ISC_R_SUCCESS)
goto cleanup;
- dns_rdataset_init(&rdataset);
+
result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
0, 0, &rdataset, NULL);
if (result != ISC_R_SUCCESS)
@@ -5502,9 +5570,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
CTRACE("query_find: resume");
if (!ISC_LIST_EMPTY(client->view->rpz_zones) &&
- RECURSIONOK(client) && !RECURSING(client) &&
- (!WANTDNSSEC(client) || sigrdataset == NULL ||
- !dns_rdataset_isassociated(sigrdataset)) &&
+ (RECURSIONOK(client) || !client->view->rpz_recursive_only) &&
+ rpz_ck_dnssec(client, result, rdataset, sigrdataset) &&
+ !RECURSING(client) &&
(client->query.rpz_st == NULL ||
(client->query.rpz_st->state & DNS_RPZ_REWRITTEN) == 0) &&
!dns_name_equal(client->query.qname, dns_rootname)) {
@@ -5578,10 +5646,22 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
break;
case DNS_RPZ_POLICY_RECORD:
result = rpz_st->m.result;
- if (type == dns_rdatatype_any &&
- result != DNS_R_CNAME &&
- dns_rdataset_isassociated(rdataset))
- dns_rdataset_disassociate(rdataset);
+ if (qtype == dns_rdatatype_any &&
+ result != DNS_R_CNAME) {
+ /*
+ * We will add all of the rdatasets of
+ * the node by iterating, setting the
+ * TTL then.
+ */
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ } else {
+ /*
+ * We will add this rdataset.
+ */
+ rdataset->ttl = ISC_MIN(rdataset->ttl,
+ rpz_st->m.ttl);
+ }
break;
case DNS_RPZ_POLICY_WILDCNAME:
result = dns_rdataset_first(rdataset);
@@ -5620,7 +5700,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
* Turn off DNSSEC because the results of a
* response policy zone cannot verify.
*/
- client->attributes &= ~NS_CLIENTATTR_WANTDNSSEC;
+ client->attributes &= ~(NS_CLIENTATTR_WANTDNSSEC |
+ DNS_MESSAGEFLAG_AD);
query_putrdataset(client, &sigrdataset);
is_zone = ISC_TRUE;
rpz_log_rewrite(client, "", rpz_st->m.policy,
@@ -6560,6 +6641,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
noqname = rdataset;
else
noqname = NULL;
+ rpz_st = client->query.rpz_st;
+ if (rpz_st != NULL)
+ rdataset->ttl = ISC_MIN(rdataset->ttl,
+ rpz_st->m.ttl);
query_addrrset(client,
fname != NULL ? &fname : &tname,
&rdataset, NULL,
@@ -6852,8 +6937,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
*/
rpz_st = client->query.rpz_st;
if (rpz_st != NULL && (rpz_st->state & DNS_RPZ_RECURSING) == 0) {
- rpz_clean(&rpz_st->m.zone, &rpz_st->m.db, &rpz_st->m.node,
- &rpz_st->m.rdataset);
+ rpz_match_clear(rpz_st);
rpz_st->state &= ~DNS_RPZ_DONE_QNAME;
}
if (rdataset != NULL)
OpenPOWER on IntegriCloud