aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon L. B. Nielsen <simon@FreeBSD.org>2010-01-06 21:45:30 +0000
committerSimon L. B. Nielsen <simon@FreeBSD.org>2010-01-06 21:45:30 +0000
commit1a707c0e67da562b02571106a36b14538caa6783 (patch)
tree5180e9822bf73978372743230c6a3624f07db14d
parent3bcabf8f98591dc2c38dcb7eaf591d9954d296db (diff)
downloadsrc-releng/6.3.tar.gz
src-releng/6.3.zip
Fix BIND named(8) cache poisoning with DNSSEC validation.releng/6.3
[SA-10:01] Fix ntpd mode 7 denial of service. [SA-10:02] Fix ZFS ZIL playback with insecure permissions. [SA-10:03] Various FreeBSD 8.0-RELEASE improvements. [EN-10:01] Security: FreeBSD-SA-10:01.bind Security: FreeBSD-SA-10:02.ntpd Security: FreeBSD-SA-10:03.zfs Errata: FreeBSD-EN-10:01.freebsd Approved by: so (simon)
Notes
Notes: svn path=/releng/6.3/; revision=201679
-rw-r--r--UPDATING6
-rw-r--r--contrib/bind9/bin/named/query.c58
-rw-r--r--contrib/bind9/lib/dns/include/dns/types.h41
-rw-r--r--contrib/bind9/lib/dns/masterdump.c3
-rw-r--r--contrib/bind9/lib/dns/rbtdb.c4
-rw-r--r--contrib/bind9/lib/dns/resolver.c31
-rw-r--r--contrib/bind9/lib/dns/validator.c10
-rw-r--r--contrib/ntp/ntpd/ntp_request.c11
-rw-r--r--sys/conf/newvers.sh2
9 files changed, 128 insertions, 38 deletions
diff --git a/UPDATING b/UPDATING
index 8509ec35c46f..fd0ed9561312 100644
--- a/UPDATING
+++ b/UPDATING
@@ -8,6 +8,12 @@ Items affecting the ports and packages system can be found in
/usr/ports/UPDATING. Please read that file before running
portupgrade.
+20100106: p15 FreeBSD-SA-10:01.bind, FreeBSD-SA-10:02.ntpd
+ Fix BIND named(8) cache poisoning with DNSSEC validation.
+ [SA-10:01]
+
+ Fix ntpd mode 7 denial of service. [SA-10:02]
+
20091203: p14 FreeBSD-SA-09:15.ssl, FreeBSD-SA-09:17.freebsd-update
Disable SSL renegotiation in order to protect against a serious
protocol flaw. [09:15]
diff --git a/contrib/bind9/bin/named/query.c b/contrib/bind9/bin/named/query.c
index c0a76a8bdd11..ef227d3b2c03 100644
--- a/contrib/bind9/bin/named/query.c
+++ b/contrib/bind9/bin/named/query.c
@@ -92,6 +92,8 @@
#define DNS_GETDB_NOLOG 0x02U
#define DNS_GETDB_PARTIAL 0x04U
+#define PENDINGOK(x) (((x) & DNS_DBFIND_PENDINGOK) != 0)
+
static void
query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
@@ -1698,14 +1700,14 @@ query_addbestns(ns_client_t *client) {
zsigrdataset = NULL;
}
- if ((client->query.dboptions & DNS_DBFIND_PENDINGOK) == 0 &&
- (rdataset->trust == dns_trust_pending ||
- (sigrdataset != NULL && sigrdataset->trust == dns_trust_pending)))
+ if ((DNS_TRUST_PENDING(rdataset->trust) ||
+ (sigrdataset != NULL && DNS_TRUST_PENDING(sigrdataset->trust))) &&
+ !PENDINGOK(client->query.dboptions))
goto cleanup;
- if (WANTDNSSEC(client) && SECURE(client) &&
- (rdataset->trust == dns_trust_glue ||
- (sigrdataset != NULL && sigrdataset->trust == dns_trust_glue)))
+ if ((DNS_TRUST_GLUE(rdataset->trust) ||
+ (sigrdataset != NULL && DNS_TRUST_GLUE(sigrdataset->trust))) &&
+ SECURE(client) && WANTDNSSEC(client))
goto cleanup;
query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
@@ -2364,6 +2366,8 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
unsigned int options;
isc_boolean_t empty_wild;
dns_rdataset_t *noqname;
+ dns_rdataset_t tmprdataset;
+ unsigned int dboptions;
CTRACE("query_find");
@@ -2563,9 +2567,47 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* Now look for an answer in the database.
*/
+ dboptions = client->query.dboptions;
+ if (sigrdataset == NULL && client->view->enablednssec) {
+ /*
+ * If the client doesn't want DNSSEC we still want to
+ * look for any data pending validation to save a remote
+ * lookup if possible.
+ */
+ dns_rdataset_init(&tmprdataset);
+ sigrdataset = &tmprdataset;
+ dboptions |= DNS_DBFIND_PENDINGOK;
+ }
+ refind:
result = dns_db_find(db, client->query.qname, version, type,
- client->query.dboptions, client->now,
- &node, fname, rdataset, sigrdataset);
+ dboptions, client->now, &node, fname,
+ rdataset, sigrdataset);
+ /*
+ * If we have found pending data try to validate it.
+ * If the data does not validate as secure and we can't
+ * use the unvalidated data requery the database with
+ * pending disabled to prevent infinite looping.
+ */
+ if (result != ISC_R_SUCCESS || !DNS_TRUST_PENDING(rdataset->trust))
+ goto validation_done;
+ if (rdataset->trust != dns_trust_pending_answer ||
+ !PENDINGOK(client->query.dboptions)) {
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (sigrdataset == &tmprdataset)
+ sigrdataset = NULL;
+ dns_db_detachnode(db, &node);
+ dboptions &= ~DNS_DBFIND_PENDINGOK;
+ goto refind;
+ }
+ validation_done:
+ if (sigrdataset == &tmprdataset) {
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ sigrdataset = NULL;
+ }
resume:
CTRACE("query_find: resume");
diff --git a/contrib/bind9/lib/dns/include/dns/types.h b/contrib/bind9/lib/dns/include/dns/types.h
index 27995deb279d..51aefcc2ab01 100644
--- a/contrib/bind9/lib/dns/include/dns/types.h
+++ b/contrib/bind9/lib/dns/include/dns/types.h
@@ -226,40 +226,51 @@ enum {
dns_trust_none = 0,
#define dns_trust_none ((dns_trust_t)dns_trust_none)
- /* Subject to DNSSEC validation but has not yet been validated */
- dns_trust_pending = 1,
-#define dns_trust_pending ((dns_trust_t)dns_trust_pending)
+ /*%
+ * Subject to DNSSEC validation but has not yet been validated
+ * dns_trust_pending_additional (from the additional section).
+ */
+ dns_trust_pending_additional = 1,
+#define dns_trust_pending_additional \
+ ((dns_trust_t)dns_trust_pending_additional)
+
+ dns_trust_pending_answer = 2,
+#define dns_trust_pending_answer ((dns_trust_t)dns_trust_pending_answer)
- /* Received in the additional section of a response. */
- dns_trust_additional = 2,
+ /*% Received in the additional section of a response. */
+ dns_trust_additional = 3,
#define dns_trust_additional ((dns_trust_t)dns_trust_additional)
- /* Received in a referral response. */
- dns_trust_glue = 3,
+ /* Received in a referral response. */
+ dns_trust_glue = 4,
#define dns_trust_glue ((dns_trust_t)dns_trust_glue)
- /* Answser from a non-authoritative server */
- dns_trust_answer = 4,
+ /* Answer from a non-authoritative server */
+ dns_trust_answer = 5,
#define dns_trust_answer ((dns_trust_t)dns_trust_answer)
/* Received in the authority section as part of an
authoritative response */
- dns_trust_authauthority = 5,
+ dns_trust_authauthority = 6,
#define dns_trust_authauthority ((dns_trust_t)dns_trust_authauthority)
- /* Answser from an authoritative server */
- dns_trust_authanswer = 6,
+ /* Answer from an authoritative server */
+ dns_trust_authanswer = 7,
#define dns_trust_authanswer ((dns_trust_t)dns_trust_authanswer)
- /* Successfully DNSSEC validated */
- dns_trust_secure = 7,
+ /* Successfully DNSSEC validated */
+ dns_trust_secure = 8,
#define dns_trust_secure ((dns_trust_t)dns_trust_secure)
/* This server is authoritative */
- dns_trust_ultimate = 8
+ dns_trust_ultimate = 9
#define dns_trust_ultimate ((dns_trust_t)dns_trust_ultimate)
};
+#define DNS_TRUST_PENDING(x) ((x) == dns_trust_pending_answer || \
+ (x) == dns_trust_pending_additional)
+#define DNS_TRUST_GLUE(x) ((x) == dns_trust_glue)
+
/*
* Name checking severites.
*/
diff --git a/contrib/bind9/lib/dns/masterdump.c b/contrib/bind9/lib/dns/masterdump.c
index 0f4716d583d9..bf938d8d8744 100644
--- a/contrib/bind9/lib/dns/masterdump.c
+++ b/contrib/bind9/lib/dns/masterdump.c
@@ -763,7 +763,8 @@ dump_order_compare(const void *a, const void *b) {
static const char *trustnames[] = {
"none",
- "pending",
+ "pending-additional",
+ "pending-answer",
"additional",
"glue",
"answer",
diff --git a/contrib/bind9/lib/dns/rbtdb.c b/contrib/bind9/lib/dns/rbtdb.c
index 8930d355fd0a..88de414d0153 100644
--- a/contrib/bind9/lib/dns/rbtdb.c
+++ b/contrib/bind9/lib/dns/rbtdb.c
@@ -2652,7 +2652,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
}
if (dname_header != NULL &&
- (dname_header->trust != dns_trust_pending ||
+ (!DNS_TRUST_PENDING(dname_header->trust) ||
(search->options & DNS_DBFIND_PENDINGOK) != 0)) {
/*
* We increment the reference count on node to ensure that
@@ -3113,7 +3113,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
if (found == NULL ||
(found->trust == dns_trust_glue &&
((options & DNS_DBFIND_GLUEOK) == 0)) ||
- (found->trust == dns_trust_pending &&
+ (DNS_TRUST_PENDING(found->trust) &&
((options & DNS_DBFIND_PENDINGOK) == 0))) {
/*
* If there is an NS rdataset at this node, then this is the
diff --git a/contrib/bind9/lib/dns/resolver.c b/contrib/bind9/lib/dns/resolver.c
index 099b80433f05..198e94d69f86 100644
--- a/contrib/bind9/lib/dns/resolver.c
+++ b/contrib/bind9/lib/dns/resolver.c
@@ -3603,6 +3603,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
* for it, unless it is glue.
*/
if (secure_domain && rdataset->trust != dns_trust_glue) {
+ dns_trust_t trust;
/*
* RRSIGs are validated as part of validating the
* type they cover.
@@ -3639,12 +3640,34 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
}
/*
+ * Reject out of bailiwick additional records
+ * without RRSIGs as they can't possibly validate
+ * as "secure" and as we will never never want to
+ * store these as "answers" after validation.
+ */
+ if (rdataset->trust == dns_trust_additional &&
+ sigrdataset == NULL && EXTERNAL(rdataset))
+ continue;
+
+ /*
+ * XXXMPA: If we store as "answer" after validating
+ * then we need to do bailiwick processing and
+ * also need to track whether RRsets are in or
+ * out of bailiwick. This will require a another
+ * pending trust level.
+ *
* Cache this rdataset/sigrdataset pair as
- * pending data.
+ * pending data. Track whether it was additional
+ * or not.
*/
- rdataset->trust = dns_trust_pending;
+ if (rdataset->trust == dns_trust_additional)
+ trust = dns_trust_pending_additional;
+ else
+ trust = dns_trust_pending_answer;
+
+ rdataset->trust = trust;
if (sigrdataset != NULL)
- sigrdataset->trust = dns_trust_pending;
+ sigrdataset->trust = trust;
if (!need_validation)
addedrdataset = ardataset;
else
@@ -3964,7 +3987,7 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
for (trdataset = ISC_LIST_HEAD(tname->list);
trdataset != NULL;
trdataset = ISC_LIST_NEXT(trdataset, link))
- trdataset->trust = dns_trust_pending;
+ trdataset->trust = dns_trust_pending_answer;
result = dns_message_nextname(fctx->rmessage,
DNS_SECTION_AUTHORITY);
}
diff --git a/contrib/bind9/lib/dns/validator.c b/contrib/bind9/lib/dns/validator.c
index 571ad791e7b6..4b40a8fa46be 100644
--- a/contrib/bind9/lib/dns/validator.c
+++ b/contrib/bind9/lib/dns/validator.c
@@ -235,7 +235,7 @@ auth_nonpending(dns_message_t *message) {
rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link))
{
- if (rdataset->trust == dns_trust_pending)
+ if (DNS_TRUST_PENDING(rdataset->trust))
rdataset->trust = dns_trust_authauthority;
}
}
@@ -1146,7 +1146,7 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
* We have an rrset for the given keyname.
*/
val->keyset = &val->frdataset;
- if (val->frdataset.trust == dns_trust_pending &&
+ if (DNS_TRUST_PENDING(val->frdataset.trust) &&
dns_rdataset_isassociated(&val->fsigrdataset))
{
/*
@@ -1161,7 +1161,7 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
if (result != ISC_R_SUCCESS)
return (result);
return (DNS_R_WAIT);
- } else if (val->frdataset.trust == dns_trust_pending) {
+ } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
/*
* Having a pending key with no signature means that
* something is broken.
@@ -1723,7 +1723,7 @@ validatezonekey(dns_validator_t *val) {
* We have DS records.
*/
val->dsset = &val->frdataset;
- if (val->frdataset.trust == dns_trust_pending &&
+ if (DNS_TRUST_PENDING(val->frdataset.trust) &&
dns_rdataset_isassociated(&val->fsigrdataset))
{
result = create_validator(val,
@@ -1736,7 +1736,7 @@ validatezonekey(dns_validator_t *val) {
if (result != ISC_R_SUCCESS)
return (result);
return (DNS_R_WAIT);
- } else if (val->frdataset.trust == dns_trust_pending) {
+ } else if (DNS_TRUST_PENDING(val->frdataset.trust)) {
/*
* There should never be an unsigned DS.
*/
diff --git a/contrib/ntp/ntpd/ntp_request.c b/contrib/ntp/ntpd/ntp_request.c
index eacba283f492..afa810894672 100644
--- a/contrib/ntp/ntpd/ntp_request.c
+++ b/contrib/ntp/ntpd/ntp_request.c
@@ -404,6 +404,7 @@ process_private(
int mod_okay
)
{
+ static u_long quiet_until;
struct req_pkt *inpkt;
struct req_pkt_tail *tailinpkt;
struct sockaddr_storage *srcadr;
@@ -439,8 +440,14 @@ process_private(
|| (++ec, INFO_MBZ(inpkt->mbz_itemsize) != 0)
|| (++ec, rbufp->recv_length < REQ_LEN_HDR)
) {
- msyslog(LOG_ERR, "process_private: INFO_ERR_FMT: test %d failed, pkt from %s", ec, stoa(srcadr));
- req_ack(srcadr, inter, inpkt, INFO_ERR_FMT);
+ NLOG(NLOG_SYSEVENT)
+ if (current_time >= quiet_until) {
+ msyslog(LOG_ERR,
+ "process_private: drop test %d"
+ " failed, pkt from %s",
+ ec, stoa(srcadr));
+ quiet_until = current_time + 60;
+ }
return;
}
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index a0bd0d756021..c244e5890597 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -32,7 +32,7 @@
TYPE="FreeBSD"
REVISION="6.3"
-BRANCH="RELEASE-p14"
+BRANCH="RELEASE-p15"
if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
BRANCH=${BRANCH_OVERRIDE}
fi