diff options
Diffstat (limited to 'contrib/bind9/lib/dns')
43 files changed, 1705 insertions, 413 deletions
diff --git a/contrib/bind9/lib/dns/api b/contrib/bind9/lib/dns/api index 4bcf883246ce..4fc7eca838cb 100644 --- a/contrib/bind9/lib/dns/api +++ b/contrib/bind9/lib/dns/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 53 +LIBINTERFACE = 56 LIBREVISION = 0 -LIBAGE = 0 +LIBAGE = 1 diff --git a/contrib/bind9/lib/dns/db.c b/contrib/bind9/lib/dns/db.c index a4c28641701f..02ea6b596ec8 100644 --- a/contrib/bind9/lib/dns/db.c +++ b/contrib/bind9/lib/dns/db.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db.c,v 1.88 2008/09/24 02:46:22 marka Exp $ */ +/* $Id: db.c,v 1.88.50.2 2009/06/23 00:19:34 tbox Exp $ */ /*! \file */ @@ -854,12 +854,14 @@ dns_db_unregister(dns_dbimplementation_t **dbimp) { RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); imp = *dbimp; + *dbimp = NULL; RWLOCK(&implock, isc_rwlocktype_write); ISC_LIST_UNLINK(implementations, imp, link); mctx = imp->mctx; isc_mem_put(mctx, imp, sizeof(dns_dbimplementation_t)); isc_mem_detach(&mctx); RWUNLOCK(&implock, isc_rwlocktype_write); + ENSURE(*dbimp == NULL); } isc_result_t diff --git a/contrib/bind9/lib/dns/dispatch.c b/contrib/bind9/lib/dns/dispatch.c index 9b4e9685f408..1d04961277be 100644 --- a/contrib/bind9/lib/dns/dispatch.c +++ b/contrib/bind9/lib/dns/dispatch.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dispatch.c,v 1.155.12.7 2009/04/28 21:39:45 jinmei Exp $ */ +/* $Id: dispatch.c,v 1.155.12.11 2009/12/02 23:26:28 marka Exp $ */ /*! \file */ @@ -746,13 +746,19 @@ new_portentry(dns_dispatch_t *disp, in_port_t port) { return (portentry); } +/*% + * The caller must not hold the qid->lock. + */ static void deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) { dispportentry_t *portentry = *portentryp; + dns_qid_t *qid; REQUIRE(disp->port_table != NULL); REQUIRE(portentry != NULL && portentry->refs > 0); + qid = DNS_QID(disp); + LOCK(&qid->lock); portentry->refs--; if (portentry->refs == 0) { ISC_LIST_UNLINK(disp->port_table[portentry->port % @@ -762,6 +768,7 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) { } *portentryp = NULL; + UNLOCK(&qid->lock); } /*% @@ -779,8 +786,9 @@ socket_search(dns_qid_t *qid, isc_sockaddr_t *dest, in_port_t port, dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]); while (dispsock != NULL) { - if (isc_sockaddr_equal(dest, &dispsock->host) && - dispsock->portentry->port == port) + if (dispsock->portentry != NULL && + dispsock->portentry->port == port && + isc_sockaddr_equal(dest, &dispsock->host)) return (dispsock); dispsock = ISC_LIST_NEXT(dispsock, blink); } @@ -2048,8 +2056,18 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr, /* Create or adjust buffer pool */ if (mgr->bpool != NULL) { - isc_mempool_setmaxalloc(mgr->bpool, maxbuffers); - mgr->maxbuffers = maxbuffers; + /* + * We only increase the maxbuffers to avoid accidental buffer + * shortage. Ideally we'd separate the manager-wide maximum + * from per-dispatch limits and respect the latter within the + * global limit. But at this moment that's deemed to be + * overkilling and isn't worth additional implementation + * complexity. + */ + if (maxbuffers > mgr->maxbuffers) { + isc_mempool_setmaxalloc(mgr->bpool, maxbuffers); + mgr->maxbuffers = maxbuffers; + } } else { result = isc_mempool_create(mgr->mctx, buffersize, &mgr->bpool); if (result != ISC_R_SUCCESS) { diff --git a/contrib/bind9/lib/dns/dnssec.c b/contrib/bind9/lib/dns/dnssec.c index baf3ec5b12ec..8ae29bceee92 100644 --- a/contrib/bind9/lib/dns/dnssec.c +++ b/contrib/bind9/lib/dns/dnssec.c @@ -16,7 +16,7 @@ */ /* - * $Id: dnssec.c,v 1.93.12.4 2009/06/08 23:47:00 tbox Exp $ + * $Id: dnssec.c,v 1.93.12.6 2009/06/22 23:47:18 tbox Exp $ */ /*! \file */ @@ -93,6 +93,7 @@ rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, isc_result_t ret; int i = 0, n; dns_rdata_t *data; + dns_rdataset_t rdataset; n = dns_rdataset_count(set); @@ -100,8 +101,11 @@ rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, if (data == NULL) return (ISC_R_NOMEMORY); - ret = dns_rdataset_first(set); + dns_rdataset_init(&rdataset); + dns_rdataset_clone(set, &rdataset); + ret = dns_rdataset_first(&rdataset); if (ret != ISC_R_SUCCESS) { + dns_rdataset_disassociate(&rdataset); isc_mem_put(mctx, data, n * sizeof(dns_rdata_t)); return (ret); } @@ -111,8 +115,8 @@ rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, */ do { dns_rdata_init(&data[i]); - dns_rdataset_current(set, &data[i++]); - } while (dns_rdataset_next(set) == ISC_R_SUCCESS); + dns_rdataset_current(&rdataset, &data[i++]); + } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS); /* * Sort the array. @@ -120,6 +124,7 @@ rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper); *rdata = data; *nrdata = n; + dns_rdataset_disassociate(&rdataset); return (ISC_R_SUCCESS); } @@ -890,3 +895,59 @@ failure: return (result); } + +/*% + * Does this key ('rdata') self sign the rrset ('rdataset')? + */ +isc_boolean_t +dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, + isc_boolean_t ignoretime, isc_mem_t *mctx) +{ + dst_key_t *dstkey = NULL; + dns_keytag_t keytag; + dns_rdata_dnskey_t key; + dns_rdata_rrsig_t sig; + dns_rdata_t sigrdata = DNS_RDATA_INIT; + isc_result_t result; + + INSIST(rdataset->type == dns_rdatatype_key || + rdataset->type == dns_rdatatype_dnskey); + if (rdataset->type == dns_rdatatype_key) { + INSIST(sigrdataset->type == dns_rdatatype_sig); + INSIST(sigrdataset->covers == dns_rdatatype_key); + } else { + INSIST(sigrdataset->type == dns_rdatatype_rrsig); + INSIST(sigrdataset->covers == dns_rdatatype_dnskey); + } + + result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey); + if (result != ISC_R_SUCCESS) + return (ISC_FALSE); + result = dns_rdata_tostruct(rdata, &key, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + keytag = dst_key_id(dstkey); + for (result = dns_rdataset_first(sigrdataset); + result == ISC_R_SUCCESS; + result = dns_rdataset_next(sigrdataset)) + { + dns_rdata_reset(&sigrdata); + dns_rdataset_current(sigrdataset, &sigrdata); + result = dns_rdata_tostruct(&sigrdata, &sig, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + if (sig.algorithm == key.algorithm && + sig.keyid == keytag) { + result = dns_dnssec_verify2(name, rdataset, dstkey, + ignoretime, mctx, + &sigrdata, NULL); + if (result == ISC_R_SUCCESS) { + dst_key_free(&dstkey); + return (ISC_TRUE); + } + } + } + dst_key_free(&dstkey); + return (ISC_FALSE); +} diff --git a/contrib/bind9/lib/dns/dst_api.c b/contrib/bind9/lib/dns/dst_api.c index 144c685e1089..bbb0a09cc3a3 100644 --- a/contrib/bind9/lib/dns/dst_api.c +++ b/contrib/bind9/lib/dns/dst_api.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -31,7 +31,7 @@ /* * Principal Author: Brian Wellington - * $Id: dst_api.c,v 1.16.12.3 2009/03/02 02:00:34 marka Exp $ + * $Id: dst_api.c,v 1.16.12.10 2010/01/15 19:38:53 each Exp $ */ /*! \file */ @@ -183,9 +183,16 @@ dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) { RETERR(dst__hmacsha512_init(&dst_t_func[DST_ALG_HMACSHA512])); #ifdef OPENSSL RETERR(dst__openssl_init()); - RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5])); - RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1])); - RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1])); + RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5], + DST_ALG_RSAMD5)); + RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1], + DST_ALG_RSASHA1)); + RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1], + DST_ALG_NSEC3RSASHA1)); + RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA256], + DST_ALG_RSASHA256)); + RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA512], + DST_ALG_RSASHA512)); #ifdef HAVE_OPENSSL_DSA RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_DSA])); RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA])); @@ -848,6 +855,8 @@ dst_key_sigsize(const dst_key_t *key, unsigned int *n) { case DST_ALG_RSAMD5: case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: + case DST_ALG_RSASHA256: + case DST_ALG_RSASHA512: *n = (key->key_size + 7) / 8; break; case DST_ALG_DSA: @@ -1017,6 +1026,9 @@ dst_key_read_public(const char *filename, int type, /* Read the next word: either TTL, class, or 'KEY' */ NEXTTOKEN(lex, opt, &token); + if (token.type != isc_tokentype_string) + BADTOKEN(); + /* If it's a TTL, read the next one */ result = dns_ttl_fromtext(&token.value.as_textregion, &ttl); if (result == ISC_R_SUCCESS) @@ -1072,6 +1084,8 @@ issymmetric(const dst_key_t *key) { case DST_ALG_RSAMD5: case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: + case DST_ALG_RSASHA256: + case DST_ALG_RSASHA512: case DST_ALG_DSA: case DST_ALG_NSEC3DSA: case DST_ALG_DH: @@ -1152,7 +1166,7 @@ write_public_key(const dst_key_t *key, int type, const char *directory) { fprintf(fp, " "); isc_buffer_usedregion(&classb, &r); - fwrite(r.base, 1, r.length, fp); + isc_util_fwrite(r.base, 1, r.length, fp); if ((type & DST_TYPE_KEY) != 0) fprintf(fp, " KEY "); @@ -1160,7 +1174,7 @@ write_public_key(const dst_key_t *key, int type, const char *directory) { fprintf(fp, " DNSKEY "); isc_buffer_usedregion(&textb, &r); - fwrite(r.base, 1, r.length, fp); + isc_util_fwrite(r.base, 1, r.length, fp); fputc('\n', fp); fflush(fp); @@ -1275,7 +1289,8 @@ algorithm_status(unsigned int alg) { if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 || alg == DST_ALG_DSA || alg == DST_ALG_DH || alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA || - alg == DST_ALG_NSEC3RSASHA1) + alg == DST_ALG_NSEC3RSASHA1 || + alg == DST_ALG_RSASHA256 || alg == DST_ALG_RSASHA512) return (DST_R_NOCRYPTO); #endif return (DST_R_UNSUPPORTEDALG); @@ -1297,6 +1312,8 @@ addsuffix(char *filename, unsigned int len, const char *ofilename, n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix); if (n < 0) + return (ISC_R_FAILURE); + if ((unsigned int)n >= len) return (ISC_R_NOSPACE); return (ISC_R_SUCCESS); } @@ -1304,6 +1321,9 @@ addsuffix(char *filename, unsigned int len, const char *ofilename, isc_result_t dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) { unsigned int flags = dst_entropy_flags; + + if (len == 0) + return (ISC_R_SUCCESS); if (pseudo) flags &= ~ISC_ENTROPY_GOODONLY; return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags)); @@ -1311,5 +1331,22 @@ dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) { unsigned int dst__entropy_status(void) { +#ifdef GSSAPI + unsigned int flags = dst_entropy_flags; + isc_result_t ret; + unsigned char buf[32]; + static isc_boolean_t first = ISC_TRUE; + + if (first) { + /* Someone believes RAND_status() initializes the PRNG */ + flags &= ~ISC_ENTROPY_GOODONLY; + ret = isc_entropy_getdata(dst_entropy_pool, buf, + sizeof(buf), NULL, flags); + INSIST(ret == ISC_R_SUCCESS); + isc_entropy_putdata(dst_entropy_pool, buf, + sizeof(buf), 2 * sizeof(buf)); + first = ISC_FALSE; + } +#endif return (isc_entropy_status(dst_entropy_pool)); } diff --git a/contrib/bind9/lib/dns/dst_internal.h b/contrib/bind9/lib/dns/dst_internal.h index 0c1a71c22560..16696487bc47 100644 --- a/contrib/bind9/lib/dns/dst_internal.h +++ b/contrib/bind9/lib/dns/dst_internal.h @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst_internal.h,v 1.11 2008/04/01 23:47:10 tbox Exp $ */ +/* $Id: dst_internal.h,v 1.11.120.2 2010/01/15 23:47:33 tbox Exp $ */ #ifndef DST_DST_INTERNAL_H #define DST_DST_INTERNAL_H 1 @@ -42,6 +42,7 @@ #include <isc/types.h> #include <isc/md5.h> #include <isc/sha1.h> +#include <isc/sha2.h> #include <isc/hmacmd5.h> #include <isc/hmacsha.h> @@ -97,7 +98,7 @@ struct dst_key { void *generic; gss_ctx_id_t gssctx; #ifdef OPENSSL -#if USE_EVP_RSA +#if !defined(USE_EVP) || !USE_EVP RSA *rsa; #endif DSA *dsa; @@ -124,6 +125,8 @@ struct dst_context { dst_gssapi_signverifyctx_t *gssctx; isc_md5_t *md5ctx; isc_sha1_t *sha1ctx; + isc_sha256_t *sha256ctx; + isc_sha512_t *sha512ctx; isc_hmacmd5_t *hmacmd5ctx; isc_hmacsha1_t *hmacsha1ctx; isc_hmacsha224_t *hmacsha224ctx; @@ -183,7 +186,8 @@ isc_result_t dst__hmacsha224_init(struct dst_func **funcp); isc_result_t dst__hmacsha256_init(struct dst_func **funcp); isc_result_t dst__hmacsha384_init(struct dst_func **funcp); isc_result_t dst__hmacsha512_init(struct dst_func **funcp); -isc_result_t dst__opensslrsa_init(struct dst_func **funcp); +isc_result_t dst__opensslrsa_init(struct dst_func **funcp, + unsigned char algorithm); isc_result_t dst__openssldsa_init(struct dst_func **funcp); isc_result_t dst__openssldh_init(struct dst_func **funcp); isc_result_t dst__gssapi_init(struct dst_func **funcp); diff --git a/contrib/bind9/lib/dns/dst_parse.c b/contrib/bind9/lib/dns/dst_parse.c index 2da72ae6415a..e8ab34ff7573 100644 --- a/contrib/bind9/lib/dns/dst_parse.c +++ b/contrib/bind9/lib/dns/dst_parse.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -31,7 +31,7 @@ /*% * Principal Author: Brian Wellington - * $Id: dst_parse.c,v 1.14.120.2 2009/03/02 23:47:11 tbox Exp $ + * $Id: dst_parse.c,v 1.14.120.6 2010/01/15 19:38:53 each Exp $ */ #include <config.h> @@ -480,6 +480,18 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, case DST_ALG_RSASHA1: fprintf(fp, "(RSASHA1)\n"); break; + case DST_ALG_NSEC3DSA: + fprintf(fp, "(NSEC3DSA)\n"); + break; + case DST_ALG_NSEC3RSASHA1: + fprintf(fp, "(NSEC3RSASHA1)\n"); + break; + case DST_ALG_RSASHA256: + fprintf(fp, "(RSASHA256)\n"); + break; + case DST_ALG_RSASHA512: + fprintf(fp, "(RSASHA512)\n"); + break; case DST_ALG_HMACMD5: fprintf(fp, "(HMAC_MD5)\n"); break; @@ -521,7 +533,7 @@ dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv, isc_buffer_usedregion(&b, &r); fprintf(fp, "%s ", s); - fwrite(r.base, 1, r.length, fp); + isc_util_fwrite(r.base, 1, r.length, fp); fprintf(fp, "\n"); } diff --git a/contrib/bind9/lib/dns/include/dns/db.h b/contrib/bind9/lib/dns/include/dns/db.h index c75c774143f0..9a1126d7084f 100644 --- a/contrib/bind9/lib/dns/include/dns/db.h +++ b/contrib/bind9/lib/dns/include/dns/db.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db.h,v 1.93.50.3.12.1 2009/12/31 21:44:37 each Exp $ */ +/* $Id: db.h,v 1.93.50.5 2009/11/25 23:48:42 tbox Exp $ */ #ifndef DNS_DB_H #define DNS_DB_H 1 @@ -695,6 +695,10 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * For cache databases, glue is any rdataset with a trust of * dns_trust_glue. * + * \li If 'options' does not have #DNS_DBFIND_ADDITIONALOK set, then no + * additional records will be returned. Only caches can have + * rdataset with trust dns_trust_additional. + * * \li If 'options' does not have #DNS_DBFIND_PENDINGOK set, then no * pending data will be returned. This option is only meaningful for * cache databases. diff --git a/contrib/bind9/lib/dns/include/dns/dnssec.h b/contrib/bind9/lib/dns/include/dns/dnssec.h index c5206be63bb3..14462664a1eb 100644 --- a/contrib/bind9/lib/dns/include/dns/dnssec.h +++ b/contrib/bind9/lib/dns/include/dns/dnssec.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec.h,v 1.32.332.4 2009/06/08 23:47:00 tbox Exp $ */ +/* $Id: dnssec.h,v 1.32.332.6 2009/06/22 23:47:18 tbox Exp $ */ #ifndef DNS_DNSSEC_H #define DNS_DNSSEC_H 1 @@ -178,6 +178,12 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, *\li DST_R_* */ +isc_boolean_t +dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name, + dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, + isc_boolean_t ignoretime, isc_mem_t *mctx); + + ISC_LANG_ENDDECLS #endif /* DNS_DNSSEC_H */ diff --git a/contrib/bind9/lib/dns/include/dns/journal.h b/contrib/bind9/lib/dns/include/dns/journal.h index 3917d8db9a0a..a1e16e448785 100644 --- a/contrib/bind9/lib/dns/include/dns/journal.h +++ b/contrib/bind9/lib/dns/include/dns/journal.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: journal.h,v 1.33.120.2 2009/01/18 23:47:41 tbox Exp $ */ +/* $Id: journal.h,v 1.33.120.4 2009/11/04 23:47:25 tbox Exp $ */ #ifndef DNS_JOURNAL_H #define DNS_JOURNAL_H 1 @@ -232,12 +232,19 @@ dns_journal_current_rr(dns_journal_t *j, dns_name_t **name, isc_uint32_t *ttl, isc_result_t dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, unsigned int options, const char *filename); + +isc_result_t +dns_journal_rollforward2(isc_mem_t *mctx, dns_db_t *db, unsigned int options, + isc_uint32_t resign, const char *filename); /*%< * Roll forward (play back) the journal file "filename" into the * database "db". This should be called when the server starts - * after a shutdown or crash. + * after a shutdown or crash. 'resign' is how many seconds before + * a RRSIG is due to expire it should be scheduled to be regenerated. * * Requires: + *\li dns_journal_rollforward() requires that DNS_JOURNALOPT_RESIGN + * is not set. *\li 'mctx' is a valid memory context. *\li 'db' is a valid database which does not have a version * open for writing. diff --git a/contrib/bind9/lib/dns/include/dns/keyvalues.h b/contrib/bind9/lib/dns/include/dns/keyvalues.h index 7f509e6ef13a..f4a50fa606f1 100644 --- a/contrib/bind9/lib/dns/include/dns/keyvalues.h +++ b/contrib/bind9/lib/dns/include/dns/keyvalues.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: keyvalues.h,v 1.23.48.2 2009/06/04 02:56:14 tbox Exp $ */ +/* $Id: keyvalues.h,v 1.23.48.4 2010/01/15 23:47:33 tbox Exp $ */ #ifndef DNS_KEYVALUES_H #define DNS_KEYVALUES_H 1 @@ -69,6 +69,8 @@ #define DNS_KEYALG_ECC 4 #define DNS_KEYALG_RSASHA1 5 #define DNS_KEYALG_NSEC3RSASHA1 7 +#define DNS_KEYALG_RSASHA256 8 +#define DNS_KEYALG_RSASHA512 10 #define DNS_KEYALG_INDIRECT 252 #define DNS_KEYALG_PRIVATEDNS 253 #define DNS_KEYALG_PRIVATEOID 254 /*%< Key begins with OID giving alg */ diff --git a/contrib/bind9/lib/dns/include/dns/name.h b/contrib/bind9/lib/dns/include/dns/name.h index 0149301dcfbd..dc6e525c1c84 100644 --- a/contrib/bind9/lib/dns/include/dns/name.h +++ b/contrib/bind9/lib/dns/include/dns/name.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: name.h,v 1.126.332.2 2009/01/18 23:47:41 tbox Exp $ */ +/* $Id: name.h,v 1.126.332.3 2009/12/24 00:34:59 each Exp $ */ #ifndef DNS_NAME_H #define DNS_NAME_H 1 @@ -99,12 +99,6 @@ ISC_LANG_BEGINDECLS *****/ /*** - *** Compression pointer chaining limit - ***/ - -#define DNS_POINTER_MAXHOPS 16 - -/*** *** Types ***/ diff --git a/contrib/bind9/lib/dns/include/dns/ncache.h b/contrib/bind9/lib/dns/include/dns/ncache.h index d61684df88c4..0677211719ec 100644 --- a/contrib/bind9/lib/dns/include/dns/ncache.h +++ b/contrib/bind9/lib/dns/include/dns/ncache.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ncache.h,v 1.25.142.1 2009/12/31 20:29:21 each Exp $ */ +/* $Id: ncache.h,v 1.25.48.2 2009/12/30 23:47:31 tbox Exp $ */ #ifndef DNS_NCACHE_H #define DNS_NCACHE_H 1 diff --git a/contrib/bind9/lib/dns/include/dns/nsec3.h b/contrib/bind9/lib/dns/include/dns/nsec3.h index 2d6a8dde8a72..6243fdb10f2b 100644 --- a/contrib/bind9/lib/dns/include/dns/nsec3.h +++ b/contrib/bind9/lib/dns/include/dns/nsec3.h @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsec3.h,v 1.5.48.2 2009/01/18 23:47:41 tbox Exp $ */ +/* $Id: nsec3.h,v 1.5.48.3 2009/10/06 21:20:18 each Exp $ */ #ifndef DNS_NSEC3_H #define DNS_NSEC3_H 1 @@ -28,6 +28,8 @@ #include <dns/rdatastruct.h> #include <dns/types.h> +#define DNS_NSEC3_SALTSIZE 255 + /* * hash = 1, flags =1, iterations = 2, salt length = 1, salt = 255 (max) * hash length = 1, hash = 255 (max), bitmap = 8192 + 512 (max) diff --git a/contrib/bind9/lib/dns/include/dns/rbt.h b/contrib/bind9/lib/dns/include/dns/rbt.h index 6eea787af888..26155965c838 100644 --- a/contrib/bind9/lib/dns/include/dns/rbt.h +++ b/contrib/bind9/lib/dns/include/dns/rbt.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbt.h,v 1.71.48.2 2009/01/18 23:47:41 tbox Exp $ */ +/* $Id: rbt.h,v 1.71.48.3 2009/10/20 05:06:04 marka Exp $ */ #ifndef DNS_RBT_H #define DNS_RBT_H 1 @@ -105,11 +105,11 @@ struct dns_rbtnode { unsigned int is_root : 1; /*%< range is 0..1 */ unsigned int color : 1; /*%< range is 0..1 */ unsigned int find_callback : 1; /*%< range is 0..1 */ - unsigned int attributes : 3; /*%< range is 0..2 */ + unsigned int attributes : 4; /*%< range is 0..2 */ unsigned int nsec3 : 1; /*%< range is 0..1 */ unsigned int namelen : 8; /*%< range is 1..255 */ unsigned int offsetlen : 8; /*%< range is 1..128 */ - unsigned int padbytes : 9; /*%< range is 0..380 */ + unsigned int oldnamelen : 8; /*%< range is 1..255 */ /*@}*/ #ifdef DNS_RBT_USEHASH diff --git a/contrib/bind9/lib/dns/include/dns/rdataset.h b/contrib/bind9/lib/dns/include/dns/rdataset.h index baff146fcade..d435ed009d4f 100644 --- a/contrib/bind9/lib/dns/include/dns/rdataset.h +++ b/contrib/bind9/lib/dns/include/dns/rdataset.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataset.h,v 1.65.50.2 2009/01/18 23:47:41 tbox Exp $ */ +/* $Id: rdataset.h,v 1.65.50.2.22.2 2010/02/25 10:57:12 tbox Exp $ */ #ifndef DNS_RDATASET_H #define DNS_RDATASET_H 1 @@ -110,6 +110,9 @@ typedef struct dns_rdatasetmethods { dns_rdataset_t *rdataset, dns_rdatasetadditional_t type, dns_rdatatype_t qtype); + void (*settrust)(dns_rdataset_t *rdataset, + dns_trust_t trust); + void (*expire)(dns_rdataset_t *rdataset); } dns_rdatasetmethods_t; #define DNS_RDATASET_MAGIC ISC_MAGIC('D','N','S','R') @@ -634,6 +637,19 @@ dns_rdataset_putadditional(dns_acache_t *acache, * information for 'rdataset.' */ +void +dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust); +/*%< + * Set the trust of the 'rdataset' to trust in any in the backing database. + * The local trust level of 'rdataset' is also set. + */ + +void +dns_rdataset_expire(dns_rdataset_t *rdataset); +/*%< + * Mark the rdataset to be expired in the backing database. + */ + ISC_LANG_ENDDECLS #endif /* DNS_RDATASET_H */ diff --git a/contrib/bind9/lib/dns/include/dns/resolver.h b/contrib/bind9/lib/dns/include/dns/resolver.h index fa837c1de4d7..8c7ad7254b0a 100644 --- a/contrib/bind9/lib/dns/include/dns/resolver.h +++ b/contrib/bind9/lib/dns/include/dns/resolver.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.h,v 1.60.56.3 2009/01/29 22:40:35 jinmei Exp $ */ +/* $Id: resolver.h,v 1.60.56.3.22.2 2010/02/25 10:57:12 tbox Exp $ */ #ifndef DNS_RESOLVER_H #define DNS_RESOLVER_H 1 @@ -508,6 +508,48 @@ dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state); unsigned int dns_resolver_getoptions(dns_resolver_t *resolver); +void +dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name, + dns_rdatatype_t type, isc_time_t *expire); +/*%< + * Add a entry to the bad cache for <name,type> that will expire at 'expire'. + * + * Requires: + * \li resolver to be valid. + * \li name to be valid. + */ + +isc_boolean_t +dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name, + dns_rdatatype_t type, isc_time_t *now); +/*%< + * Check to see if there is a unexpired entry in the bad cache for + * <name,type>. + * + * Requires: + * \li resolver to be valid. + * \li name to be valid. + */ + +void +dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name); +/*%< + * Flush the bad cache of all entries at 'name' if 'name' is non NULL. + * Flush the entire bad cache if 'name' is NULL. + * + * Requires: + * \li resolver to be valid. + */ + +void +dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp); +/*% + * Print out the contents of the bad cache to 'fp'. + * + * Requires: + * \li resolver to be valid. + */ + ISC_LANG_ENDDECLS #endif /* DNS_RESOLVER_H */ diff --git a/contrib/bind9/lib/dns/include/dns/result.h b/contrib/bind9/lib/dns/include/dns/result.h index ed29bcd5d3f6..a1e7f535dee8 100644 --- a/contrib/bind9/lib/dns/include/dns/result.h +++ b/contrib/bind9/lib/dns/include/dns/result.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.h,v 1.116 2008/09/25 04:02:39 tbox Exp $ */ +/* $Id: result.h,v 1.116.226.2 2010/02/25 10:57:12 tbox Exp $ */ #ifndef DNS_RESULT_H #define DNS_RESULT_H 1 @@ -148,8 +148,10 @@ #define DNS_R_MXISADDRESS (ISC_RESULTCLASS_DNS + 102) #define DNS_R_DUPLICATE (ISC_RESULTCLASS_DNS + 103) #define DNS_R_INVALIDNSEC3 (ISC_RESULTCLASS_DNS + 104) +#define DNS_R_NOTMASTER (ISC_RESULTCLASS_DNS + 105) +#define DNS_R_BROKENCHAIN (ISC_RESULTCLASS_DNS + 106) -#define DNS_R_NRESULTS 105 /*%< Number of results */ +#define DNS_R_NRESULTS 107 /*%< Number of results */ /* * DNS wire format rcodes. diff --git a/contrib/bind9/lib/dns/include/dns/types.h b/contrib/bind9/lib/dns/include/dns/types.h index 525dd8d48921..10ce229ac970 100644 --- a/contrib/bind9/lib/dns/include/dns/types.h +++ b/contrib/bind9/lib/dns/include/dns/types.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: types.h,v 1.130.50.3.12.2 2009/12/31 20:29:21 each Exp $ */ +/* $Id: types.h,v 1.130.50.5 2009/12/30 08:34:30 jinmei Exp $ */ #ifndef DNS_TYPES_H #define DNS_TYPES_H 1 diff --git a/contrib/bind9/lib/dns/include/dns/validator.h b/contrib/bind9/lib/dns/include/dns/validator.h index 2555214b14cf..1da4e0c4c390 100644 --- a/contrib/bind9/lib/dns/include/dns/validator.h +++ b/contrib/bind9/lib/dns/include/dns/validator.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.h,v 1.41.48.3 2009/01/18 23:25:17 marka Exp $ */ +/* $Id: validator.h,v 1.41.48.3.22.2 2010/02/25 10:57:12 tbox Exp $ */ #ifndef DNS_VALIDATOR_H #define DNS_VALIDATOR_H 1 @@ -159,6 +159,8 @@ struct dns_validator { isc_boolean_t mustbesecure; unsigned int dlvlabels; unsigned int depth; + unsigned int authcount; + unsigned int authfail; }; /*% diff --git a/contrib/bind9/lib/dns/include/dns/zone.h b/contrib/bind9/lib/dns/include/dns/zone.h index e2859ae5bbb5..746b43cdd6f6 100644 --- a/contrib/bind9/lib/dns/include/dns/zone.h +++ b/contrib/bind9/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.160.50.4 2009/01/29 22:40:35 jinmei Exp $ */ +/* $Id: zone.h,v 1.160.50.6 2009/10/05 21:57:00 each Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -149,13 +149,24 @@ dns_zone_getclass(dns_zone_t *zone); *\li 'zone' to be a valid zone. */ +isc_result_t +dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp); + isc_uint32_t dns_zone_getserial(dns_zone_t *zone); /*%< - * Returns the current serial number of the zone. + * Returns the current serial number of the zone. On success, the SOA + * serial of the zone will be copied into '*serialp'. + * dns_zone_getserial() cannot catch failure cases and is deprecated by + * dns_zone_getserial2(). * * Requires: *\li 'zone' to be a valid zone. + *\li 'serialp' to be non NULL + * + * Returns: + *\li #ISC_R_SUCCESS + *\li #DNS_R_NOTLOADED zone DB is not loaded */ void @@ -256,6 +267,9 @@ dns_zone_load(dns_zone_t *zone); isc_result_t dns_zone_loadnew(dns_zone_t *zone); + +isc_result_t +dns_zone_loadandthaw(dns_zone_t *zone); /*%< * Cause the database to be loaded from its backing store. * Confirm that the minimum requirements for the zone type are @@ -264,6 +278,8 @@ dns_zone_loadnew(dns_zone_t *zone); * dns_zone_loadnew() only loads zones that are not yet loaded. * dns_zone_load() also loads zones that are already loaded and * and whose master file has changed since the last load. + * dns_zone_loadandthaw() is similar to dns_zone_load() but will + * also re-enable DNS UPDATEs when the load completes. * * Require: *\li 'zone' to be a valid zone. diff --git a/contrib/bind9/lib/dns/include/dst/dst.h b/contrib/bind9/lib/dns/include/dst/dst.h index 702ad719d21b..de262bdafb1a 100644 --- a/contrib/bind9/lib/dns/include/dst/dst.h +++ b/contrib/bind9/lib/dns/include/dst/dst.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dst.h,v 1.12 2008/09/24 02:46:23 marka Exp $ */ +/* $Id: dst.h,v 1.12.50.2 2010/01/15 23:47:34 tbox Exp $ */ #ifndef DST_DST_H #define DST_DST_H 1 @@ -53,6 +53,8 @@ typedef struct dst_context dst_context_t; #define DST_ALG_RSASHA1 5 #define DST_ALG_NSEC3DSA 6 #define DST_ALG_NSEC3RSASHA1 7 +#define DST_ALG_RSASHA256 8 +#define DST_ALG_RSASHA512 10 #define DST_ALG_HMACMD5 157 #define DST_ALG_GSSAPI 160 #define DST_ALG_HMACSHA1 161 /* XXXMPA */ diff --git a/contrib/bind9/lib/dns/journal.c b/contrib/bind9/lib/dns/journal.c index 8c21f1ece34b..638e64755b54 100644 --- a/contrib/bind9/lib/dns/journal.c +++ b/contrib/bind9/lib/dns/journal.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: journal.c,v 1.103.48.2 2009/01/18 23:47:37 tbox Exp $ */ +/* $Id: journal.c,v 1.103.48.6 2009/11/04 23:47:25 tbox Exp $ */ #include <config.h> @@ -1218,7 +1218,9 @@ dns_journal_destroy(dns_journal_t **journalp) { /* XXX Share code with incoming IXFR? */ static isc_result_t -roll_forward(dns_journal_t *j, dns_db_t *db, unsigned int options) { +roll_forward(dns_journal_t *j, dns_db_t *db, unsigned int options, + isc_uint32_t resign) +{ isc_buffer_t source; /* Transaction data from disk */ isc_buffer_t target; /* Ditto after _fromwire check */ isc_uint32_t db_serial; /* Database SOA serial */ @@ -1235,6 +1237,7 @@ roll_forward(dns_journal_t *j, dns_db_t *db, unsigned int options) { REQUIRE(DNS_DB_VALID(db)); dns_diff_init(j->mctx, &diff); + diff.resign = resign; /* * Set up empty initial buffers for unchecked and checked @@ -1353,6 +1356,14 @@ isc_result_t dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, unsigned int options, const char *filename) { + REQUIRE((options & DNS_JOURNALOPT_RESIGN) == 0); + return (dns_journal_rollforward2(mctx, db, options, 0, filename)); +} + +isc_result_t +dns_journal_rollforward2(isc_mem_t *mctx, dns_db_t *db, unsigned int options, + isc_uint32_t resign, const char *filename) +{ dns_journal_t *j; isc_result_t result; @@ -1371,7 +1382,7 @@ dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, if (JOURNAL_EMPTY(&j->header)) result = DNS_R_UPTODATE; else - result = roll_forward(j, db, options); + result = roll_forward(j, db, options, resign); dns_journal_destroy(&j); @@ -1850,18 +1861,11 @@ dns_diff_subtract(dns_diff_t diff[2], dns_diff_t *r) { return (result); } -/* - * Compare the databases 'dba' and 'dbb' and generate a journal - * entry containing the changes to make 'dba' from 'dbb' (note - * the order). This journal entry will consist of a single, - * possibly very large transaction. - */ - -isc_result_t -dns_db_diff(isc_mem_t *mctx, - dns_db_t *dba, dns_dbversion_t *dbvera, - dns_db_t *dbb, dns_dbversion_t *dbverb, - const char *journal_filename) +static isc_result_t +diff_namespace(isc_mem_t *mctx, + dns_db_t *dba, dns_dbversion_t *dbvera, + dns_db_t *dbb, dns_dbversion_t *dbverb, + unsigned int options, dns_diff_t *resultdiff) { dns_db_t *db[2]; dns_dbversion_t *ver[2]; @@ -1869,30 +1873,24 @@ dns_db_diff(isc_mem_t *mctx, isc_boolean_t have[2] = { ISC_FALSE, ISC_FALSE }; dns_fixedname_t fixname[2]; isc_result_t result, itresult[2]; - dns_diff_t diff[2], resultdiff; + dns_diff_t diff[2]; int i, t; - dns_journal_t *journal = NULL; db[0] = dba, db[1] = dbb; ver[0] = dbvera, ver[1] = dbverb; dns_diff_init(mctx, &diff[0]); dns_diff_init(mctx, &diff[1]); - dns_diff_init(mctx, &resultdiff); dns_fixedname_init(&fixname[0]); dns_fixedname_init(&fixname[1]); - result = dns_journal_open(mctx, journal_filename, ISC_TRUE, &journal); + result = dns_db_createiterator(db[0], options, &dbit[0]); if (result != ISC_R_SUCCESS) return (result); - - result = dns_db_createiterator(db[0], 0, &dbit[0]); - if (result != ISC_R_SUCCESS) - goto cleanup_journal; - result = dns_db_createiterator(db[1], 0, &dbit[1]); + result = dns_db_createiterator(db[1], options, &dbit[1]); if (result != ISC_R_SUCCESS) - goto cleanup_interator0; + goto cleanup_iterator; itresult[0] = dns_dbiterator_first(dbit[0]); itresult[1] = dns_dbiterator_first(dbit[1]); @@ -1919,7 +1917,7 @@ dns_db_diff(isc_mem_t *mctx, for (i = 0; i < 2; i++) { if (! have[!i]) { - ISC_LIST_APPENDLIST(resultdiff.tuples, + ISC_LIST_APPENDLIST(resultdiff->tuples, diff[i].tuples, link); INSIST(ISC_LIST_EMPTY(diff[i].tuples)); have[i] = ISC_FALSE; @@ -1930,21 +1928,21 @@ dns_db_diff(isc_mem_t *mctx, t = dns_name_compare(dns_fixedname_name(&fixname[0]), dns_fixedname_name(&fixname[1])); if (t < 0) { - ISC_LIST_APPENDLIST(resultdiff.tuples, + ISC_LIST_APPENDLIST(resultdiff->tuples, diff[0].tuples, link); INSIST(ISC_LIST_EMPTY(diff[0].tuples)); have[0] = ISC_FALSE; continue; } if (t > 0) { - ISC_LIST_APPENDLIST(resultdiff.tuples, + ISC_LIST_APPENDLIST(resultdiff->tuples, diff[1].tuples, link); INSIST(ISC_LIST_EMPTY(diff[1].tuples)); have[1] = ISC_FALSE; continue; } INSIST(t == 0); - CHECK(dns_diff_subtract(diff, &resultdiff)); + CHECK(dns_diff_subtract(diff, resultdiff)); INSIST(ISC_LIST_EMPTY(diff[0].tuples)); INSIST(ISC_LIST_EMPTY(diff[1].tuples)); have[0] = have[1] = ISC_FALSE; @@ -1955,20 +1953,49 @@ dns_db_diff(isc_mem_t *mctx, if (itresult[1] != ISC_R_NOMORE) FAIL(itresult[1]); + INSIST(ISC_LIST_EMPTY(diff[0].tuples)); + INSIST(ISC_LIST_EMPTY(diff[1].tuples)); + + failure: + dns_dbiterator_destroy(&dbit[1]); + cleanup_iterator: + dns_dbiterator_destroy(&dbit[0]); + return (result); +} + +/* + * Compare the databases 'dba' and 'dbb' and generate a journal + * entry containing the changes to make 'dba' from 'dbb' (note + * the order). This journal entry will consist of a single, + * possibly very large transaction. + */ +isc_result_t +dns_db_diff(isc_mem_t *mctx, + dns_db_t *dba, dns_dbversion_t *dbvera, + dns_db_t *dbb, dns_dbversion_t *dbverb, + const char *journal_filename) +{ + isc_result_t result; + dns_journal_t *journal = NULL; + dns_diff_t resultdiff; + + result = dns_journal_open(mctx, journal_filename, ISC_TRUE, &journal); + if (result != ISC_R_SUCCESS) + return (result); + + dns_diff_init(mctx, &resultdiff); + + CHECK(diff_namespace(mctx, dba, dbvera, dbb, dbverb, + DNS_DB_NONSEC3, &resultdiff)); + CHECK(diff_namespace(mctx, dba, dbvera, dbb, dbverb, + DNS_DB_NSEC3ONLY, &resultdiff)); if (ISC_LIST_EMPTY(resultdiff.tuples)) { isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no changes"); } else { CHECK(dns_journal_write_transaction(journal, &resultdiff)); } - INSIST(ISC_LIST_EMPTY(diff[0].tuples)); - INSIST(ISC_LIST_EMPTY(diff[1].tuples)); - failure: dns_diff_clear(&resultdiff); - dns_dbiterator_destroy(&dbit[1]); - cleanup_interator0: - dns_dbiterator_destroy(&dbit[0]); - cleanup_journal: dns_journal_destroy(&journal); return (result); } diff --git a/contrib/bind9/lib/dns/masterdump.c b/contrib/bind9/lib/dns/masterdump.c index 1dbb1e615e8b..314112ce5f1b 100644 --- a/contrib/bind9/lib/dns/masterdump.c +++ b/contrib/bind9/lib/dns/masterdump.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: masterdump.c,v 1.94.50.2.12.1 2009/11/18 23:58:04 marka Exp $ */ +/* $Id: masterdump.c,v 1.94.50.3 2009/11/18 00:15:37 marka Exp $ */ /*! \file */ diff --git a/contrib/bind9/lib/dns/message.c b/contrib/bind9/lib/dns/message.c index b541635abf03..2e34120f3b9b 100644 --- a/contrib/bind9/lib/dns/message.c +++ b/contrib/bind9/lib/dns/message.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: message.c,v 1.245.50.2 2009/01/18 23:47:40 tbox Exp $ */ +/* $Id: message.c,v 1.245.50.3 2009/11/24 03:25:53 marka Exp $ */ /*! \file */ @@ -1888,6 +1888,8 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, msg->counts[sectionid] += total; return (result); } + if (result == ISC_R_NOSPACE) + msg->flags |= DNS_MESSAGEFLAG_TC; if (result != ISC_R_SUCCESS) { INSIST(st.used < 65536); dns_compress_rollback(msg->cctx, diff --git a/contrib/bind9/lib/dns/ncache.c b/contrib/bind9/lib/dns/ncache.c index af0450b525dc..733d138dda24 100644 --- a/contrib/bind9/lib/dns/ncache.c +++ b/contrib/bind9/lib/dns/ncache.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ncache.c,v 1.43 2008/09/25 04:02:38 tbox Exp $ */ +/* $Id: ncache.c,v 1.43.334.2 2010/02/25 10:57:11 tbox Exp $ */ /*! \file */ @@ -519,6 +519,8 @@ static dns_rdatasetmethods_t rdataset_methods = { NULL, NULL, NULL, + NULL, + NULL, NULL }; diff --git a/contrib/bind9/lib/dns/nsec3.c b/contrib/bind9/lib/dns/nsec3.c index f9b8cad21a70..ea6546d9e60f 100644 --- a/contrib/bind9/lib/dns/nsec3.c +++ b/contrib/bind9/lib/dns/nsec3.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: nsec3.c,v 1.6.12.2 2009/06/04 02:56:14 tbox Exp $ */ +/* $Id: nsec3.c,v 1.6.12.4 2009/11/03 23:47:46 tbox Exp $ */ #include <config.h> @@ -87,6 +87,8 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, unsigned int i, window; int octet; isc_boolean_t found; + isc_boolean_t found_ns; + isc_boolean_t need_rrsig; unsigned char *nsec_bits, *bm; unsigned int max_type; @@ -140,7 +142,7 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, result = dns_db_allrdatasets(db, node, version, 0, &rdsiter); if (result != ISC_R_SUCCESS) return (result); - found = ISC_FALSE; + found = found_ns = need_rrsig = ISC_FALSE; for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; result = dns_rdatasetiter_next(rdsiter)) @@ -152,13 +154,26 @@ dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version, if (rdataset.type > max_type) max_type = rdataset.type; set_bit(bm, rdataset.type, 1); - /* Don't set RRSIG for insecure delegation. */ - if (rdataset.type != dns_rdatatype_ns) + /* + * Work out if we need to set the RRSIG bit for + * this node. We set the RRSIG bit if either of + * the following conditions are met: + * 1) We have a SOA or DS then we need to set + * the RRSIG bit as both always will be signed. + * 2) We set the RRSIG bit if we don't have + * a NS record but do have other data. + */ + if (rdataset.type == dns_rdatatype_soa || + rdataset.type == dns_rdatatype_ds) + need_rrsig = ISC_TRUE; + else if (rdataset.type == dns_rdatatype_ns) + found_ns = ISC_TRUE; + else found = ISC_TRUE; } dns_rdataset_disassociate(&rdataset); } - if (found) { + if ((found && !found_ns) || need_rrsig) { if (dns_rdatatype_rrsig > max_type) max_type = dns_rdatatype_rrsig; set_bit(bm, dns_rdatatype_rrsig, 1); diff --git a/contrib/bind9/lib/dns/opensslrsa_link.c b/contrib/bind9/lib/dns/opensslrsa_link.c index d557c43db258..95095d1186b7 100644 --- a/contrib/bind9/lib/dns/opensslrsa_link.c +++ b/contrib/bind9/lib/dns/opensslrsa_link.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -17,21 +17,23 @@ /* * Principal Author: Brian Wellington - * $Id: opensslrsa_link.c,v 1.20.50.3 2009/01/18 23:25:16 marka Exp $ + * $Id: opensslrsa_link.c,v 1.20.50.8 2010/01/22 02:36:49 marka Exp $ */ #ifdef OPENSSL +#include <config.h> + #ifndef USE_EVP +#if !defined(HAVE_EVP_SHA256) || !defined(HAVE_EVP_SHA512) +#define USE_EVP 0 +#else #define USE_EVP 1 #endif -#if USE_EVP -#define USE_EVP_RSA 1 #endif -#include <config.h> - #include <isc/entropy.h> #include <isc/md5.h> #include <isc/sha1.h> +#include <isc/sha2.h> #include <isc/mem.h> #include <isc/string.h> #include <isc/util.h> @@ -112,23 +114,42 @@ static isc_result_t opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) { #if USE_EVP EVP_MD_CTX *evp_md_ctx; - const EVP_MD *type; + const EVP_MD *type = NULL; #endif UNUSED(key); REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 || dctx->key->key_alg == DST_ALG_RSASHA1 || - dctx->key->key_alg == DST_ALG_NSEC3RSASHA1); + dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 || + dctx->key->key_alg == DST_ALG_RSASHA256 || + dctx->key->key_alg == DST_ALG_RSASHA512); #if USE_EVP evp_md_ctx = EVP_MD_CTX_create(); if (evp_md_ctx == NULL) return (ISC_R_NOMEMORY); - if (dctx->key->key_alg == DST_ALG_RSAMD5) + switch (dctx->key->key_alg) { + case DST_ALG_RSAMD5: type = EVP_md5(); /* MD5 + RSA */ - else + break; + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: type = EVP_sha1(); /* SHA1 + RSA */ + break; +#ifdef HAVE_EVP_SHA256 + case DST_ALG_RSASHA256: + type = EVP_sha256(); /* SHA256 + RSA */ + break; +#endif +#ifdef HAVE_EVP_SHA512 + case DST_ALG_RSASHA512: + type = EVP_sha512(); + break; +#endif + default: + INSIST(0); + } if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) { EVP_MD_CTX_destroy(evp_md_ctx); @@ -136,22 +157,56 @@ opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) { } dctx->ctxdata.evp_md_ctx = evp_md_ctx; #else - if (dctx->key->key_alg == DST_ALG_RSAMD5) { - isc_md5_t *md5ctx; + switch (dctx->key->key_alg) { + case DST_ALG_RSAMD5: + { + isc_md5_t *md5ctx; - md5ctx = isc_mem_get(dctx->mctx, sizeof(isc_md5_t)); - if (md5ctx == NULL) - return (ISC_R_NOMEMORY); - isc_md5_init(md5ctx); - dctx->ctxdata.md5ctx = md5ctx; - } else { - isc_sha1_t *sha1ctx; + md5ctx = isc_mem_get(dctx->mctx, sizeof(isc_md5_t)); + if (md5ctx == NULL) + return (ISC_R_NOMEMORY); + isc_md5_init(md5ctx); + dctx->ctxdata.md5ctx = md5ctx; + } + break; + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + { + isc_sha1_t *sha1ctx; - sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t)); - if (sha1ctx == NULL) - return (ISC_R_NOMEMORY); - isc_sha1_init(sha1ctx); - dctx->ctxdata.sha1ctx = sha1ctx; + sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t)); + if (sha1ctx == NULL) + return (ISC_R_NOMEMORY); + isc_sha1_init(sha1ctx); + dctx->ctxdata.sha1ctx = sha1ctx; + } + break; + case DST_ALG_RSASHA256: + { + isc_sha256_t *sha256ctx; + + sha256ctx = isc_mem_get(dctx->mctx, + sizeof(isc_sha256_t)); + if (sha256ctx == NULL) + return (ISC_R_NOMEMORY); + isc_sha256_init(sha256ctx); + dctx->ctxdata.sha256ctx = sha256ctx; + } + break; + case DST_ALG_RSASHA512: + { + isc_sha512_t *sha512ctx; + + sha512ctx = isc_mem_get(dctx->mctx, + sizeof(isc_sha512_t)); + if (sha512ctx == NULL) + return (ISC_R_NOMEMORY); + isc_sha512_init(sha512ctx); + dctx->ctxdata.sha512ctx = sha512ctx; + } + break; + default: + INSIST(0); } #endif @@ -166,7 +221,9 @@ opensslrsa_destroyctx(dst_context_t *dctx) { REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 || dctx->key->key_alg == DST_ALG_RSASHA1 || - dctx->key->key_alg == DST_ALG_NSEC3RSASHA1); + dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 || + dctx->key->key_alg == DST_ALG_RSASHA256 || + dctx->key->key_alg == DST_ALG_RSASHA512); #if USE_EVP if (evp_md_ctx != NULL) { @@ -174,22 +231,58 @@ opensslrsa_destroyctx(dst_context_t *dctx) { dctx->ctxdata.evp_md_ctx = NULL; } #else - if (dctx->key->key_alg == DST_ALG_RSAMD5) { - isc_md5_t *md5ctx = dctx->ctxdata.md5ctx; + switch (dctx->key->key_alg) { + case DST_ALG_RSAMD5: + { + isc_md5_t *md5ctx = dctx->ctxdata.md5ctx; - if (md5ctx != NULL) { - isc_md5_invalidate(md5ctx); - isc_mem_put(dctx->mctx, md5ctx, sizeof(isc_md5_t)); - dctx->ctxdata.md5ctx = NULL; + if (md5ctx != NULL) { + isc_md5_invalidate(md5ctx); + isc_mem_put(dctx->mctx, md5ctx, + sizeof(isc_md5_t)); + dctx->ctxdata.md5ctx = NULL; + } } - } else { - isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx; + break; + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + { + isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx; - if (sha1ctx != NULL) { - isc_sha1_invalidate(sha1ctx); - isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t)); - dctx->ctxdata.sha1ctx = NULL; + if (sha1ctx != NULL) { + isc_sha1_invalidate(sha1ctx); + isc_mem_put(dctx->mctx, sha1ctx, + sizeof(isc_sha1_t)); + dctx->ctxdata.sha1ctx = NULL; + } } + break; + case DST_ALG_RSASHA256: + { + isc_sha256_t *sha256ctx = dctx->ctxdata.sha256ctx; + + if (sha256ctx != NULL) { + isc_sha256_invalidate(sha256ctx); + isc_mem_put(dctx->mctx, sha256ctx, + sizeof(isc_sha256_t)); + dctx->ctxdata.sha256ctx = NULL; + } + } + break; + case DST_ALG_RSASHA512: + { + isc_sha512_t *sha512ctx = dctx->ctxdata.sha512ctx; + + if (sha512ctx != NULL) { + isc_sha512_invalidate(sha512ctx); + isc_mem_put(dctx->mctx, sha512ctx, + sizeof(isc_sha512_t)); + dctx->ctxdata.sha512ctx = NULL; + } + } + break; + default: + INSIST(0); } #endif } @@ -202,24 +295,67 @@ opensslrsa_adddata(dst_context_t *dctx, const isc_region_t *data) { REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 || dctx->key->key_alg == DST_ALG_RSASHA1 || - dctx->key->key_alg == DST_ALG_NSEC3RSASHA1); + dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 || + dctx->key->key_alg == DST_ALG_RSASHA256 || + dctx->key->key_alg == DST_ALG_RSASHA512); #if USE_EVP if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) { return (ISC_R_FAILURE); } #else - if (dctx->key->key_alg == DST_ALG_RSAMD5) { - isc_md5_t *md5ctx = dctx->ctxdata.md5ctx; - isc_md5_update(md5ctx, data->base, data->length); - } else { - isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx; - isc_sha1_update(sha1ctx, data->base, data->length); + switch (dctx->key->key_alg) { + case DST_ALG_RSAMD5: + { + isc_md5_t *md5ctx = dctx->ctxdata.md5ctx; + + isc_md5_update(md5ctx, data->base, data->length); + } + break; + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + { + isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx; + + isc_sha1_update(sha1ctx, data->base, data->length); + } + break; + case DST_ALG_RSASHA256: + { + isc_sha256_t *sha256ctx = dctx->ctxdata.sha256ctx; + + isc_sha256_update(sha256ctx, data->base, data->length); + } + break; + case DST_ALG_RSASHA512: + { + isc_sha512_t *sha512ctx = dctx->ctxdata.sha512ctx; + + isc_sha512_update(sha512ctx, data->base, data->length); + } + break; + default: + INSIST(0); } #endif return (ISC_R_SUCCESS); } +#if ! USE_EVP && OPENSSL_VERSION_NUMBER < 0x00908000L +/* + * Digest prefixes from RFC 5702. + */ +static unsigned char sha256_prefix[] = + { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; +static unsigned char sha512_prefix[] = + { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; +#define PREFIXLEN sizeof(sha512_prefix) +#else +#define PREFIXLEN 0 +#endif + static isc_result_t opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { dst_key_t *key = dctx->key; @@ -230,20 +366,26 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { EVP_PKEY *pkey = key->keydata.pkey; #else RSA *rsa = key->keydata.rsa; - /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */ - unsigned char digest[ISC_SHA1_DIGESTLENGTH]; - int status; - int type; - unsigned int digestlen; + /* note: ISC_SHA512_DIGESTLENGTH >= ISC_*_DIGESTLENGTH */ + unsigned char digest[PREFIXLEN + ISC_SHA512_DIGESTLENGTH]; + int status = 0; + int type = 0; + unsigned int digestlen = 0; char *message; unsigned long err; const char* file; int line; +#if OPENSSL_VERSION_NUMBER < 0x00908000L + unsigned int prefixlen = 0; + const unsigned char *prefix = NULL; +#endif #endif REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 || dctx->key->key_alg == DST_ALG_RSASHA1 || - dctx->key->key_alg == DST_ALG_NSEC3RSASHA1); + dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 || + dctx->key->key_alg == DST_ALG_RSASHA256 || + dctx->key->key_alg == DST_ALG_RSASHA512); isc_buffer_availableregion(sig, &r); @@ -258,19 +400,92 @@ opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { if (r.length < (unsigned int) RSA_size(rsa)) return (ISC_R_NOSPACE); - if (dctx->key->key_alg == DST_ALG_RSAMD5) { - isc_md5_t *md5ctx = dctx->ctxdata.md5ctx; - isc_md5_final(md5ctx, digest); - type = NID_md5; - digestlen = ISC_MD5_DIGESTLENGTH; - } else { - isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx; - isc_sha1_final(sha1ctx, digest); - type = NID_sha1; - digestlen = ISC_SHA1_DIGESTLENGTH; + switch (dctx->key->key_alg) { + case DST_ALG_RSAMD5: + { + isc_md5_t *md5ctx = dctx->ctxdata.md5ctx; + + isc_md5_final(md5ctx, digest); + type = NID_md5; + digestlen = ISC_MD5_DIGESTLENGTH; + } + break; + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + { + isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx; + + isc_sha1_final(sha1ctx, digest); + type = NID_sha1; + digestlen = ISC_SHA1_DIGESTLENGTH; + } + break; + case DST_ALG_RSASHA256: + { + isc_sha256_t *sha256ctx = dctx->ctxdata.sha256ctx; + + isc_sha256_final(digest, sha256ctx); + digestlen = ISC_SHA256_DIGESTLENGTH; +#if OPENSSL_VERSION_NUMBER < 0x00908000L + prefix = sha256_prefix; + prefixlen = sizeof(sha256_prefix); +#else + type = NID_sha256; +#endif + } + break; + case DST_ALG_RSASHA512: + { + isc_sha512_t *sha512ctx = dctx->ctxdata.sha512ctx; + + isc_sha512_final(digest, sha512ctx); + digestlen = ISC_SHA512_DIGESTLENGTH; +#if OPENSSL_VERSION_NUMBER < 0x00908000L + prefix = sha512_prefix; + prefixlen = sizeof(sha512_prefix); +#else + type = NID_sha512; +#endif + } + break; + default: + INSIST(0); } +#if OPENSSL_VERSION_NUMBER < 0x00908000L + switch (dctx->key->key_alg) { + case DST_ALG_RSAMD5: + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + INSIST(type != 0); + status = RSA_sign(type, digest, digestlen, r.base, + &siglen, rsa); + break; + + case DST_ALG_RSASHA256: + case DST_ALG_RSASHA512: + INSIST(prefix != NULL); + INSIST(prefixlen != 0); + INSIST(prefixlen + digestlen <= sizeof(digest)); + + memmove(digest + prefixlen, digest, digestlen); + memcpy(digest, prefix, prefixlen); + status = RSA_private_encrypt(digestlen + prefixlen, + digest, r.base, rsa, + RSA_PKCS1_PADDING); + if (status < 0) + status = 0; + else + siglen = status; + break; + + default: + INSIST(0); + } +#else + INSIST(type != 0); status = RSA_sign(type, digest, digestlen, r.base, &siglen, rsa); +#endif if (status == 0) { err = ERR_peek_error_line(&file, &line); if (err != 0U) { @@ -293,37 +508,129 @@ opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) { EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx; EVP_PKEY *pkey = key->keydata.pkey; #else - /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */ - unsigned char digest[ISC_SHA1_DIGESTLENGTH]; - int type; - unsigned int digestlen; + /* note: ISC_SHA512_DIGESTLENGTH >= ISC_*_DIGESTLENGTH */ + unsigned char digest[ISC_SHA512_DIGESTLENGTH]; + int type = 0; + unsigned int digestlen = 0; RSA *rsa = key->keydata.rsa; +#if OPENSSL_VERSION_NUMBER < 0x00908000L + unsigned int prefixlen = 0; + const unsigned char *prefix = NULL; +#endif #endif REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 || dctx->key->key_alg == DST_ALG_RSASHA1 || - dctx->key->key_alg == DST_ALG_NSEC3RSASHA1); + dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 || + dctx->key->key_alg == DST_ALG_RSASHA256 || + dctx->key->key_alg == DST_ALG_RSASHA512); #if USE_EVP status = EVP_VerifyFinal(evp_md_ctx, sig->base, sig->length, pkey); #else - if (dctx->key->key_alg == DST_ALG_RSAMD5) { - isc_md5_t *md5ctx = dctx->ctxdata.md5ctx; - isc_md5_final(md5ctx, digest); - type = NID_md5; - digestlen = ISC_MD5_DIGESTLENGTH; - } else { - isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx; - isc_sha1_final(sha1ctx, digest); - type = NID_sha1; - digestlen = ISC_SHA1_DIGESTLENGTH; + switch (dctx->key->key_alg) { + case DST_ALG_RSAMD5: + { + isc_md5_t *md5ctx = dctx->ctxdata.md5ctx; + + isc_md5_final(md5ctx, digest); + type = NID_md5; + digestlen = ISC_MD5_DIGESTLENGTH; + } + break; + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + { + isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx; + + isc_sha1_final(sha1ctx, digest); + type = NID_sha1; + digestlen = ISC_SHA1_DIGESTLENGTH; + } + break; + case DST_ALG_RSASHA256: + { + isc_sha256_t *sha256ctx = dctx->ctxdata.sha256ctx; + + isc_sha256_final(digest, sha256ctx); + digestlen = ISC_SHA256_DIGESTLENGTH; +#if OPENSSL_VERSION_NUMBER < 0x00908000L + prefix = sha256_prefix; + prefixlen = sizeof(sha256_prefix); +#else + type = NID_sha256; +#endif + } + break; + case DST_ALG_RSASHA512: + { + isc_sha512_t *sha512ctx = dctx->ctxdata.sha512ctx; + + isc_sha512_final(digest, sha512ctx); + digestlen = ISC_SHA512_DIGESTLENGTH; +#if OPENSSL_VERSION_NUMBER < 0x00908000L + prefix = sha512_prefix; + prefixlen = sizeof(sha512_prefix); +#else + type = NID_sha512; +#endif + } + break; + default: + INSIST(0); } - if (sig->length < (unsigned int) RSA_size(rsa)) + if (sig->length != (unsigned int) RSA_size(rsa)) return (DST_R_VERIFYFAILURE); +#if OPENSSL_VERSION_NUMBER < 0x00908000L + switch (dctx->key->key_alg) { + case DST_ALG_RSAMD5: + case DST_ALG_RSASHA1: + case DST_ALG_NSEC3RSASHA1: + INSIST(type != 0); + status = RSA_verify(type, digest, digestlen, sig->base, + RSA_size(rsa), rsa); + break; + + case DST_ALG_RSASHA256: + case DST_ALG_RSASHA512: + { + /* + * 1024 is big enough for all valid RSA bit sizes + * for use with DNSSEC. + */ + unsigned char original[PREFIXLEN + 1024]; + + INSIST(prefix != NULL); + INSIST(prefixlen != 0U); + + if (RSA_size(rsa) > (int)sizeof(original)) + return (DST_R_VERIFYFAILURE); + + status = RSA_public_decrypt(sig->length, sig->base, + original, rsa, + RSA_PKCS1_PADDING); + if (status <= 0) + return (DST_R_VERIFYFAILURE); + if (status != (int)(prefixlen + digestlen)) + return (DST_R_VERIFYFAILURE); + if (memcmp(original, prefix, prefixlen)) + return (DST_R_VERIFYFAILURE); + if (memcmp(original + prefixlen, digest, digestlen)) + return (DST_R_VERIFYFAILURE); + status = 1; + } + break; + + default: + INSIST(0); + } +#else + INSIST(type != 0); status = RSA_verify(type, digest, digestlen, sig->base, - RSA_size(rsa), rsa); + RSA_size(rsa), rsa); +#endif #endif if (status != 1) return (dst__openssl_toresult(DST_R_VERIFYFAILURE)); @@ -552,19 +859,20 @@ opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) { if (r.length < 1) DST_RET(ISC_R_NOSPACE); isc_buffer_putuint8(data, (isc_uint8_t) e_bytes); + isc_region_consume(&r, 1); } else { if (r.length < 3) DST_RET(ISC_R_NOSPACE); isc_buffer_putuint8(data, 0); isc_buffer_putuint16(data, (isc_uint16_t) e_bytes); + isc_region_consume(&r, 3); } if (r.length < e_bytes + mod_bytes) - return (ISC_R_NOSPACE); - isc_buffer_availableregion(data, &r); + DST_RET(ISC_R_NOSPACE); BN_bn2bin(rsa->e, r.base); - r.base += e_bytes; + isc_region_consume(&r, e_bytes); BN_bn2bin(rsa->n, r.base); isc_buffer_add(data, e_bytes + mod_bytes); @@ -805,8 +1113,8 @@ opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) { DST_RET(DST_R_NOENGINE); pkey = ENGINE_load_private_key(e, label, NULL, NULL); if (pkey == NULL) { - ERR_print_errors_fp(stderr); - DST_RET(ISC_R_FAILURE); + /* ERR_print_errors_fp(stderr); */ + DST_RET(ISC_R_NOTFOUND); } key->engine = isc_mem_strdup(key->mctx, name); if (key->engine == NULL) @@ -924,7 +1232,7 @@ opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label, DST_RET(DST_R_NOENGINE); pkey = ENGINE_load_private_key(e, label, NULL, NULL); if (pkey == NULL) - DST_RET(ISC_R_NOMEMORY); + DST_RET(ISC_R_NOTFOUND); key->engine = isc_mem_strdup(key->mctx, label); if (key->engine == NULL) DST_RET(ISC_R_NOMEMORY); @@ -969,10 +1277,26 @@ static dst_func_t opensslrsa_functions = { }; isc_result_t -dst__opensslrsa_init(dst_func_t **funcp) { +dst__opensslrsa_init(dst_func_t **funcp, unsigned char algorithm) { REQUIRE(funcp != NULL); - if (*funcp == NULL) - *funcp = &opensslrsa_functions; + + if (*funcp == NULL) { + switch (algorithm) { + case DST_ALG_RSASHA256: +#if defined(HAVE_EVP_SHA256) || !USE_EVP + *funcp = &opensslrsa_functions; +#endif + break; + case DST_ALG_RSASHA512: +#if defined(HAVE_EVP_SHA512) || !USE_EVP + *funcp = &opensslrsa_functions; +#endif + break; + default: + *funcp = &opensslrsa_functions; + break; + } + } return (ISC_R_SUCCESS); } diff --git a/contrib/bind9/lib/dns/rbt.c b/contrib/bind9/lib/dns/rbt.c index ff8b3a36e379..62a9e2b03bb7 100644 --- a/contrib/bind9/lib/dns/rbt.c +++ b/contrib/bind9/lib/dns/rbt.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbt.c,v 1.142.50.2 2009/01/18 23:47:40 tbox Exp $ */ +/* $Id: rbt.c,v 1.142.50.3 2009/10/20 05:06:04 marka Exp $ */ /*! \file */ @@ -85,9 +85,9 @@ struct dns_rbt { #define HASHVAL(node) ((node)->hashval) #define COLOR(node) ((node)->color) #define NAMELEN(node) ((node)->namelen) +#define OLDNAMELEN(node) ((node)->oldnamelen) #define OFFSETLEN(node) ((node)->offsetlen) #define ATTRS(node) ((node)->attributes) -#define PADBYTES(node) ((node)->padbytes) #define IS_ROOT(node) ISC_TF((node)->is_root == 1) #define FINDCALLBACK(node) ISC_TF((node)->find_callback == 1) @@ -100,13 +100,23 @@ struct dns_rbt { #define LOCKNUM(node) ((node)->locknum) /*% - * The variable length stuff stored after the node. + * The variable length stuff stored after the node has the following + * structure. + * + * <name_data>{1..255}<oldoffsetlen>{1}<offsets>{1..128} + * + * <name_data> contains the name of the node when it was created. + * <oldoffsetlen> contains the length of <offsets> when the node was created. + * <offsets> contains the offets into name for each label when the node was + * created. */ + #define NAME(node) ((unsigned char *)((node) + 1)) -#define OFFSETS(node) (NAME(node) + NAMELEN(node)) +#define OFFSETS(node) (NAME(node) + OLDNAMELEN(node) + 1) +#define OLDOFFSETLEN(node) (OFFSETS(node)[-1]) #define NODE_SIZE(node) (sizeof(*node) + \ - NAMELEN(node) + OFFSETLEN(node) + PADBYTES(node)) + OLDNAMELEN(node) + OLDOFFSETLEN(node) + 1) /*% * Color management. @@ -553,11 +563,6 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) { NAMELEN(current) = prefix->length; OFFSETLEN(current) = prefix->labels; - memcpy(OFFSETS(current), prefix->offsets, - prefix->labels); - PADBYTES(current) += - (current_name.length - prefix->length) + - (current_name.labels - prefix->labels); /* * Set up the new root of the next level. @@ -1423,7 +1428,7 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) { * Allocate space for the node structure, the name, and the offsets. */ node = (dns_rbtnode_t *)isc_mem_get(mctx, sizeof(*node) + - region.length + labels); + region.length + labels + 1); if (node == NULL) return (ISC_R_NOMEMORY); @@ -1460,10 +1465,12 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) { * The offsets table could be made smaller by eliminating the * first offset, which is always 0. This requires changes to * lib/dns/name.c. + * + * Note: OLDOFFSETLEN *must* be assigned *after* OLDNAMELEN is assigned + * as it uses OLDNAMELEN. */ - NAMELEN(node) = region.length; - PADBYTES(node) = 0; - OFFSETLEN(node) = labels; + OLDNAMELEN(node) = NAMELEN(node) = region.length; + OLDOFFSETLEN(node) = OFFSETLEN(node) = labels; ATTRS(node) = name->attributes; memcpy(NAME(node), region.base, region.length); diff --git a/contrib/bind9/lib/dns/rbtdb.c b/contrib/bind9/lib/dns/rbtdb.c index d5b5b5c8194f..df3a5f47e206 100644 --- a/contrib/bind9/lib/dns/rbtdb.c +++ b/contrib/bind9/lib/dns/rbtdb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.270.12.6.10.2 2009/12/31 21:44:36 each Exp $ */ +/* $Id: rbtdb.c,v 1.270.12.16.8.3 2010/02/26 00:24:39 marka Exp $ */ /*! \file */ @@ -258,21 +258,8 @@ typedef struct rdatasetheader { dns_rbtnode_t *node; isc_stdtime_t last_used; - ISC_LINK(struct rdatasetheader) lru_link; - /*%< - * Used for LRU-based cache management. We should probably make - * these cache-DB specific. We might also make it a pointer and - * ensure only the top header has a valid link to save memory. - * The linked-list is locked by the rbtdb->lrulock. - */ + ISC_LINK(struct rdatasetheader) link; - /* - * It's possible this should not be here anymore, but instead - * referenced from the bucket's heap directly. - */ -#if 0 - isc_heap_t *heap; -#endif unsigned int heap_index; /*%< * Used for TTL-based cache cleaning. @@ -396,7 +383,7 @@ typedef struct rbtdb_version { isc_uint8_t flags; isc_uint16_t iterations; isc_uint8_t salt_length; - unsigned char salt[NSEC3_MAX_HASH_LENGTH]; + unsigned char salt[DNS_NSEC3_SALTSIZE]; } rbtdb_version_t; typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t; @@ -534,6 +521,8 @@ static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader); static void prune_tree(isc_task_t *task, isc_event_t *event); +static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust); +static void rdataset_expire(dns_rdataset_t *rdataset); static dns_rdatasetmethods_t rdataset_methods = { rdataset_disassociate, @@ -548,7 +537,9 @@ static dns_rdatasetmethods_t rdataset_methods = { rdataset_getclosest, rdataset_getadditional, rdataset_setadditional, - rdataset_putadditional + rdataset_putadditional, + rdataset_settrust, + rdataset_expire }; static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp); @@ -1227,7 +1218,7 @@ free_noqname(isc_mem_t *mctx, struct noqname **noqname) { static inline void init_rdataset(dns_rbtdb_t *rbtdb, rdatasetheader_t *h) { - ISC_LINK_INIT(h, lru_link); + ISC_LINK_INIT(h, link); h->heap_index = 0; #if TRACE_HEADER @@ -1267,8 +1258,10 @@ free_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *rdataset) } idx = rdataset->node->locknum; - if (ISC_LINK_LINKED(rdataset, lru_link)) - ISC_LIST_UNLINK(rbtdb->rdatasets[idx], rdataset, lru_link); + if (ISC_LINK_LINKED(rdataset, link)) { + INSIST(IS_CACHE(rbtdb)); + ISC_LIST_UNLINK(rbtdb->rdatasets[idx], rdataset, link); + } if (rdataset->heap_index != 0) isc_heap_delete(rbtdb->heaps[idx], rdataset->heap_index); rdataset->heap_index = 0; @@ -2075,8 +2068,6 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version, continue; #endif - INSIST(nsec3param.salt_length <= - sizeof(version->salt)); memcpy(version->salt, nsec3param.salt, nsec3param.salt_length); version->hash = nsec3param.hash; @@ -2284,17 +2275,18 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { for (header = HEAD(resigned_list); header != NULL; header = HEAD(resigned_list)) { - ISC_LIST_UNLINK(resigned_list, header, lru_link); - if (rollback) { - nodelock_t *lock; - lock = &rbtdb->node_locks[header->node->locknum].lock; - NODE_LOCK(lock, isc_rwlocktype_write); + nodelock_t *lock; + + ISC_LIST_UNLINK(resigned_list, header, link); + + lock = &rbtdb->node_locks[header->node->locknum].lock; + NODE_LOCK(lock, isc_rwlocktype_write); + if (rollback) resign_insert(rbtdb, header->node->locknum, header); - NODE_UNLOCK(lock, isc_rwlocktype_write); - } decrement_reference(rbtdb, header->node, least_serial, isc_rwlocktype_write, isc_rwlocktype_none, ISC_FALSE); + NODE_UNLOCK(lock, isc_rwlocktype_write); } if (!EMPTY(cleanup_list)) { @@ -3524,11 +3516,17 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, /* * The node may be a zone cut itself. If it might be one, * make sure we check for it later. + * + * DS records live above the zone cut in ordinary zone so + * we want to ignore any referral. + * + * Stub zones don't have anything "above" the delgation so + * we always return a referral. */ if (node->find_callback && - (node != search.rbtdb->origin_node || - IS_STUB(search.rbtdb)) && - !dns_rdatatype_atparent(type)) + ((node != search.rbtdb->origin_node && + !dns_rdatatype_atparent(type)) || + IS_STUB(search.rbtdb))) maybe_zonecut = ISC_TRUE; } @@ -3546,8 +3544,8 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * We now go looking for rdata... */ - NODE_LOCK(&(search.rbtdb->node_locks[node->locknum].lock), - isc_rwlocktype_read); + lock = &search.rbtdb->node_locks[node->locknum].lock; + NODE_LOCK(lock, isc_rwlocktype_read); found = NULL; foundsig = NULL; @@ -3625,8 +3623,10 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * we are using behave as if it isn't here. */ if (header->type == dns_rdatatype_nsec3 && - !matchparams(header, &search)) + !matchparams(header, &search)) { + NODE_UNLOCK(lock, isc_rwlocktype_read); goto partial_match; + } /* * If we found a type we were looking for, * remember it. @@ -3705,7 +3705,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * we really have a partial match. */ if (!wild) { - lock = &search.rbtdb->node_locks[node->locknum].lock; NODE_UNLOCK(lock, isc_rwlocktype_read); goto partial_match; } @@ -3722,7 +3721,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, * * Return the delegation. */ - lock = &search.rbtdb->node_locks[node->locknum].lock; NODE_UNLOCK(lock, isc_rwlocktype_read); result = setup_delegation(&search, nodep, foundname, rdataset, sigrdataset); @@ -3744,7 +3742,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, goto node_exit; } - lock = &search.rbtdb->node_locks[node->locknum].lock; NODE_UNLOCK(lock, isc_rwlocktype_read); result = find_closest_nsec(&search, nodep, foundname, rdataset, sigrdataset, @@ -3829,7 +3826,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, if (result == DNS_R_GLUE && (search.options & DNS_DBFIND_VALIDATEGLUE) != 0 && !valid_glue(&search, foundname, type, node)) { - lock = &search.rbtdb->node_locks[node->locknum].lock; NODE_UNLOCK(lock, isc_rwlocktype_read); result = setup_delegation(&search, nodep, foundname, rdataset, sigrdataset); @@ -3861,8 +3857,7 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, foundname->attributes |= DNS_NAMEATTR_WILDCARD; node_exit: - NODE_UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock), - isc_rwlocktype_read); + NODE_UNLOCK(lock, isc_rwlocktype_read); tree_exit: RWUNLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read); @@ -5408,8 +5403,10 @@ static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader) { isc_result_t result; + INSIST(!IS_CACHE(rbtdb)); INSIST(newheader->heap_index == 0); - INSIST(!ISC_LINK_LINKED(newheader, lru_link)); + INSIST(!ISC_LINK_LINKED(newheader, link)); + result = isc_heap_insert(rbtdb->heaps[idx], newheader); return (result); } @@ -5735,7 +5732,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, idx = newheader->node->locknum; if (IS_CACHE(rbtdb)) { ISC_LIST_PREPEND(rbtdb->rdatasets[idx], - newheader, lru_link); + newheader, link); /* * XXXMLG We don't check the return value * here. If it fails, we will not do TTL @@ -5794,7 +5791,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, idx = newheader->node->locknum; if (IS_CACHE(rbtdb)) { ISC_LIST_PREPEND(rbtdb->rdatasets[idx], - newheader, lru_link); + newheader, link); isc_heap_insert(rbtdb->heaps[idx], newheader); } else if (RESIGN(newheader)) { resign_insert(rbtdb, idx, newheader); @@ -6519,11 +6516,17 @@ static void delete_callback(void *data, void *arg) { dns_rbtdb_t *rbtdb = arg; rdatasetheader_t *current, *next; + unsigned int locknum; - for (current = data; current != NULL; current = next) { + current = data; + locknum = current->node->locknum; + NODE_LOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); + while (current != NULL) { next = current->next; free_rdataset(rbtdb, rbtdb->common.mctx, current); + current = next; } + NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write); } static isc_boolean_t @@ -6642,8 +6645,8 @@ getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash, if (rbtversion->havensec3) { if (hash != NULL) *hash = rbtversion->hash; - if (salt != NULL && salt_length != 0) { - REQUIRE(*salt_length > rbtversion->salt_length); + if (salt != NULL && salt_length != NULL) { + REQUIRE(*salt_length >= rbtversion->salt_length); memcpy(salt, rbtversion->salt, rbtversion->salt_length); } if (salt_length != NULL) @@ -6707,27 +6710,35 @@ getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, rdatasetheader_t *header = NULL, *this; unsigned int i; isc_result_t result = ISC_R_NOTFOUND; + unsigned int locknum; REQUIRE(VALID_RBTDB(rbtdb)); RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read); for (i = 0; i < rbtdb->node_lock_count; i++) { + NODE_LOCK(&rbtdb->node_locks[i].lock, isc_rwlocktype_read); this = isc_heap_element(rbtdb->heaps[i], 1); - if (this == NULL) + if (this == NULL) { + NODE_UNLOCK(&rbtdb->node_locks[i].lock, + isc_rwlocktype_read); continue; + } if (header == NULL) header = this; - else if (isc_serial_lt(this->resign, header->resign)) + else if (isc_serial_lt(this->resign, header->resign)) { + locknum = header->node->locknum; + NODE_UNLOCK(&rbtdb->node_locks[locknum].lock, + isc_rwlocktype_read); header = this; + } else + NODE_UNLOCK(&rbtdb->node_locks[i].lock, + isc_rwlocktype_read); } if (header == NULL) goto unlock; - NODE_LOCK(&rbtdb->node_locks[header->node->locknum].lock, - isc_rwlocktype_read); - bind_rdataset(rbtdb, header->node, header, 0, rdataset); if (foundname != NULL) @@ -6761,7 +6772,7 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) header = rdataset->private3; header--; - RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read); + RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write); NODE_LOCK(&rbtdb->node_locks[node->locknum].lock, isc_rwlocktype_write); /* @@ -6771,11 +6782,11 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) new_reference(rbtdb, node); isc_heap_delete(rbtdb->heaps[node->locknum], header->heap_index); header->heap_index = 0; - ISC_LIST_APPEND(rbtversion->resigned_list, header, lru_link); + ISC_LIST_APPEND(rbtversion->resigned_list, header, link); NODE_UNLOCK(&rbtdb->node_locks[node->locknum].lock, isc_rwlocktype_write); - RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read); + RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write); } static dns_stats_t * @@ -7400,6 +7411,34 @@ rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name, return (ISC_R_SUCCESS); } +static void +rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { + dns_rbtdb_t *rbtdb = rdataset->private1; + dns_rbtnode_t *rbtnode = rdataset->private2; + rdatasetheader_t *header = rdataset->private3; + + header--; + NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock, + isc_rwlocktype_write); + header->trust = rdataset->trust = trust; + NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock, + isc_rwlocktype_write); +} + +static void +rdataset_expire(dns_rdataset_t *rdataset) { + dns_rbtdb_t *rbtdb = rdataset->private1; + dns_rbtnode_t *rbtnode = rdataset->private2; + rdatasetheader_t *header = rdataset->private3; + + header--; + NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock, + isc_rwlocktype_write); + expire_header(rbtdb, header, ISC_FALSE); + NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock, + isc_rwlocktype_write); +} + /* * Rdataset Iterator Methods */ @@ -8497,13 +8536,11 @@ update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, INSIST(IS_CACHE(rbtdb)); /* To be checked: can we really assume this? XXXMLG */ - INSIST(ISC_LINK_LINKED(header, lru_link)); + INSIST(ISC_LINK_LINKED(header, link)); - ISC_LIST_UNLINK(rbtdb->rdatasets[header->node->locknum], - header, lru_link); + ISC_LIST_UNLINK(rbtdb->rdatasets[header->node->locknum], header, link); header->last_used = now; - ISC_LIST_PREPEND(rbtdb->rdatasets[header->node->locknum], - header, lru_link); + ISC_LIST_PREPEND(rbtdb->rdatasets[header->node->locknum], header, link); } /*% @@ -8539,7 +8576,7 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]); header != NULL && purgecount > 0; header = header_prev) { - header_prev = ISC_LIST_PREV(header, lru_link); + header_prev = ISC_LIST_PREV(header, link); /* * Unlink the entry at this point to avoid checking it * again even if it's currently used someone else and @@ -8548,7 +8585,7 @@ overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, * TTL was reset to 0. */ ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header, - lru_link); + link); expire_header(rbtdb, header, tree_locked); purgecount--; } diff --git a/contrib/bind9/lib/dns/rcode.c b/contrib/bind9/lib/dns/rcode.c index 58ade8587e8c..9feaeb07d9c0 100644 --- a/contrib/bind9/lib/dns/rcode.c +++ b/contrib/bind9/lib/dns/rcode.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rcode.c,v 1.8 2008/09/25 04:02:38 tbox Exp $ */ +/* $Id: rcode.c,v 1.8.48.2 2010/01/15 23:47:33 tbox Exp $ */ #include <config.h> #include <ctype.h> @@ -100,6 +100,8 @@ { DNS_KEYALG_ECC, "ECC", 0 }, \ { DNS_KEYALG_RSASHA1, "RSASHA1", 0 }, \ { DNS_KEYALG_NSEC3RSASHA1, "NSEC3RSASHA1", 0 }, \ + { DNS_KEYALG_RSASHA256, "RSASHA256", 0 }, \ + { DNS_KEYALG_RSASHA512, "RSASHA512", 0 }, \ { DNS_KEYALG_INDIRECT, "INDIRECT", 0 }, \ { DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 }, \ { DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, \ diff --git a/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c b/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c index bc2b4e889d4b..6a58bc9bb4e8 100644 --- a/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c +++ b/contrib/bind9/lib/dns/rdata/generic/ipseckey_45.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ipseckey_45.c,v 1.4.332.2 2009/01/18 23:47:41 tbox Exp $ */ +/* $Id: ipseckey_45.c,v 1.4.332.3 2009/09/18 21:55:48 jinmei Exp $ */ #ifndef RDATA_GENERIC_IPSECKEY_45_C #define RDATA_GENERIC_IPSECKEY_45_C @@ -243,6 +243,7 @@ fromwire_ipseckey(ARGS_FROMWIRE) { isc_buffer_forward(source, 3); RETERR(dns_name_fromwire(&name, source, dctx, options, target)); isc_buffer_activeregion(source, ®ion); + isc_buffer_forward(source, region.length); return(mem_tobuffer(target, region.base, region.length)); default: diff --git a/contrib/bind9/lib/dns/rdatalist.c b/contrib/bind9/lib/dns/rdatalist.c index d6f11ae64d30..d07261989640 100644 --- a/contrib/bind9/lib/dns/rdatalist.c +++ b/contrib/bind9/lib/dns/rdatalist.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdatalist.c,v 1.36 2008/09/24 02:46:22 marka Exp $ */ +/* $Id: rdatalist.c,v 1.36.336.2 2010/02/25 10:57:12 tbox Exp $ */ /*! \file */ @@ -46,6 +46,8 @@ static dns_rdatasetmethods_t methods = { isc__rdatalist_getclosest, NULL, NULL, + NULL, + NULL, NULL }; diff --git a/contrib/bind9/lib/dns/rdataset.c b/contrib/bind9/lib/dns/rdataset.c index 6088a068ad2f..946ec9ae9aab 100644 --- a/contrib/bind9/lib/dns/rdataset.c +++ b/contrib/bind9/lib/dns/rdataset.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataset.c,v 1.82.50.2 2009/01/18 23:47:40 tbox Exp $ */ +/* $Id: rdataset.c,v 1.82.50.2.22.2 2010/02/25 10:57:12 tbox Exp $ */ /*! \file */ @@ -182,6 +182,8 @@ static dns_rdatasetmethods_t question_methods = { NULL, NULL, NULL, + NULL, + NULL, NULL }; @@ -732,3 +734,22 @@ dns_rdataset_putadditional(dns_acache_t *acache, return (ISC_R_FAILURE); } +void +dns_rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (rdataset->methods->settrust != NULL) + (rdataset->methods->settrust)(rdataset, trust); + else + rdataset->trust = trust; +} + +void +dns_rdataset_expire(dns_rdataset_t *rdataset) { + REQUIRE(DNS_RDATASET_VALID(rdataset)); + REQUIRE(rdataset->methods != NULL); + + if (rdataset->methods->expire != NULL) + (rdataset->methods->expire)(rdataset); +} diff --git a/contrib/bind9/lib/dns/rdataslab.c b/contrib/bind9/lib/dns/rdataslab.c index b22868d6f212..4eadff9881e7 100644 --- a/contrib/bind9/lib/dns/rdataslab.c +++ b/contrib/bind9/lib/dns/rdataslab.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rdataslab.c,v 1.48.50.2 2009/01/18 23:47:40 tbox Exp $ */ +/* $Id: rdataslab.c,v 1.48.50.2.22.2 2010/02/25 10:57:12 tbox Exp $ */ /*! \file */ @@ -436,6 +436,8 @@ static dns_rdatasetmethods_t rdataset_methods = { NULL, NULL, NULL, + NULL, + NULL, NULL }; diff --git a/contrib/bind9/lib/dns/resolver.c b/contrib/bind9/lib/dns/resolver.c index 1b4f407c87fe..244718fb5db0 100644 --- a/contrib/bind9/lib/dns/resolver.c +++ b/contrib/bind9/lib/dns/resolver.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.384.14.14.8.2 2010/01/07 17:17:19 each Exp $ */ +/* $Id: resolver.c,v 1.384.14.20.8.2 2010/02/25 10:57:12 tbox Exp $ */ /*! \file */ @@ -334,6 +334,18 @@ typedef struct alternate { ISC_LINK(struct alternate) link; } alternate_t; +typedef struct dns_badcache dns_badcache_t; +struct dns_badcache { + dns_badcache_t * next; + dns_rdatatype_t type; + isc_time_t expire; + unsigned int hashval; + dns_name_t name; +}; +#define DNS_BADCACHE_SIZE 1021 +#define DNS_BADCACHE_TTL(fctx) \ + (((fctx)->res->lame_ttl > 30 ) ? (fctx)->res->lame_ttl : 30) + struct dns_resolver { /* Unlocked. */ unsigned int magic; @@ -380,6 +392,13 @@ struct dns_resolver { isc_boolean_t priming; unsigned int spillat; /* clients-per-query */ unsigned int nextdisp; + + /* Bad cache. */ + dns_badcache_t ** badcache; + unsigned int badcount; + unsigned int badhash; + unsigned int badsweep; + /* Locked by primelock. */ dns_fetch_t * primefetch; /* Locked by nlock. */ @@ -410,7 +429,8 @@ static void empty_bucket(dns_resolver_t *res); static isc_result_t resquery_send(resquery_t *query); static void resquery_response(isc_task_t *task, isc_event_t *event); static void resquery_connected(isc_task_t *task, isc_event_t *event); -static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying); +static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, + isc_boolean_t badcache); static isc_boolean_t fctx_destroy(fetchctx_t *fctx); static isc_result_t ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, @@ -1169,7 +1189,7 @@ process_sendevent(resquery_t *query, isc_event_t *event) { if (result != ISC_R_SUCCESS) fctx_done(fctx, result, __LINE__); else - fctx_try(fctx, ISC_TRUE); + fctx_try(fctx, ISC_TRUE, ISC_FALSE); } } @@ -2071,7 +2091,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_SUCCESS) fctx_done(fctx, result, __LINE__); else - fctx_try(fctx, ISC_TRUE); + fctx_try(fctx, ISC_TRUE, ISC_FALSE); } } @@ -2133,7 +2153,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) { dns_adb_destroyfind(&find); if (want_try) - fctx_try(fctx, ISC_TRUE); + fctx_try(fctx, ISC_TRUE, ISC_FALSE); else if (want_done) fctx_done(fctx, ISC_R_FAILURE, __LINE__); else if (bucket_empty) @@ -2534,8 +2554,18 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port, } } +static isc_boolean_t +isstrictsubdomain(dns_name_t *name1, dns_name_t *name2) { + int order; + unsigned int nlabels; + dns_namereln_t namereln; + + namereln = dns_name_fullcompare(name1, name2, &order, &nlabels); + return (ISC_TF(namereln == dns_namereln_subdomain)); +} + static isc_result_t -fctx_getaddresses(fetchctx_t *fctx) { +fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) { dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; dns_resolver_t *res; @@ -2579,23 +2609,40 @@ fctx_getaddresses(fetchctx_t *fctx) { dns_name_t *name = &fctx->name; dns_name_t suffix; unsigned int labels; + dns_fixedname_t fixed; + dns_name_t *domain; /* * DS records are found in the parent server. * Strip label to get the correct forwarder (if any). */ - if (fctx->type == dns_rdatatype_ds && + if (dns_rdatatype_atparent(fctx->type) && dns_name_countlabels(name) > 1) { dns_name_init(&suffix, NULL); labels = dns_name_countlabels(name); dns_name_getlabelsequence(name, 1, labels - 1, &suffix); name = &suffix; } - result = dns_fwdtable_find(fctx->res->view->fwdtable, name, - &forwarders); + + dns_fixedname_init(&fixed); + domain = dns_fixedname_name(&fixed); + result = dns_fwdtable_find2(fctx->res->view->fwdtable, name, + domain, &forwarders); if (result == ISC_R_SUCCESS) { sa = ISC_LIST_HEAD(forwarders->addrs); fctx->fwdpolicy = forwarders->fwdpolicy; + if (fctx->fwdpolicy == dns_fwdpolicy_only && + isstrictsubdomain(domain, &fctx->domain)) { + isc_mem_t *mctx; + + mctx = res->buckets[fctx->bucketnum].mctx; + dns_name_free(&fctx->domain, mctx); + dns_name_init(&fctx->domain, NULL); + result = dns_name_dup(domain, mctx, + &fctx->domain); + if (result != ISC_R_SUCCESS) + return (result); + } } } @@ -2737,12 +2784,24 @@ fctx_getaddresses(fetchctx_t *fctx) { */ result = DNS_R_WAIT; } else { + isc_time_t expire; + isc_interval_t i; /* * We've lost completely. We don't know any * addresses, and the ADB has told us it can't get * them. */ FCTXTRACE("no addresses"); + isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0); + result = isc_time_nowplusinterval(&expire, &i); + if (badcache && + (fctx->type == dns_rdatatype_dnskey || + fctx->type == dns_rdatatype_dlv || + fctx->type == dns_rdatatype_ds) && + result == ISC_R_SUCCESS) + dns_resolver_addbadcache(fctx->res, + &fctx->name, + fctx->type, &expire); result = ISC_R_FAILURE; } } else { @@ -2965,7 +3024,7 @@ fctx_nextaddress(fetchctx_t *fctx) { } static void -fctx_try(fetchctx_t *fctx, isc_boolean_t retrying) { +fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) { isc_result_t result; dns_adbaddrinfo_t *addrinfo; @@ -2983,7 +3042,7 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying) { fctx_cleanupaltfinds(fctx); fctx_cleanupforwaddrs(fctx); fctx_cleanupaltaddrs(fctx); - result = fctx_getaddresses(fctx); + result = fctx_getaddresses(fctx, badcache); if (result == DNS_R_WAIT) { /* * Sleep waiting for addresses. @@ -3148,7 +3207,7 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) { /* * Keep trying. */ - fctx_try(fctx, ISC_TRUE); + fctx_try(fctx, ISC_TRUE, ISC_FALSE); } isc_event_free(&event); @@ -3318,7 +3377,7 @@ fctx_start(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_SUCCESS) fctx_done(fctx, result, __LINE__); else - fctx_try(fctx, ISC_FALSE); + fctx_try(fctx, ISC_FALSE, ISC_FALSE); } else if (bucket_empty) empty_bucket(res); } @@ -3477,21 +3536,22 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, if (domain == NULL) { dns_forwarders_t *forwarders = NULL; unsigned int labels; + dns_name_t *fwdname = name; /* * DS records are found in the parent server. * Strip label to get the correct forwarder (if any). */ - if (fctx->type == dns_rdatatype_ds && + if (dns_rdatatype_atparent(fctx->type) && dns_name_countlabels(name) > 1) { dns_name_init(&suffix, NULL); labels = dns_name_countlabels(name); dns_name_getlabelsequence(name, 1, labels - 1, &suffix); - name = &suffix; + fwdname = &suffix; } dns_fixedname_init(&fixed); domain = dns_fixedname_name(&fixed); - result = dns_fwdtable_find2(fctx->res->view->fwdtable, name, + result = dns_fwdtable_find2(fctx->res->view->fwdtable, fwdname, domain, &forwarders); if (result == ISC_R_SUCCESS) fctx->fwdpolicy = forwarders->fwdpolicy; @@ -3502,7 +3562,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, * nameservers, and we're not in forward-only mode, * so find the best nameservers to use. */ - if (dns_rdatatype_atparent(type)) + if (dns_rdatatype_atparent(fctx->type)) findoptions |= DNS_DBFIND_NOEXACT; result = dns_view_findzonecut(res->view, name, domain, 0, findoptions, ISC_TRUE, @@ -3895,6 +3955,8 @@ validated(isc_task_t *task, isc_event_t *event) { LOCK(&fctx->res->buckets[fctx->bucketnum].lock); + isc_stdtime_get(&now); + /* * If chaining, we need to make sure that the right result code is * returned, and that the rdatasets are bound. @@ -3941,35 +4003,80 @@ validated(isc_task_t *task, isc_event_t *event) { inc_stats(fctx->res, dns_resstatscounter_valfail); fctx->valfail++; fctx->vresult = vevent->result; - result = ISC_R_NOTFOUND; - if (vevent->rdataset != NULL) - result = dns_db_findnode(fctx->cache, vevent->name, - ISC_TRUE, &node); - if (result == ISC_R_SUCCESS) - (void)dns_db_deleterdataset(fctx->cache, node, NULL, - vevent->type, 0); - if (result == ISC_R_SUCCESS && vevent->sigrdataset != NULL) - (void)dns_db_deleterdataset(fctx->cache, node, NULL, - dns_rdatatype_rrsig, - vevent->type); - if (result == ISC_R_SUCCESS) - dns_db_detachnode(fctx->cache, &node); - result = vevent->result; + if (fctx->vresult != DNS_R_BROKENCHAIN) { + result = ISC_R_NOTFOUND; + if (vevent->rdataset != NULL) + result = dns_db_findnode(fctx->cache, + vevent->name, + ISC_TRUE, &node); + if (result == ISC_R_SUCCESS) + (void)dns_db_deleterdataset(fctx->cache, node, + NULL, + vevent->type, 0); + if (result == ISC_R_SUCCESS && + vevent->sigrdataset != NULL) + (void)dns_db_deleterdataset(fctx->cache, node, + NULL, + dns_rdatatype_rrsig, + vevent->type); + if (result == ISC_R_SUCCESS) + dns_db_detachnode(fctx->cache, &node); + } + if (fctx->vresult == DNS_R_BROKENCHAIN && !negative) { + /* + * Cache the data as pending for later validation. + */ + result = ISC_R_NOTFOUND; + if (vevent->rdataset != NULL) + result = dns_db_findnode(fctx->cache, + vevent->name, + ISC_TRUE, &node); + if (result == ISC_R_SUCCESS) { + (void)dns_db_addrdataset(fctx->cache, node, + NULL, now, + vevent->rdataset, 0, + NULL); + } + if (result == ISC_R_SUCCESS && + vevent->sigrdataset != NULL) + (void)dns_db_addrdataset(fctx->cache, node, + NULL, now, + vevent->sigrdataset, + 0, NULL); + if (result == ISC_R_SUCCESS) + dns_db_detachnode(fctx->cache, &node); + } + result = fctx->vresult; add_bad(fctx, addrinfo, result, badns_validation); isc_event_free(&event); UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); INSIST(fctx->validator == NULL); fctx->validator = ISC_LIST_HEAD(fctx->validators); - if (fctx->validator != NULL) { + if (fctx->validator != NULL) dns_validator_send(fctx->validator); - } else if (sentresponse) + else if (sentresponse) fctx_done(fctx, result, __LINE__); /* Locks bucket. */ - else - fctx_try(fctx, ISC_TRUE); /* Locks bucket. */ + else if (result == DNS_R_BROKENCHAIN) { + isc_result_t tresult; + isc_time_t expire; + isc_interval_t i; + + isc_interval_set(&i, DNS_BADCACHE_TTL(fctx), 0); + tresult = isc_time_nowplusinterval(&expire, &i); + if (negative && + (fctx->type == dns_rdatatype_dnskey || + fctx->type == dns_rdatatype_dlv || + fctx->type == dns_rdatatype_ds) && + tresult == ISC_R_SUCCESS) + dns_resolver_addbadcache(fctx->res, + &fctx->name, + fctx->type, &expire); + fctx_done(fctx, result, __LINE__); /* Locks bucket. */ + } else + fctx_try(fctx, ISC_TRUE, ISC_TRUE); /* Locks bucket. */ return; } - isc_stdtime_get(&now); if (negative) { dns_rdatatype_t covers; @@ -5762,7 +5869,7 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) { /* * Try again. */ - fctx_try(fctx, ISC_TRUE); + fctx_try(fctx, ISC_TRUE, ISC_FALSE); } else { unsigned int n; dns_rdataset_t *nsrdataset = NULL; @@ -6601,7 +6708,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { /* * Try again. */ - fctx_try(fctx, !get_nameservers); + fctx_try(fctx, !get_nameservers, ISC_FALSE); } else if (resend) { /* * Resend (probably with changed options). @@ -6663,6 +6770,27 @@ resquery_response(isc_task_t *task, isc_event_t *event) { /*** *** Resolver Methods ***/ +static void +destroy_badcache(dns_resolver_t *res) { + dns_badcache_t *bad, *next; + unsigned int i; + + if (res->badcache != NULL) { + for (i = 0; i < res->badhash; i++) + for (bad = res->badcache[i]; bad != NULL; + bad = next) { + next = bad->next; + isc_mem_put(res->mctx, bad, sizeof(*bad) + + bad->name.length); + res->badcount--; + } + isc_mem_put(res->mctx, res->badcache, + sizeof(*res->badcache) * res->badhash); + res->badcache = NULL; + res->badhash = 0; + INSIST(res->badcount == 0); + } +} static void destroy(dns_resolver_t *res) { @@ -6700,6 +6828,7 @@ destroy(dns_resolver_t *res) { isc_mem_put(res->mctx, a, sizeof(*a)); } dns_resolver_reset_algorithms(res); + destroy_badcache(res); dns_resolver_resetmustbesecure(res); #if USE_ALGLOCK isc_rwlock_destroy(&res->alglock); @@ -6823,6 +6952,10 @@ dns_resolver_create(dns_view_t *view, ISC_LIST_INIT(res->alternates); res->udpsize = RECV_BUFFER_SIZE; res->algorithms = NULL; + res->badcache = NULL; + res->badcount = 0; + res->badhash = 0; + res->badsweep = 0; res->mustbesecure = NULL; res->spillatmin = res->spillat = 10; res->spillatmax = 100; @@ -7664,6 +7797,256 @@ dns_resolver_getudpsize(dns_resolver_t *resolver) { return (resolver->udpsize); } +void +dns_resolver_flushbadcache(dns_resolver_t *resolver, dns_name_t *name) { + unsigned int i; + dns_badcache_t *bad, *prev, *next; + + REQUIRE(VALID_RESOLVER(resolver)); + + LOCK(&resolver->lock); + if (resolver->badcache == NULL) + goto unlock; + + if (name != NULL) { + isc_time_t now; + isc_result_t result; + result = isc_time_now(&now); + if (result != ISC_R_SUCCESS) + isc_time_settoepoch(&now); + i = dns_name_hash(name, ISC_FALSE) % resolver->badhash; + prev = NULL; + for (bad = resolver->badcache[i]; bad != NULL; bad = next) { + int n; + next = bad->next; + n = isc_time_compare(&bad->expire, &now); + if (n < 0 || dns_name_equal(name, &bad->name)) { + if (prev == NULL) + resolver->badcache[i] = bad->next; + else + prev->next = bad->next; + isc_mem_put(resolver->mctx, bad, sizeof(*bad) + + bad->name.length); + resolver->badcount--; + } else + prev = bad; + } + } else + destroy_badcache(resolver); + + unlock: + UNLOCK(&resolver->lock); + +} + +static void +resizehash(dns_resolver_t *resolver, isc_time_t *now, isc_boolean_t grow) { + unsigned int newsize; + dns_badcache_t **new, *bad, *next; + unsigned int i; + + if (grow) + newsize = resolver->badhash * 2 + 1; + else + newsize = (resolver->badhash - 1) / 2; + + new = isc_mem_get(resolver->mctx, + sizeof(*resolver->badcache) * newsize); + if (new == NULL) + return; + memset(new, 0, sizeof(*resolver->badcache) * newsize); + for (i = 0; i < resolver->badhash; i++) { + for (bad = resolver->badcache[i]; bad != NULL; bad = next) { + next = bad->next; + if (isc_time_compare(&bad->expire, now) < 0) { + isc_mem_put(resolver->mctx, bad, sizeof(*bad) + + bad->name.length); + resolver->badcount--; + } else { + bad->next = new[bad->hashval % newsize]; + new[bad->hashval % newsize] = bad; + } + } + } + isc_mem_put(resolver->mctx, resolver->badcache, + sizeof(*resolver->badcache) * resolver->badhash); + resolver->badhash = newsize; + resolver->badcache = new; +} + +void +dns_resolver_addbadcache(dns_resolver_t *resolver, dns_name_t *name, + dns_rdatatype_t type, isc_time_t *expire) +{ + isc_time_t now; + isc_result_t result = ISC_R_SUCCESS; + unsigned int i, hashval; + dns_badcache_t *bad, *prev, *next; + + REQUIRE(VALID_RESOLVER(resolver)); + + LOCK(&resolver->lock); + if (resolver->badcache == NULL) { + resolver->badcache = isc_mem_get(resolver->mctx, + sizeof(*resolver->badcache) * + DNS_BADCACHE_SIZE); + if (resolver->badcache == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + resolver->badhash = DNS_BADCACHE_SIZE; + memset(resolver->badcache, 0, sizeof(*resolver->badcache) * + resolver->badhash); + } + + result = isc_time_now(&now); + if (result != ISC_R_SUCCESS) + isc_time_settoepoch(&now); + hashval = dns_name_hash(name, ISC_FALSE); + i = hashval % resolver->badhash; + prev = NULL; + for (bad = resolver->badcache[i]; bad != NULL; bad = next) { + next = bad->next; + if (bad->type == type && dns_name_equal(name, &bad->name)) + break; + if (isc_time_compare(&bad->expire, &now) < 0) { + if (prev == NULL) + resolver->badcache[i] = bad->next; + else + prev->next = bad->next; + isc_mem_put(resolver->mctx, bad, sizeof(*bad) + + bad->name.length); + resolver->badcount--; + } else + prev = bad; + } + if (bad == NULL) { + isc_buffer_t buffer; + bad = isc_mem_get(resolver->mctx, sizeof(*bad) + name->length); + if (bad == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + bad->type = type; + bad->hashval = hashval; + isc_buffer_init(&buffer, bad + 1, name->length); + dns_name_init(&bad->name, NULL); + dns_name_copy(name, &bad->name, &buffer); + bad->next = resolver->badcache[i]; + resolver->badcache[i] = bad; + resolver->badcount++; + if (resolver->badcount > resolver->badhash * 8) + resizehash(resolver, &now, ISC_TRUE); + if (resolver->badcount < resolver->badhash * 2 && + resolver->badhash > DNS_BADCACHE_SIZE) + resizehash(resolver, &now, ISC_FALSE); + } + bad->expire = *expire; + cleanup: + UNLOCK(&resolver->lock); +} + +isc_boolean_t +dns_resolver_getbadcache(dns_resolver_t *resolver, dns_name_t *name, + dns_rdatatype_t type, isc_time_t *now) +{ + dns_badcache_t *bad, *prev, *next; + isc_boolean_t answer = ISC_FALSE; + unsigned int i; + + REQUIRE(VALID_RESOLVER(resolver)); + + LOCK(&resolver->lock); + if (resolver->badcache == NULL) + goto unlock; + + i = dns_name_hash(name, ISC_FALSE) % resolver->badhash; + prev = NULL; + for (bad = resolver->badcache[i]; bad != NULL; bad = next) { + next = bad->next; + /* + * Search the hash list. Clean out expired records as we go. + */ + if (isc_time_compare(&bad->expire, now) < 0) { + if (prev != NULL) + prev->next = bad->next; + else + resolver->badcache[i] = bad->next; + isc_mem_put(resolver->mctx, bad, sizeof(*bad) + + bad->name.length); + resolver->badcount--; + continue; + } + if (bad->type == type && dns_name_equal(name, &bad->name)) { + answer = ISC_TRUE; + break; + } + prev = bad; + } + + /* + * Slow sweep to clean out stale records. + */ + i = resolver->badsweep++ % resolver->badhash; + bad = resolver->badcache[i]; + if (bad != NULL && isc_time_compare(&bad->expire, now) < 0) { + resolver->badcache[i] = bad->next; + isc_mem_put(resolver->mctx, bad, sizeof(*bad) + + bad->name.length); + resolver->badcount--; + } + + unlock: + UNLOCK(&resolver->lock); + return (answer); +} + +void +dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp) { + char namebuf[DNS_NAME_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + dns_badcache_t *bad, *next, *prev; + isc_time_t now; + unsigned int i; + isc_uint64_t t; + + LOCK(&resolver->lock); + fprintf(fp, ";\n; Bad cache\n;\n"); + + if (resolver->badcache == NULL) + goto unlock; + + TIME_NOW(&now); + for (i = 0; i < resolver->badhash; i++) { + prev = NULL; + for (bad = resolver->badcache[i]; bad != NULL; bad = next) { + next = bad->next; + if (isc_time_compare(&bad->expire, &now) < 0) { + if (prev != NULL) + prev->next = bad->next; + else + resolver->badcache[i] = bad->next; + isc_mem_put(resolver->mctx, bad, sizeof(*bad) + + bad->name.length); + resolver->badcount--; + continue; + } + prev = bad; + dns_name_format(&bad->name, namebuf, sizeof(namebuf)); + dns_rdatatype_format(bad->type, typebuf, + sizeof(typebuf)); + t = isc_time_microdiff(&bad->expire, &now); + t /= 1000; + fprintf(fp, "; %s/%s [ttl " + "%" ISC_PLATFORM_QUADFORMAT "u]\n", + namebuf, typebuf, t); + } + } + + unlock: + UNLOCK(&resolver->lock); +} + static void free_algorithm(void *node, void *arg) { unsigned char *algorithms = node; diff --git a/contrib/bind9/lib/dns/result.c b/contrib/bind9/lib/dns/result.c index 54c70e0e9088..e3361975823b 100644 --- a/contrib/bind9/lib/dns/result.c +++ b/contrib/bind9/lib/dns/result.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008, 2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: result.c,v 1.125 2008/09/25 04:02:38 tbox Exp $ */ +/* $Id: result.c,v 1.125.122.2 2010/02/25 10:57:12 tbox Exp $ */ /*! \file */ @@ -157,6 +157,9 @@ static const char *text[DNS_R_NRESULTS] = { "MX is an address", /*%< 102 DNS_R_MXISADDRESS */ "duplicate query", /*%< 103 DNS_R_DUPLICATE */ "invalid NSEC3 owner name (wildcard)", /*%< 104 DNS_R_INVALIDNSEC3 */ + + "not master", /*%< 105 DNS_R_NOTMASTER */ + "broken trust chain", /*%< 106 DNS_R_BROKENCHAIN */ }; static const char *rcode_text[DNS_R_NRCODERESULTS] = { diff --git a/contrib/bind9/lib/dns/sdb.c b/contrib/bind9/lib/dns/sdb.c index 03fca9ed63e6..e0c8786b2130 100644 --- a/contrib/bind9/lib/dns/sdb.c +++ b/contrib/bind9/lib/dns/sdb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdb.c,v 1.66.48.2 2009/04/21 23:47:18 tbox Exp $ */ +/* $Id: sdb.c,v 1.66.48.3.8.2 2010/02/25 10:57:12 tbox Exp $ */ /*! \file */ @@ -1387,6 +1387,8 @@ static dns_rdatasetmethods_t methods = { NULL, NULL, NULL, + NULL, + NULL, NULL }; @@ -1458,9 +1460,11 @@ dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) { sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator; sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist); - while (sdbiter->current != NULL) + while (sdbiter->current != NULL) { if (dns_name_equal(sdbiter->current->name, name)) return (ISC_R_SUCCESS); + sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link); + } return (ISC_R_NOTFOUND); } diff --git a/contrib/bind9/lib/dns/sdlz.c b/contrib/bind9/lib/dns/sdlz.c index 89cd0eea2a70..caf71b5af7cf 100644 --- a/contrib/bind9/lib/dns/sdlz.c +++ b/contrib/bind9/lib/dns/sdlz.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2005-2009 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2005-2010 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -50,7 +50,7 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdlz.c,v 1.18.50.2 2009/04/21 23:47:18 tbox Exp $ */ +/* $Id: sdlz.c,v 1.18.50.3.8.2 2010/02/25 10:57:12 tbox Exp $ */ /*! \file */ @@ -1117,9 +1117,11 @@ dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) { sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist); - while (sdlziter->current != NULL) + while (sdlziter->current != NULL) { if (dns_name_equal(sdlziter->current->name, name)) return (ISC_R_SUCCESS); + sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link); + } return (ISC_R_NOTFOUND); } @@ -1209,6 +1211,8 @@ static dns_rdatasetmethods_t rdataset_methods = { NULL, NULL, NULL, + NULL, + NULL, NULL }; diff --git a/contrib/bind9/lib/dns/spnego.c b/contrib/bind9/lib/dns/spnego.c index 0ae6ea233c0a..6c94e51baeea 100644 --- a/contrib/bind9/lib/dns/spnego.c +++ b/contrib/bind9/lib/dns/spnego.c @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: spnego.c,v 1.8.118.2 2009/01/18 23:47:40 tbox Exp $ */ +/* $Id: spnego.c,v 1.8.118.4 2009/07/21 07:27:13 marka Exp $ */ /*! \file * \brief @@ -265,8 +265,7 @@ decode_oid(const unsigned char *p, size_t len, oid * k, size_t * size); static int -decode_enumerated(const unsigned char *p, size_t len, - unsigned *num, size_t *size); +decode_enumerated(const unsigned char *p, size_t len, void *num, size_t *size); static int decode_octet_string(const unsigned char *, size_t, octet_string *, size_t *); @@ -291,8 +290,7 @@ der_put_length_and_tag(unsigned char *, size_t, size_t, Der_class, Der_type, int, size_t *); static int -encode_enumerated(unsigned char *p, size_t len, - const unsigned *data, size_t *); +encode_enumerated(unsigned char *p, size_t len, const void *data, size_t *); static int encode_octet_string(unsigned char *p, size_t len, @@ -622,7 +620,7 @@ gss_accept_sec_context_spnego(OM_uint32 *minor_status, } for (i = 0; !found && i < init_token.mechTypes.len; ++i) { - char mechbuf[17]; + unsigned char mechbuf[17]; size_t mech_len; ret = der_put_oid(mechbuf + sizeof(mechbuf) - 1, @@ -956,8 +954,7 @@ der_match_tag_and_length(const unsigned char *p, size_t len, } static int -decode_enumerated(const unsigned char *p, size_t len, - unsigned *num, size_t *size) +decode_enumerated(const unsigned char *p, size_t len, void *num, size_t *size) { size_t ret = 0; size_t l, reallen; @@ -1269,10 +1266,9 @@ der_put_length_and_tag(unsigned char *p, size_t len, size_t len_val, } static int -encode_enumerated(unsigned char *p, size_t len, const unsigned *data, - size_t *size) +encode_enumerated(unsigned char *p, size_t len, const void *data, size_t *size) { - unsigned num = *data; + unsigned num = *(const unsigned *)data; size_t ret = 0; size_t l; int e; diff --git a/contrib/bind9/lib/dns/validator.c b/contrib/bind9/lib/dns/validator.c index ce49daf2eb10..0ccdc41980ce 100644 --- a/contrib/bind9/lib/dns/validator.c +++ b/contrib/bind9/lib/dns/validator.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: validator.c,v 1.164.12.9.8.2 2009/12/31 20:29:21 each Exp $ */ +/* $Id: validator.c,v 1.164.12.11.8.2 2010/02/25 10:57:12 tbox Exp $ */ #include <config.h> @@ -177,9 +177,16 @@ static inline void markanswer(dns_validator_t *val) { validator_log(val, ISC_LOG_DEBUG(3), "marking as answer"); if (val->event->rdataset != NULL) - val->event->rdataset->trust = dns_trust_answer; + dns_rdataset_settrust(val->event->rdataset, dns_trust_answer); if (val->event->sigrdataset != NULL) - val->event->sigrdataset->trust = dns_trust_answer; + dns_rdataset_settrust(val->event->sigrdataset, + dns_trust_answer); +} + +static inline void +marksecure(dns_validatorevent_t *event) { + dns_rdataset_settrust(event->rdataset, dns_trust_secure); + dns_rdataset_settrust(event->sigrdataset, dns_trust_secure); } static void @@ -425,7 +432,7 @@ fetch_callback_validator(isc_task_t *task, isc_event_t *event) { if (eresult == ISC_R_CANCELED) validator_done(val, eresult); else - validator_done(val, DNS_R_NOVALIDKEY); + validator_done(val, DNS_R_BROKENCHAIN); } want_destroy = exit_check(val); UNLOCK(&val->lock); @@ -495,7 +502,7 @@ dsfetched(isc_task_t *task, isc_event_t *event) { if (eresult == ISC_R_CANCELED) validator_done(val, eresult); else - validator_done(val, DNS_R_NOVALIDDS); + validator_done(val, DNS_R_BROKENCHAIN); } want_destroy = exit_check(val); UNLOCK(&val->lock); @@ -635,10 +642,16 @@ keyvalidated(isc_task_t *task, isc_event_t *event) { if (result != DNS_R_WAIT) validator_done(val, result); } else { + if (eresult != DNS_R_BROKENCHAIN) { + if (dns_rdataset_isassociated(&val->frdataset)) + dns_rdataset_expire(&val->frdataset); + if (dns_rdataset_isassociated(&val->fsigrdataset)) + dns_rdataset_expire(&val->fsigrdataset); + } validator_log(val, ISC_LOG_DEBUG(3), "keyvalidated: got %s", isc_result_totext(eresult)); - validator_done(val, eresult); + validator_done(val, DNS_R_BROKENCHAIN); } want_destroy = exit_check(val); UNLOCK(&val->lock); @@ -685,10 +698,16 @@ dsvalidated(isc_task_t *task, isc_event_t *event) { if (result != DNS_R_WAIT) validator_done(val, result); } else { + if (eresult != DNS_R_BROKENCHAIN) { + if (dns_rdataset_isassociated(&val->frdataset)) + dns_rdataset_expire(&val->frdataset); + if (dns_rdataset_isassociated(&val->fsigrdataset)) + dns_rdataset_expire(&val->fsigrdataset); + } validator_log(val, ISC_LOG_DEBUG(3), "dsvalidated: got %s", isc_result_totext(eresult)); - validator_done(val, eresult); + validator_done(val, DNS_R_BROKENCHAIN); } want_destroy = exit_check(val); UNLOCK(&val->lock); @@ -1199,6 +1218,8 @@ authvalidated(isc_task_t *task, isc_event_t *event) { validator_log(val, ISC_LOG_DEBUG(3), "authvalidated: got %s", isc_result_totext(result)); + if (result == DNS_R_BROKENCHAIN) + val->authfail++; if (result == ISC_R_CANCELED) validator_done(val, result); else { @@ -1271,6 +1292,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) { * \li DNS_R_NCACHENXRRSET * \li DNS_R_NXRRSET * \li DNS_R_NXDOMAIN + * \li DNS_R_BROKENCHAIN */ static inline isc_result_t view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) { @@ -1280,9 +1302,12 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) { dns_rdata_t rdata = DNS_RDATA_INIT; isc_result_t result; unsigned int options; + isc_time_t now; char buf1[DNS_NAME_FORMATSIZE]; char buf2[DNS_NAME_FORMATSIZE]; char buf3[DNS_NAME_FORMATSIZE]; + char namebuf[DNS_NAME_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; if (dns_rdataset_isassociated(&val->frdataset)) dns_rdataset_disassociate(&val->frdataset); @@ -1292,6 +1317,16 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) { if (val->view->zonetable == NULL) return (ISC_R_CANCELED); + if (isc_time_now(&now) == ISC_R_SUCCESS && + dns_resolver_getbadcache(val->view->resolver, name, type, &now)) { + + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_rdatatype_format(type, typebuf, sizeof(typebuf)); + validator_log(val, ISC_LOG_INFO, "bad cache hit (%s/%s)", + namebuf, typebuf); + return (DNS_R_BROKENCHAIN); + } + options = DNS_DBFIND_PENDINGOK; if (type == dns_rdatatype_dlv) options |= DNS_DBFIND_COVERINGNSEC; @@ -1300,6 +1335,7 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) { result = dns_view_find(val->view, name, type, 0, options, ISC_FALSE, NULL, NULL, foundname, &val->frdataset, &val->fsigrdataset); + if (result == DNS_R_NXDOMAIN) { if (dns_rdataset_isassociated(&val->frdataset)) dns_rdataset_disassociate(&val->frdataset); @@ -1656,7 +1692,8 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) { /* * We don't know anything about this key. */ - result = create_fetch(val, &siginfo->signer, dns_rdatatype_dnskey, + result = create_fetch(val, &siginfo->signer, + dns_rdatatype_dnskey, fetch_callback_validator, "get_key"); if (result != ISC_R_SUCCESS) return (result); @@ -1671,7 +1708,8 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) { * This key doesn't exist. */ result = DNS_R_CONTINUE; - } + } else if (result == DNS_R_BROKENCHAIN) + return (result); if (dns_rdataset_isassociated(&val->frdataset) && val->keyset != &val->frdataset) @@ -1919,8 +1957,7 @@ validate(dns_validator_t *val, isc_boolean_t resume) { "looking for noqname proof"); return (nsecvalidate(val, ISC_FALSE)); } else if (result == ISC_R_SUCCESS) { - event->rdataset->trust = dns_trust_secure; - event->sigrdataset->trust = dns_trust_secure; + marksecure(event); validator_log(val, ISC_LOG_DEBUG(3), "marking as secure"); return (result); @@ -2096,8 +2133,7 @@ dlv_validatezonekey(dns_validator_t *val) { "no RRSIG matching DLV key"); } if (result == ISC_R_SUCCESS) { - val->event->rdataset->trust = dns_trust_secure; - val->event->sigrdataset->trust = dns_trust_secure; + marksecure(val->event); validator_log(val, ISC_LOG_DEBUG(3), "marking as secure"); return (result); } else if (result == ISC_R_NOMORE && !supported_algorithm) { @@ -2198,8 +2234,7 @@ validatezonekey(dns_validator_t *val) { keynode = nextnode; } if (result == ISC_R_SUCCESS) { - event->rdataset->trust = dns_trust_secure; - event->sigrdataset->trust = dns_trust_secure; + marksecure(event); validator_log(val, ISC_LOG_DEBUG(3), "signed by trusted key; " "marking as secure"); @@ -2226,11 +2261,14 @@ validatezonekey(dns_validator_t *val) { */ dns_name_format(val->event->name, namebuf, sizeof(namebuf)); - validator_log(val, ISC_LOG_DEBUG(2), + validator_log(val, ISC_LOG_NOTICE, "unable to find a DNSKEY which verifies " "the DNSKEY RRset and also matches one " "of specified trusted-keys for '%s'", namebuf); + validator_log(val, ISC_LOG_NOTICE, + "please check the 'trusted-keys' for " + "'%s' in named.conf.", namebuf); return (DNS_R_NOVALIDKEY); } @@ -2291,7 +2329,8 @@ validatezonekey(dns_validator_t *val) { dns_rdataset_disassociate(&val->fsigrdataset); validator_log(val, ISC_LOG_DEBUG(2), "no DS record"); return (DNS_R_NOVALIDSIG); - } + } else if (result == DNS_R_BROKENCHAIN) + return (result); } /* @@ -2440,8 +2479,7 @@ validatezonekey(dns_validator_t *val) { "no RRSIG matching DS key"); } if (result == ISC_R_SUCCESS) { - event->rdataset->trust = dns_trust_secure; - event->sigrdataset->trust = dns_trust_secure; + marksecure(event); validator_log(val, ISC_LOG_DEBUG(3), "marking as secure"); return (result); } else if (result == ISC_R_NOMORE && !supported_algorithm) { @@ -2844,6 +2882,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) { "nsecvalidate"); if (result != ISC_R_SUCCESS) return (result); + val->authcount++; return (DNS_R_WAIT); } @@ -2868,8 +2907,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) { "noqname proof found"); validator_log(val, ISC_LOG_DEBUG(3), "marking as secure"); - val->event->rdataset->trust = dns_trust_secure; - val->event->sigrdataset->trust = dns_trust_secure; + marksecure(val->event); return (ISC_R_SUCCESS); } else if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0 && dns_name_countlabels(dns_fixedname_name(&val->wild)) @@ -2923,6 +2961,8 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) { } findnsec3proofs(val); + if (val->authcount == val->authfail) + return (DNS_R_BROKENCHAIN); validator_log(val, ISC_LOG_DEBUG(3), "nonexistence proof(s) not found"); val->attributes |= VALATTR_INSECURITY; @@ -2954,6 +2994,58 @@ check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) { return (ISC_FALSE); } +static void +dlvvalidated(isc_task_t *task, isc_event_t *event) { + dns_validatorevent_t *devent; + dns_validator_t *val; + isc_result_t eresult; + isc_boolean_t want_destroy; + + UNUSED(task); + INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE); + + devent = (dns_validatorevent_t *)event; + val = devent->ev_arg; + eresult = devent->result; + + isc_event_free(&event); + dns_validator_destroy(&val->subvalidator); + + INSIST(val->event != NULL); + + validator_log(val, ISC_LOG_DEBUG(3), "in dlvvalidated"); + LOCK(&val->lock); + if (CANCELED(val)) { + validator_done(val, ISC_R_CANCELED); + } else if (eresult == ISC_R_SUCCESS) { + validator_log(val, ISC_LOG_DEBUG(3), + "dlvset with trust %d", val->frdataset.trust); + dns_rdataset_clone(&val->frdataset, &val->dlv); + val->havedlvsep = ISC_TRUE; + if (dlv_algorithm_supported(val)) + dlv_validator_start(val); + else { + markanswer(val); + validator_done(val, ISC_R_SUCCESS); + } + } else { + if (eresult != DNS_R_BROKENCHAIN) { + if (dns_rdataset_isassociated(&val->frdataset)) + dns_rdataset_expire(&val->frdataset); + if (dns_rdataset_isassociated(&val->fsigrdataset)) + dns_rdataset_expire(&val->fsigrdataset); + } + validator_log(val, ISC_LOG_DEBUG(3), + "dlvvalidated: got %s", + isc_result_totext(eresult)); + validator_done(val, DNS_R_BROKENCHAIN); + } + want_destroy = exit_check(val); + UNLOCK(&val->lock); + if (want_destroy) + destroy(val); +} + /*% * Callback from fetching a DLV record. * @@ -3173,6 +3265,24 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) { namebuf); result = view_find(val, dlvname, dns_rdatatype_dlv); if (result == ISC_R_SUCCESS) { + if (DNS_TRUST_PENDING(val->frdataset.trust) && + dns_rdataset_isassociated(&val->fsigrdataset)) + { + dns_fixedname_init(&val->fname); + dns_name_copy(dlvname, + dns_fixedname_name(&val->fname), + NULL); + result = create_validator(val, + dns_fixedname_name(&val->fname), + dns_rdatatype_dlv, + &val->frdataset, + &val->fsigrdataset, + dlvvalidated, + "finddlvsep"); + if (result != ISC_R_SUCCESS) + return (result); + return (DNS_R_WAIT); + } if (val->frdataset.trust < dns_trust_secure) return (DNS_R_NOVALIDSIG); val->havedlvsep = ISC_TRUE; @@ -3223,6 +3333,7 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) { * \li DNS_R_NOVALIDSIG * \li DNS_R_NOVALIDNSEC * \li DNS_R_NOTINSECURE + * \li DNS_R_BROKENCHAIN */ static isc_result_t proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) @@ -3465,7 +3576,8 @@ proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume) if (result != ISC_R_SUCCESS) goto out; return (DNS_R_WAIT); - } + } else if (result == DNS_R_BROKENCHAIN) + return (result); } /* @@ -3682,6 +3794,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, val->seensig = ISC_FALSE; val->havedlvsep = ISC_FALSE; val->depth = 0; + val->authcount = 0; + val->authfail = 0; val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name); dns_rdataset_init(&val->frdataset); dns_rdataset_init(&val->fsigrdataset); diff --git a/contrib/bind9/lib/dns/view.c b/contrib/bind9/lib/dns/view.c index 5f1447ae06ed..72163b4ab896 100644 --- a/contrib/bind9/lib/dns/view.c +++ b/contrib/bind9/lib/dns/view.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.c,v 1.150.84.2 2009/01/29 23:47:44 tbox Exp $ */ +/* $Id: view.c,v 1.150.84.3.8.2 2010/02/25 10:57:12 tbox Exp $ */ /*! \file */ @@ -1250,7 +1250,8 @@ dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr, if (result != ISC_R_SUCCESS) return (result); - return (dns_view_gettsig(view, keyname, keyp)); + result = dns_view_gettsig(view, keyname, keyp); + return ((result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result); } isc_result_t @@ -1270,10 +1271,11 @@ dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) { (void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name); result = dns_master_dumptostream(view->mctx, view->cachedb, NULL, - &dns_master_style_cache, fp); + &dns_master_style_cache, fp); if (result != ISC_R_SUCCESS) return (result); dns_adb_dump(view->adb, fp); + dns_resolver_printbadcache(view->resolver, fp); return (ISC_R_SUCCESS); } @@ -1294,6 +1296,8 @@ dns_view_flushcache(dns_view_t *view) { dns_cache_attachdb(view->cache, &view->cachedb); if (view->acache != NULL) dns_acache_setdb(view->acache, view->cachedb); + if (view->resolver != NULL) + dns_resolver_flushbadcache(view->resolver, NULL); dns_adb_flush(view->adb); return (ISC_R_SUCCESS); @@ -1308,6 +1312,8 @@ dns_view_flushname(dns_view_t *view, dns_name_t *name) { dns_adb_flushname(view->adb, name); if (view->cache == NULL) return (ISC_R_SUCCESS); + if (view->resolver != NULL) + dns_resolver_flushbadcache(view->resolver, name); return (dns_cache_flushname(view->cache, name)); } diff --git a/contrib/bind9/lib/dns/zone.c b/contrib/bind9/lib/dns/zone.c index 423b00578720..c21b1f05b118 100644 --- a/contrib/bind9/lib/dns/zone.c +++ b/contrib/bind9/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.483.36.6 2009/03/26 22:57:07 marka Exp $ */ +/* $Id: zone.c,v 1.483.36.17 2009/12/21 04:32:42 marka Exp $ */ /*! \file */ @@ -200,7 +200,6 @@ struct dns_zone { isc_time_t keywarntime; isc_time_t signingtime; isc_time_t nsec3chaintime; - isc_uint32_t serial; isc_uint32_t refresh; isc_uint32_t retry; isc_uint32_t expire; @@ -351,11 +350,15 @@ struct dns_zone { #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U +#define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */ +#define DNS_ZONEFLG_THAW 0x08000000U #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0) /* Flags for zone_load() */ #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */ +#define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful + load. */ #define UNREACH_CHACHE_SIZE 10U #define UNREACH_HOLD_TIME 600 /* 10 minutes */ @@ -718,7 +721,6 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { isc_time_settoepoch(&zone->keywarntime); isc_time_settoepoch(&zone->signingtime); isc_time_settoepoch(&zone->nsec3chaintime); - zone->serial = 0; zone->refresh = DNS_ZONE_DEFAULTREFRESH; zone->retry = DNS_ZONE_DEFAULTRETRY; zone->expire = 0; @@ -967,16 +969,35 @@ dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) { UNLOCK_ZONE(zone); } -isc_uint32_t -dns_zone_getserial(dns_zone_t *zone) { - isc_uint32_t serial; +isc_result_t +dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) { + isc_result_t result; REQUIRE(DNS_ZONE_VALID(zone)); + REQUIRE(serialp != NULL); LOCK_ZONE(zone); - serial = zone->serial; + ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->db != NULL) { + result = zone_get_from_db(zone, zone->db, NULL, NULL, serialp, + NULL, NULL, NULL, NULL, NULL); + } else + result = DNS_R_NOTLOADED; + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); UNLOCK_ZONE(zone); + return (result); +} + +isc_uint32_t +dns_zone_getserial(dns_zone_t *zone) { + isc_result_t result; + isc_uint32_t serial; + + result = dns_zone_getserial2(zone, &serial); + if (result != ISC_R_SUCCESS) + serial = 0; /* XXX: not really correct, but no other choice */ + return (serial); } @@ -1314,7 +1335,9 @@ zone_load(dns_zone_t *zone, unsigned int flags) { INSIST(zone->type != dns_zone_none); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) { - result = ISC_R_SUCCESS; + if ((flags & DNS_ZONELOADFLAG_THAW) != 0) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW); + result = DNS_R_CONTINUE; goto cleanup; } @@ -1448,6 +1471,8 @@ zone_load(dns_zone_t *zone, unsigned int flags) { if (result == DNS_R_CONTINUE) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING); + if ((flags & DNS_ZONELOADFLAG_THAW) != 0) + DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW); goto cleanup; } @@ -1470,6 +1495,30 @@ dns_zone_loadnew(dns_zone_t *zone) { return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT)); } +isc_result_t +dns_zone_loadandthaw(dns_zone_t *zone) { + isc_result_t result; + + result = zone_load(zone, DNS_ZONELOADFLAG_THAW); + switch (result) { + case DNS_R_CONTINUE: + /* Deferred thaw. */ + break; + case ISC_R_SUCCESS: + case DNS_R_UPTODATE: + case DNS_R_SEENINCLUDE: + zone->update_disabled = ISC_FALSE; + break; + case DNS_R_NOMASTERFILE: + zone->update_disabled = ISC_FALSE; + break; + default: + /* Error, remain in disabled state. */ + break; + } + return (result); +} + static unsigned int get_master_options(dns_zone_t *zone) { unsigned int options; @@ -2148,7 +2197,8 @@ resume_signingwithkey(dns_zone_t *zone) { } result = zone_signwithkey(zone, rdata.data[0], - (rdata.data[1] << 8) | rdata.data[2], ISC_TF(rdata.data[3])); + (rdata.data[1] << 8) | rdata.data[2], + ISC_TF(rdata.data[3])); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "zone_signwithkey failed: %s", @@ -2291,7 +2341,6 @@ static void set_resigntime(dns_zone_t *zone) { dns_rdataset_t rdataset; dns_fixedname_t fixed; - char namebuf[DNS_NAME_FORMATSIZE]; unsigned int resign; isc_result_t result; isc_uint32_t nanosecs; @@ -2305,7 +2354,6 @@ set_resigntime(dns_zone_t *zone) { return; } resign = rdataset.resign; - dns_name_format(dns_fixedname_name(&fixed), namebuf, sizeof(namebuf)); dns_rdataset_disassociate(&rdataset); isc_random_get(&nanosecs); nanosecs %= 1000000000; @@ -2409,7 +2457,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, unsigned int soacount = 0; unsigned int nscount = 0; unsigned int errors = 0; - isc_uint32_t serial, refresh, retry, expire, minimum; + isc_uint32_t serial, oldserial, refresh, retry, expire, minimum; isc_time_t now; isc_boolean_t needdump = ISC_FALSE; isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE); @@ -2463,8 +2511,9 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, options = DNS_JOURNALOPT_RESIGN; else options = 0; - result = dns_journal_rollforward(zone->mctx, db, options, - zone->journal); + result = dns_journal_rollforward2(zone->mctx, db, options, + zone->sigresigninginterval, + zone->journal); if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND && result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL && result != ISC_R_RANGE) { @@ -2544,14 +2593,18 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, * This is checked in zone_replacedb() for slave zones * as they don't reload from disk. */ + result = zone_get_from_db(zone, zone->db, NULL, NULL, + &oldserial, NULL, NULL, NULL, + NULL, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) && - !isc_serial_gt(serial, zone->serial)) { + !isc_serial_gt(serial, oldserial)) { isc_uint32_t serialmin, serialmax; INSIST(zone->type == dns_zone_master); - serialmin = (zone->serial + 1) & 0xffffffffU; - serialmax = (zone->serial + 0x7fffffffU) & + serialmin = (oldserial + 1) & 0xffffffffU; + serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU; dns_zone_log(zone, ISC_LOG_ERROR, "ixfr-from-differences: " @@ -2560,10 +2613,10 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, serialmax); result = DNS_R_BADZONE; goto cleanup; - } else if (!isc_serial_ge(serial, zone->serial)) + } else if (!isc_serial_ge(serial, oldserial)) dns_zone_log(zone, ISC_LOG_ERROR, "zone serial has gone backwards"); - else if (serial == zone->serial && !hasinclude) + else if (serial == oldserial && !hasinclude) dns_zone_log(zone, ISC_LOG_ERROR, "zone serial unchanged. " "zone may fail to transfer " @@ -2580,7 +2633,6 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, "3 * refresh."); } - zone->serial = serial; zone->refresh = RANGE(refresh, zone->minrefresh, zone->maxrefresh); zone->retry = RANGE(retry, @@ -2664,8 +2716,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, } if (! dns_db_ispersistent(db)) - dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", - zone->serial, + dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial, dns_db_issecure(db) ? " (signed)" : ""); return (result); @@ -2683,7 +2734,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, if (zone->task != NULL) zone_settimer(zone, &now); result = ISC_R_SUCCESS; - } + } else if (zone->type == dns_zone_master) + dns_zone_log(zone, ISC_LOG_ERROR, "not loaded due to errors."); return (result); } @@ -4374,7 +4426,8 @@ updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version, seen_done = ISC_TRUE; else CHECK(update_one_rr(signing->db, version, diff, - DNS_DIFFOP_DEL, name, rdataset.ttl, &rdata)); + DNS_DIFFOP_DEL, name, + rdataset.ttl, &rdata)); dns_rdata_reset(&rdata); } if (result == ISC_R_NOMORE) @@ -5458,6 +5511,7 @@ zone_sign(dns_zone_t *zone) { dst_key_t *zone_keys[MAXZONEKEYS]; isc_int32_t signatures; isc_boolean_t check_ksk, is_ksk; + isc_boolean_t commit = ISC_FALSE; isc_boolean_t delegation; isc_boolean_t finishedakey = ISC_FALSE; isc_boolean_t secureupdated = ISC_FALSE; @@ -5745,6 +5799,7 @@ zone_sign(dns_zone_t *zone) { goto failure; } } + if (finishedakey) { /* * We have changed the RRset above so we need to update @@ -5770,6 +5825,15 @@ zone_sign(dns_zone_t *zone) { goto failure; } } + + /* + * Have we changed anything? + */ + if (ISC_LIST_HEAD(sig_diff.tuples) == NULL) + goto pauseall; + + commit = ISC_TRUE; + result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa, &sig_diff, zone_keys, nkeys, now); if (result != ISC_R_SUCCESS) { @@ -5801,6 +5865,9 @@ zone_sign(dns_zone_t *zone) { goto failure; } + /* + * Write changes to journal file. + */ journalfile = dns_zone_getjournal(zone); if (journalfile != NULL) { dns_journal_t *journal = NULL; @@ -5823,7 +5890,7 @@ zone_sign(dns_zone_t *zone) { } } - + pauseall: /* * Pause all iterators so that dns_db_closeversion() can succeed. */ @@ -5840,7 +5907,7 @@ zone_sign(dns_zone_t *zone) { /* * Everything has succeeded. Commit the changes. */ - dns_db_closeversion(db, &version, ISC_TRUE); + dns_db_closeversion(db, &version, commit); /* * Everything succeeded so we can clean these up now. @@ -5856,9 +5923,11 @@ zone_sign(dns_zone_t *zone) { set_resigntime(zone); - LOCK_ZONE(zone); - zone_needdump(zone, DNS_DUMP_DELAY); - UNLOCK_ZONE(zone); + if (commit) { + LOCK_ZONE(zone); + zone_needdump(zone, DNS_DUMP_DELAY); + UNLOCK_ZONE(zone); + } failure: /* @@ -6498,6 +6567,7 @@ notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) { isc_sockaddr_t any; isc_boolean_t isself; isc_netaddr_t dstaddr; + isc_result_t result; if (zone->view == NULL || zone->isself == NULL) return (ISC_FALSE); @@ -6523,7 +6593,9 @@ notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) { src = *dst; isc_netaddr_fromsockaddr(&dstaddr, dst); - (void)dns_view_getpeertsig(zone->view, &dstaddr, &key); + result = dns_view_getpeertsig(zone->view, &dstaddr, &key); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) + return (ISC_FALSE); isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass, zone->isselfarg); if (key != NULL) @@ -6725,9 +6797,14 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) { goto cleanup; isc_netaddr_fromsockaddr(&dstip, ¬ify->dst); - (void)dns_view_getpeertsig(notify->zone->view, &dstip, &key); - isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf)); + result = dns_view_getpeertsig(notify->zone->view, &dstip, &key); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { + notify_log(notify->zone, ISC_LOG_ERROR, "NOTIFY to %s not " + "sent. Peer TSIG key lookup failure.", addrbuf); + goto cleanup_message; + } + notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s", addrbuf); if (notify->zone->view->peers != NULL) { @@ -6774,6 +6851,7 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) { cleanup_key: if (key != NULL) dns_tsigkey_detach(&key); + cleanup_message: dns_message_destroy(&message); cleanup: UNLOCK_ZONE(notify->zone); @@ -7386,7 +7464,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_soa_t soa; isc_result_t result; - isc_uint32_t serial; + isc_uint32_t serial, oldserial; unsigned int j; zone = revent->ev_arg; @@ -7609,12 +7687,17 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { RUNTIME_CHECK(result == ISC_R_SUCCESS); serial = soa.serial; - - zone_debuglog(zone, me, 1, "serial: new %u, old %u", - serial, zone->serial); + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { + result = dns_zone_getserial2(zone, &oldserial); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + zone_debuglog(zone, me, 1, "serial: new %u, old %u", + serial, oldserial); + } else + zone_debuglog(zone, me, 1, "serial: new %u, old not loaded", + serial); if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) || DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) || - isc_serial_gt(serial, zone->serial)) { + isc_serial_gt(serial, oldserial)) { if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr, &zone->sourceaddr, &now)) { dns_zone_log(zone, ISC_LOG_INFO, @@ -7638,7 +7721,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { } if (msg != NULL) dns_message_destroy(&msg); - } else if (isc_serial_eq(soa.serial, zone->serial)) { + } else if (isc_serial_eq(soa.serial, oldserial)) { if (zone->masterfile != NULL) { result = ISC_R_FAILURE; if (zone->journal != NULL) @@ -7671,7 +7754,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) " "received from master %s < ours (%u)", - soa.serial, master, zone->serial); + soa.serial, master, oldserial); else zone_debuglog(zone, me, 1, "ahead"); zone->mastersok[zone->curmaster] = ISC_TRUE; @@ -7965,10 +8048,19 @@ soa_query(isc_task_t *task, isc_event_t *event) { dns_name_format(keyname, namebuf, sizeof(namebuf)); dns_zone_log(zone, ISC_LOG_ERROR, "unable to find key: %s", namebuf); + goto skip_master; + } + } + if (key == NULL) { + result = dns_view_getpeertsig(zone->view, &masterip, &key); + if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { + char addrbuf[ISC_NETADDR_FORMATSIZE]; + isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf)); + dns_zone_log(zone, ISC_LOG_ERROR, + "unable to find TSIG key for %s", addrbuf); + goto skip_master; } } - if (key == NULL) - (void)dns_view_getpeertsig(zone->view, &masterip, &key); have_xfrsource = ISC_FALSE; reqnsid = zone->view->requestnsid; @@ -8789,13 +8881,21 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, if (result == ISC_R_SUCCESS) result = dns_rdataset_first(rdataset); if (result == ISC_R_SUCCESS) { - isc_uint32_t serial = 0; + isc_uint32_t serial = 0, oldserial; dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &soa, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); serial = soa.serial; - if (isc_serial_le(serial, zone->serial)) { + /* + * The following should safely be performed without DB + * lock and succeed in this context. + */ + result = zone_get_from_db(zone, zone->db, NULL, NULL, + &oldserial, NULL, NULL, NULL, + NULL, NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + if (isc_serial_le(serial, oldserial)) { dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: " "zone is up to date", @@ -9473,7 +9573,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { if (zone->db != NULL && zone->journal != NULL && DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { - isc_uint32_t serial; + isc_uint32_t serial, oldserial; dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs"); @@ -9488,11 +9588,15 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { /* * This is checked in zone_postload() for master zones. */ + result = zone_get_from_db(zone, zone->db, NULL, NULL, + &oldserial, NULL, NULL, NULL, NULL, + NULL); + RUNTIME_CHECK(result == ISC_R_SUCCESS); if (zone->type == dns_zone_slave && - !isc_serial_gt(serial, zone->serial)) { + !isc_serial_gt(serial, oldserial)) { isc_uint32_t serialmin, serialmax; - serialmin = (zone->serial + 1) & 0xffffffffU; - serialmax = (zone->serial + 0x7fffffffU) & 0xffffffffU; + serialmin = (oldserial + 1) & 0xffffffffU; + serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU; dns_zone_log(zone, ISC_LOG_ERROR, "ixfr-from-differences: failed: " "new serial (%u) out of range [%u - %u]", @@ -9685,7 +9789,6 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { zone_unload(zone); goto next_master; } - zone->serial = serial; zone->refresh = RANGE(refresh, zone->minrefresh, zone->maxrefresh); zone->retry = RANGE(retry, zone->minretry, @@ -9723,7 +9826,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) { buf[0] = '\0'; dns_zone_log(zone, ISC_LOG_INFO, "transferred serial %u%s", - zone->serial, buf); + serial, buf); } /* @@ -9873,6 +9976,13 @@ zone_loaddone(void *arg, isc_result_t result) { (void)zone_postload(load->zone, load->db, load->loadtime, result); zonemgr_putio(&load->zone->readio); DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING); + /* + * Leave the zone frozen if the reload fails. + */ + if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) && + DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW)) + zone->update_disabled = ISC_FALSE; + DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW); UNLOCK_ZONE(load->zone); load->magic = 0; @@ -11508,7 +11618,8 @@ zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid, cleanup: if (signing != NULL) { - dns_db_detach(&signing->db); + if (signing->db != NULL) + dns_db_detach(&signing->db); if (signing->dbiterator != NULL) dns_dbiterator_destroy(&signing->dbiterator); isc_mem_put(zone->mctx, signing, sizeof *signing); |
