diff --git a/Changes.md b/Changes.md new file mode 100644 index 0000000000000000000000000000000000000000..66610342d0e94a868595068956b0ee20c31af0d9 --- /dev/null +++ b/Changes.md @@ -0,0 +1,43 @@ +# Significant Changes in BIND9 package + +## BIND 9.16 + +### New features + +- *libuv* is used for network subsystem as a mandatory dependency +- *dnssec-policy* support in named.conf is introduced, providing a a key and signing policy + ([KASP](https://gitlab.isc.org/isc-projects/bind9/-/wikis/DNSSEC-Key-and-Signing-Policy-(KASP))) +- *trusted-keys* and *managed-keys* are deprecated, replaced by *trust-anchors* +- *trust-anchors* support also anchor in a *DS* format, in addition to *DNSKEY* format +- **dig, mdig** and **delv** support **+yaml** parameter to print detailed machine parseable output + +### Feature changes + +- Static trust anchor and *dnssec-validation auto;* are incompatible and cause fatal error, when used together. +- *DS* and *CDS* now generates only SHA-256 digest, SHA-1 is no longer generated by default +- SipHash 2-4 DNS Cookie ([RFC 7873](https://www.rfc-editor.org/rfc/rfc7873.html) is now default). + Only AES alternative algorithm is kept, HMAC-SHA cookie support were removed. +- **dnssec-signzone** and **dnssec-verify** commands print output to stdout, *-q* parameter can silence them + +### Features removed + +- *dnssec-enable* option is obsolete, DNSSEC support is always enabled +- *dnssec-lookaside* option is deprecated and support for it removed from all tools +- *cleaning-interval* option is removed + +### Upstream release notes + +- [9.16.10 notes](https://downloads.isc.org/isc/bind9/9.16.10/doc/arm/html/notes.html#notes-for-bind-9-16-10) +- [9.16.0 notes](https://downloads.isc.org/isc/bind9/9.16.0/doc/arm/html/notes.html#notes-for-bind-9-16-0) + +## BIND 9.14 + +- single thread support removed. Cannot provide *bind-export-libs* for DHCP +- *lwres* support completely removed. Both daemon and library +- common parts of daemon moved into *libns* shared library +- introduced plugin for filtering aaaa responses +- some SDB utilities no longer supported + +### Upstream release notes + +- [9.14.7 notes](https://downloads.isc.org/isc/bind9/9.14.7/RELEASE-NOTES-bind-9.14.7.html) diff --git a/backport-CVE-2023-4408.patch b/backport-CVE-2023-4408.patch new file mode 100644 index 0000000000000000000000000000000000000000..d1d3971501f792e40875319942c9cb63b7ed1851 --- /dev/null +++ b/backport-CVE-2023-4408.patch @@ -0,0 +1,901 @@ +From 608707b4f5b473e416563bfe0d43e26d6dc4a5c6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Mon, 11 Sep 2023 10:35:28 +0200 +Subject: [PATCH] Use hashtable when parsing a message + +When parsing messages use a hashtable instead of a linear search to +reduce the amount of work done in findname when there's more than one +name in the section. + +There are two hashtables: + +1) hashtable for owner names - that's constructed for each section when +we hit the second name in the section and destroyed right after parsing +that section; + +2) per-name hashtable - for each name in the section, we construct a new +hashtable for that name if there are more than one rdataset for that +particular name. + +Conflict:NA +Reference:https://downloads.isc.org/isc/bind/9.18.24/patches/0001-CVE-2023-4408.patch + +(cherry picked from commit b8a96317544c7b310b4f74360825a87b6402ddc2) + +--- + lib/dns/include/dns/message.h | 38 ---- + lib/dns/include/dns/name.h | 37 ++-- + lib/dns/message.c | 374 ++++++++++++++++++++++------------ + lib/dns/name.c | 1 + + lib/isc/ht.c | 55 ++++- + 5 files changed, 309 insertions(+), 196 deletions(-) + +diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h +index 940c9b1..f15884a 100644 +--- a/lib/dns/include/dns/message.h ++++ b/lib/dns/include/dns/message.h +@@ -856,44 +856,6 @@ dns_message_findtype(const dns_name_t *name, dns_rdatatype_t type, + *\li #ISC_R_NOTFOUND -- the desired type does not exist. + */ + +-isc_result_t +-dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass, +- dns_rdatatype_t type, dns_rdatatype_t covers, +- dns_rdataset_t **rdataset); +-/*%< +- * Search the name for the specified rdclass and type. If it is found, +- * *rdataset is filled in with a pointer to that rdataset. +- * +- * Requires: +- *\li if '**rdataset' is non-NULL, *rdataset needs to be NULL. +- * +- *\li 'type' be a valid type, and NOT dns_rdatatype_any. +- * +- *\li If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type. +- * Otherwise it should be 0. +- * +- * Returns: +- *\li #ISC_R_SUCCESS -- all is well. +- *\li #ISC_R_NOTFOUND -- the desired type does not exist. +- */ +- +-void +-dns_message_movename(dns_message_t *msg, dns_name_t *name, +- dns_section_t fromsection, dns_section_t tosection); +-/*%< +- * Move a name from one section to another. +- * +- * Requires: +- * +- *\li 'msg' be valid. +- * +- *\li 'name' must be a name already in 'fromsection'. +- * +- *\li 'fromsection' must be a valid section. +- * +- *\li 'tosection' must be a valid section. +- */ +- + void + dns_message_addname(dns_message_t *msg, dns_name_t *name, + dns_section_t section); +diff --git a/lib/dns/include/dns/name.h b/lib/dns/include/dns/name.h +index a758c4d..199856a 100644 +--- a/lib/dns/include/dns/name.h ++++ b/lib/dns/include/dns/name.h +@@ -68,6 +68,7 @@ + #include + #include + ++#include + #include + #include + #include /* Required for storage size of dns_label_t. */ +@@ -111,6 +112,7 @@ struct dns_name { + isc_buffer_t *buffer; + ISC_LINK(dns_name_t) link; + ISC_LIST(dns_rdataset_t) list; ++ isc_ht_t *ht; + }; + + #define DNS_NAME_MAGIC ISC_MAGIC('D', 'N', 'S', 'n') +@@ -166,30 +168,24 @@ extern const dns_name_t *dns_wildcardname; + * unsigned char offsets[] = { 0, 6 }; + * dns_name_t value = DNS_NAME_INITABSOLUTE(data, offsets); + */ +-#define DNS_NAME_INITNONABSOLUTE(A, B) \ +- { \ +- DNS_NAME_MAGIC, A, (sizeof(A) - 1), sizeof(B), \ +- DNS_NAMEATTR_READONLY, B, NULL, \ +- { (void *)-1, (void *)-1 }, { \ +- NULL, NULL \ +- } \ ++#define DNS_NAME_INITNONABSOLUTE(A, B) \ ++ { \ ++ DNS_NAME_MAGIC, A, (sizeof(A) - 1), sizeof(B), \ ++ DNS_NAMEATTR_READONLY, B, NULL, \ ++ { (void *)-1, (void *)-1 }, { NULL, NULL }, NULL \ + } + +-#define DNS_NAME_INITABSOLUTE(A, B) \ +- { \ +- DNS_NAME_MAGIC, A, sizeof(A), sizeof(B), \ +- DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, B, \ +- NULL, { (void *)-1, (void *)-1 }, { \ +- NULL, NULL \ +- } \ ++#define DNS_NAME_INITABSOLUTE(A, B) \ ++ { \ ++ DNS_NAME_MAGIC, A, sizeof(A), sizeof(B), \ ++ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, B, \ ++ NULL, { (void *)-1, (void *)-1 }, { NULL, NULL }, NULL \ + } + +-#define DNS_NAME_INITEMPTY \ +- { \ +- DNS_NAME_MAGIC, NULL, 0, 0, 0, NULL, NULL, \ +- { (void *)-1, (void *)-1 }, { \ +- NULL, NULL \ +- } \ ++#define DNS_NAME_INITEMPTY \ ++ { \ ++ DNS_NAME_MAGIC, NULL, 0, 0, 0, NULL, NULL, \ ++ { (void *)-1, (void *)-1 }, { NULL, NULL }, NULL \ + } + + /*% +@@ -1330,6 +1326,7 @@ ISC_LANG_ENDDECLS + _n->buffer = NULL; \ + ISC_LINK_INIT(_n, link); \ + ISC_LIST_INIT(_n->list); \ ++ _n->ht = NULL; \ + } while (0) + + #define DNS_NAME_RESET(n) \ +diff --git a/lib/dns/message.c b/lib/dns/message.c +index 761a8e1..8654e92 100644 +--- a/lib/dns/message.c ++++ b/lib/dns/message.c +@@ -22,6 +22,8 @@ + #include + + #include ++#include ++#include + #include + #include + #include +@@ -493,9 +495,11 @@ msgresetsigs(dns_message_t *msg, bool replying) { + } else { + dns_rdataset_disassociate(msg->tsig); + isc_mempool_put(msg->rdspool, msg->tsig); ++ msg->tsig = NULL; + if (msg->querytsig != NULL) { + dns_rdataset_disassociate(msg->querytsig); + isc_mempool_put(msg->rdspool, msg->querytsig); ++ msg->querytsig = NULL; + } + } + dns_message_puttempname(msg, &msg->tsigname); +@@ -790,6 +794,18 @@ dns_message_detach(dns_message_t **messagep) { + } + } + ++static isc_result_t ++name_hash_add(isc_ht_t *ht, dns_name_t *name, dns_name_t **foundp) { ++ isc_result_t result = isc_ht_find(ht, name->ndata, name->length, ++ (void **)foundp); ++ if (result == ISC_R_SUCCESS) { ++ return (ISC_R_EXISTS); ++ } ++ result = isc_ht_add(ht, name->ndata, name->length, (void *)name); ++ INSIST(result == ISC_R_SUCCESS); ++ return (ISC_R_SUCCESS); ++} ++ + static isc_result_t + findname(dns_name_t **foundname, const dns_name_t *target, + dns_namelist_t *section) { +@@ -809,29 +825,26 @@ findname(dns_name_t **foundname, const dns_name_t *target, + return (ISC_R_NOTFOUND); + } + +-isc_result_t +-dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass, +- dns_rdatatype_t type, dns_rdatatype_t covers, +- dns_rdataset_t **rdataset) { +- dns_rdataset_t *curr; +- +- REQUIRE(name != NULL); +- REQUIRE(rdataset == NULL || *rdataset == NULL); +- +- for (curr = ISC_LIST_TAIL(name->list); curr != NULL; +- curr = ISC_LIST_PREV(curr, link)) +- { +- if (curr->rdclass == rdclass && curr->type == type && +- curr->covers == covers) +- { +- if (rdataset != NULL) { +- *rdataset = curr; +- } +- return (ISC_R_SUCCESS); +- } +- } ++typedef struct __attribute__((__packed__)) rds_key { ++ dns_rdataclass_t rdclass; ++ dns_rdatatype_t type; ++ dns_rdatatype_t covers; ++} rds_key_t; + +- return (ISC_R_NOTFOUND); ++static isc_result_t ++rds_hash_add(isc_ht_t *ht, dns_rdataset_t *rds, dns_rdataset_t **foundp) { ++ rds_key_t key = { .rdclass = rds->rdclass, ++ .type = rds->type, ++ .covers = rds->covers }; ++ isc_result_t result = isc_ht_find(ht, (const unsigned char *)&key, ++ sizeof(key), (void **)foundp); ++ if (result == ISC_R_SUCCESS) { ++ return (ISC_R_EXISTS); ++ } ++ result = isc_ht_add(ht, (const unsigned char *)&key, sizeof(key), ++ (void *)rds); ++ INSIST(result == ISC_R_SUCCESS); ++ return (ISC_R_SUCCESS); + } + + isc_result_t +@@ -958,6 +971,18 @@ getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + } \ + } while (0) + ++static void ++cleanup_name_hashmaps(dns_namelist_t *section) { ++ dns_name_t *name = NULL; ++ for (name = ISC_LIST_HEAD(*section); name != NULL; ++ name = ISC_LIST_NEXT(name, link)) ++ { ++ if (name->ht != NULL) { ++ isc_ht_destroy(&name->ht); ++ } ++ } ++} ++ + static isc_result_t + getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + unsigned int options) { +@@ -967,13 +992,19 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + dns_name_t *name2 = NULL; + dns_rdataset_t *rdataset = NULL; + dns_rdatalist_t *rdatalist = NULL; +- isc_result_t result; ++ isc_result_t result = ISC_R_SUCCESS; + dns_rdatatype_t rdtype; + dns_rdataclass_t rdclass; + dns_namelist_t *section = &msg->sections[DNS_SECTION_QUESTION]; + bool best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0); + bool seen_problem = false; + bool free_name = false; ++ bool free_ht = false; ++ isc_ht_t *name_map = NULL; ++ ++ if (msg->counts[DNS_SECTION_QUESTION] > 1) { ++ isc_ht_init(&name_map, msg->mctx, 1, ISC_HT_CASE_INSENSITIVE); ++ } + + for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) { + name = NULL; +@@ -994,13 +1025,19 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + goto cleanup; + } + ++ /* If there is only one QNAME, skip the duplicity checks */ ++ if (name_map == NULL) { ++ result = ISC_R_SUCCESS; ++ goto skip_name_check; ++ } ++ + /* + * Run through the section, looking to see if this name + * is already there. If it is found, put back the allocated + * name since we no longer need it, and set our name pointer + * to point to the name we found. + */ +- result = findname(&name2, name, section); ++ result = name_hash_add(name_map, name, &name2); + + /* + * If it is the first name in the section, accept it. +@@ -1012,19 +1049,25 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + * this should be legal or not. In either case we no longer + * need this name pointer. + */ +- if (result != ISC_R_SUCCESS) { ++ skip_name_check: ++ switch (result) { ++ case ISC_R_SUCCESS: + if (!ISC_LIST_EMPTY(*section)) { + DO_ERROR(DNS_R_FORMERR); + } + ISC_LIST_APPEND(*section, name, link); +- free_name = false; +- } else { ++ break; ++ case ISC_R_EXISTS: + dns_message_puttempname(msg, &name); + name = name2; + name2 = NULL; +- free_name = false; ++ break; ++ default: ++ UNREACHABLE(); + } + ++ free_name = false; ++ + /* + * Get type and class. + */ +@@ -1054,14 +1097,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + msg->tkey = 1; + } + +- /* +- * Can't ask the same question twice. +- */ +- result = dns_message_find(name, rdclass, rdtype, 0, NULL); +- if (result == ISC_R_SUCCESS) { +- DO_ERROR(DNS_R_FORMERR); +- } +- + /* + * Allocate a new rdatalist. + */ +@@ -1071,6 +1106,7 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + goto cleanup; + } + rdataset = isc_mempool_get(msg->rdspool); ++ dns_rdataset_init(rdataset); + + /* + * Convert rdatalist to rdataset, and attach the latter to +@@ -1078,8 +1114,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + */ + rdatalist->type = rdtype; + rdatalist->rdclass = rdclass; +- +- dns_rdataset_init(rdataset); + result = dns_rdatalist_tordataset(rdatalist, rdataset); + if (result != ISC_R_SUCCESS) { + goto cleanup; +@@ -1087,24 +1121,66 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + + rdataset->attributes |= DNS_RDATASETATTR_QUESTION; + ++ /* ++ * Skip the duplicity check for first rdataset ++ */ ++ if (ISC_LIST_EMPTY(name->list)) { ++ result = ISC_R_SUCCESS; ++ goto skip_rds_check; ++ } ++ ++ /* ++ * Can't ask the same question twice. ++ */ ++ if (name->ht == NULL) { ++ isc_ht_init(&name->ht, msg->mctx, 1, ++ ISC_HT_CASE_SENSITIVE); ++ free_ht = true; ++ ++ INSIST(ISC_LIST_HEAD(name->list) == ++ ISC_LIST_TAIL(name->list)); ++ ++ dns_rdataset_t *old_rdataset = ++ ISC_LIST_HEAD(name->list); ++ ++ result = rds_hash_add(name->ht, old_rdataset, NULL); ++ ++ INSIST(result == ISC_R_SUCCESS); ++ } ++ result = rds_hash_add(name->ht, rdataset, NULL); ++ if (result == ISC_R_EXISTS) { ++ DO_ERROR(DNS_R_FORMERR); ++ } ++ ++ skip_rds_check: + ISC_LIST_APPEND(name->list, rdataset, link); ++ + rdataset = NULL; + } + + if (seen_problem) { +- return (DNS_R_RECOVERABLE); ++ result = DNS_R_RECOVERABLE; + } +- return (ISC_R_SUCCESS); + + cleanup: + if (rdataset != NULL) { +- INSIST(!dns_rdataset_isassociated(rdataset)); ++ if (dns_rdataset_isassociated(rdataset)) { ++ dns_rdataset_disassociate(rdataset); ++ } + isc_mempool_put(msg->rdspool, rdataset); + } + if (free_name) { + dns_message_puttempname(msg, &name); + } + ++ if (free_ht) { ++ cleanup_name_hashmaps(section); ++ } ++ ++ if (name_map != NULL) { ++ isc_ht_destroy(&name_map); ++ } ++ + return (result); + } + +@@ -1184,17 +1260,24 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + dns_name_t *name = NULL; + dns_name_t *name2 = NULL; + dns_rdataset_t *rdataset = NULL; ++ dns_rdataset_t *found_rdataset = NULL; + dns_rdatalist_t *rdatalist = NULL; +- isc_result_t result; ++ isc_result_t result = ISC_R_SUCCESS; + dns_rdatatype_t rdtype, covers; + dns_rdataclass_t rdclass; + dns_rdata_t *rdata = NULL; + dns_ttl_t ttl; + dns_namelist_t *section = &msg->sections[sectionid]; +- bool free_name = false, free_rdataset = false, seen_problem = false; ++ bool free_name = false, seen_problem = false; ++ bool free_ht = false; + bool preserve_order = ((options & DNS_MESSAGEPARSE_PRESERVEORDER) != 0); + bool best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0); + bool isedns, issigzero, istsig; ++ isc_ht_t *name_map = NULL; ++ ++ if (msg->counts[sectionid] > 1) { ++ isc_ht_init(&name_map, msg->mctx, 1, ISC_HT_CASE_INSENSITIVE); ++ } + + for (count = 0; count < msg->counts[sectionid]; count++) { + int recstart = source->current; +@@ -1202,10 +1285,10 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + + skip_name_search = false; + skip_type_search = false; +- free_rdataset = false; + isedns = false; + issigzero = false; + istsig = false; ++ found_rdataset = NULL; + + name = NULL; + result = dns_message_gettempname(msg, &name); +@@ -1245,8 +1328,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + if (msg->rdclass_set == 0 && + rdtype != dns_rdatatype_opt && /* class is UDP SIZE */ + rdtype != dns_rdatatype_tsig && /* class is ANY */ +- rdtype != dns_rdatatype_tkey) +- { /* class is undefined */ ++ rdtype != dns_rdatatype_tkey) /* class is undefined */ ++ { + msg->rdclass = rdclass; + msg->rdclass_set = 1; + } +@@ -1353,10 +1436,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + * Then put the meta-class back into the finished rdata. + */ + rdata = newrdata(msg); +- if (rdata == NULL) { +- result = ISC_R_NOMEMORY; +- goto cleanup; +- } + if (msg->opcode == dns_opcode_update && + update(sectionid, rdclass)) + { +@@ -1445,34 +1524,62 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + free_name = false; + } + } else { ++ if (name_map == NULL) { ++ result = ISC_R_SUCCESS; ++ goto skip_name_check; ++ } ++ + /* + * Run through the section, looking to see if this name + * is already there. If it is found, put back the + * allocated name since we no longer need it, and set + * our name pointer to point to the name we found. + */ +- result = findname(&name2, name, section); ++ result = name_hash_add(name_map, name, &name2); + + /* + * If it is a new name, append to the section. + */ +- if (result == ISC_R_SUCCESS) { ++ skip_name_check: ++ switch (result) { ++ case ISC_R_SUCCESS: ++ ISC_LIST_APPEND(*section, name, link); ++ break; ++ case ISC_R_EXISTS: + dns_message_puttempname(msg, &name); + name = name2; +- } else { +- ISC_LIST_APPEND(*section, name, link); ++ name2 = NULL; ++ break; ++ default: ++ UNREACHABLE(); + } + free_name = false; + } + ++ rdatalist = newrdatalist(msg); ++ rdatalist->type = rdtype; ++ rdatalist->covers = covers; ++ rdatalist->rdclass = rdclass; ++ rdatalist->ttl = ttl; ++ ++ dns_message_gettemprdataset(msg, &rdataset); ++ RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ++ ISC_R_SUCCESS); ++ dns_rdataset_setownercase(rdataset, name); ++ rdatalist = NULL; ++ + /* + * Search name for the particular type and class. + * Skip this stage if in update mode or this is a meta-type. + */ +- if (preserve_order || msg->opcode == dns_opcode_update || +- skip_type_search) ++ if (isedns || istsig || issigzero) { ++ /* Skip adding the rdataset to the tables */ ++ } else if (preserve_order || msg->opcode == dns_opcode_update || ++ skip_type_search) + { +- result = ISC_R_NOTFOUND; ++ result = ISC_R_SUCCESS; ++ ++ ISC_LIST_APPEND(name->list, rdataset, link); + } else { + /* + * If this is a type that can only occur in +@@ -1482,59 +1589,71 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + DO_ERROR(DNS_R_FORMERR); + } + +- rdataset = NULL; +- result = dns_message_find(name, rdclass, rdtype, covers, +- &rdataset); +- } +- +- /* +- * If we found an rdataset that matches, we need to +- * append this rdata to that set. If we did not, we need +- * to create a new rdatalist, store the important bits there, +- * convert it to an rdataset, and link the latter to the name. +- * Yuck. When appending, make certain that the type isn't +- * a singleton type, such as SOA or CNAME. +- * +- * Note that this check will be bypassed when preserving order, +- * the opcode is an update, or the type search is skipped. +- */ +- if (result == ISC_R_SUCCESS) { +- if (dns_rdatatype_issingleton(rdtype)) { +- dns_rdata_t *first; +- dns_rdatalist_fromrdataset(rdataset, +- &rdatalist); +- first = ISC_LIST_HEAD(rdatalist->rdata); +- INSIST(first != NULL); +- if (dns_rdata_compare(rdata, first) != 0) { +- DO_ERROR(DNS_R_FORMERR); +- } ++ if (ISC_LIST_EMPTY(name->list)) { ++ result = ISC_R_SUCCESS; ++ goto skip_rds_check; + } +- } + +- if (result == ISC_R_NOTFOUND) { +- rdataset = isc_mempool_get(msg->rdspool); +- free_rdataset = true; ++ if (name->ht == NULL) { ++ isc_ht_init(&name->ht, msg->mctx, 1, ++ ISC_HT_CASE_SENSITIVE); ++ free_ht = true; + +- rdatalist = newrdatalist(msg); +- if (rdatalist == NULL) { +- result = ISC_R_NOMEMORY; +- goto cleanup; ++ INSIST(ISC_LIST_HEAD(name->list) == ++ ISC_LIST_TAIL(name->list)); ++ ++ dns_rdataset_t *old_rdataset = ++ ISC_LIST_HEAD(name->list); ++ ++ result = rds_hash_add(name->ht, old_rdataset, ++ NULL); ++ ++ INSIST(result == ISC_R_SUCCESS); + } ++ found_rdataset = NULL; ++ result = rds_hash_add(name->ht, rdataset, ++ &found_rdataset); + +- rdatalist->type = rdtype; +- rdatalist->covers = covers; +- rdatalist->rdclass = rdclass; +- rdatalist->ttl = ttl; ++ /* ++ * If we found an rdataset that matches, we need to ++ * append this rdata to that set. If we did not, we ++ * need to create a new rdatalist, store the important ++ * bits there, convert it to an rdataset, and link the ++ * latter to the name. Yuck. When appending, make ++ * certain that the type isn't a singleton type, such as ++ * SOA or CNAME. ++ * ++ * Note that this check will be bypassed when preserving ++ * order, the opcode is an update, or the type search is ++ * skipped. ++ */ ++ skip_rds_check: ++ switch (result) { ++ case ISC_R_EXISTS: ++ /* Free the rdataset we used as the key */ ++ dns_rdataset_disassociate(rdataset); ++ isc_mempool_put(msg->rdspool, rdataset); ++ result = ISC_R_SUCCESS; ++ rdataset = found_rdataset; + +- dns_rdataset_init(rdataset); +- RUNTIME_CHECK( +- dns_rdatalist_tordataset(rdatalist, rdataset) == +- ISC_R_SUCCESS); +- dns_rdataset_setownercase(rdataset, name); ++ if (!dns_rdatatype_issingleton(rdtype)) { ++ break; ++ } + +- if (!isedns && !istsig && !issigzero) { ++ dns_rdatalist_fromrdataset(rdataset, ++ &rdatalist); ++ dns_rdata_t *first = ++ ISC_LIST_HEAD(rdatalist->rdata); ++ INSIST(first != NULL); ++ if (dns_rdata_compare(rdata, first) != 0) { ++ DO_ERROR(DNS_R_FORMERR); ++ } ++ break; ++ case ISC_R_SUCCESS: + ISC_LIST_APPEND(name->list, rdataset, link); +- free_rdataset = false; ++ break; ++ default: ++ UNREACHABLE(); + } + } + +@@ -1569,8 +1688,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + dns_rcode_t ercode; + + msg->opt = rdataset; +- rdataset = NULL; +- free_rdataset = false; + ercode = (dns_rcode_t)((msg->opt->ttl & + DNS_MESSAGE_EDNSRCODE_MASK) >> + 20); +@@ -1581,8 +1698,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + msg->sig0 = rdataset; + msg->sig0name = name; + msg->sigstart = recstart; +- rdataset = NULL; +- free_rdataset = false; + free_name = false; + } else if (istsig) { + msg->tsig = rdataset; +@@ -1592,22 +1707,17 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + * Windows doesn't like TSIG names to be compressed. + */ + msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; +- rdataset = NULL; +- free_rdataset = false; + free_name = false; + } ++ rdataset = NULL; + + if (seen_problem) { + if (free_name) { + dns_message_puttempname(msg, &name); + } +- if (free_rdataset) { +- isc_mempool_put(msg->rdspool, rdataset); +- } +- free_name = free_rdataset = false; ++ free_name = false; + } + INSIST(!free_name); +- INSIST(!free_rdataset); + } + + /* +@@ -1625,16 +1735,24 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, + } + + if (seen_problem) { +- return (DNS_R_RECOVERABLE); ++ result = DNS_R_RECOVERABLE; + } +- return (ISC_R_SUCCESS); + + cleanup: ++ if (rdataset != NULL && rdataset != found_rdataset) { ++ dns_rdataset_disassociate(rdataset); ++ isc_mempool_put(msg->rdspool, rdataset); ++ } + if (free_name) { + dns_message_puttempname(msg, &name); + } +- if (free_rdataset) { +- isc_mempool_put(msg->rdspool, rdataset); ++ ++ if (free_ht) { ++ cleanup_name_hashmaps(section); ++ } ++ ++ if (name_map != NULL) { ++ isc_ht_destroy(&name_map); + } + + return (result); +@@ -2452,7 +2570,7 @@ dns_message_findname(dns_message_t *msg, dns_section_t section, + const dns_name_t *target, dns_rdatatype_t type, + dns_rdatatype_t covers, dns_name_t **name, + dns_rdataset_t **rdataset) { +- dns_name_t *foundname; ++ dns_name_t *foundname = NULL; + isc_result_t result; + + /* +@@ -2499,22 +2617,6 @@ dns_message_findname(dns_message_t *msg, dns_section_t section, + return (result); + } + +-void +-dns_message_movename(dns_message_t *msg, dns_name_t *name, +- dns_section_t fromsection, dns_section_t tosection) { +- REQUIRE(msg != NULL); +- REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); +- REQUIRE(name != NULL); +- REQUIRE(VALID_NAMED_SECTION(fromsection)); +- REQUIRE(VALID_NAMED_SECTION(tosection)); +- +- /* +- * Unlink the name from the old section +- */ +- ISC_LIST_UNLINK(msg->sections[fromsection], name, link); +- ISC_LIST_APPEND(msg->sections[tosection], name, link); +-} +- + void + dns_message_addname(dns_message_t *msg, dns_name_t *name, + dns_section_t section) { +@@ -2591,6 +2693,10 @@ dns_message_puttempname(dns_message_t *msg, dns_name_t **itemp) { + REQUIRE(!ISC_LINK_LINKED(item, link)); + REQUIRE(ISC_LIST_HEAD(item->list) == NULL); + ++ if (item->ht != NULL) { ++ isc_ht_destroy(&item->ht); ++ } ++ + /* + * we need to check this in case dns_name_dup() was used. + */ +diff --git a/lib/dns/name.c b/lib/dns/name.c +index 8a258a2..90044ba 100644 +--- a/lib/dns/name.c ++++ b/lib/dns/name.c +@@ -188,6 +188,7 @@ dns_name_invalidate(dns_name_t *name) { + name->offsets = NULL; + name->buffer = NULL; + ISC_LINK_INIT(name, link); ++ INSIST(name->ht == NULL); + } + + bool +diff --git a/lib/isc/ht.c b/lib/isc/ht.c +index eaf2b3c..e11050f 100644 +--- a/lib/isc/ht.c ++++ b/lib/isc/ht.c +@@ -93,11 +93,54 @@ maybe_rehash(isc_ht_t *ht, size_t newcount); + static isc_result_t + isc__ht_iter_next(isc_ht_iter_t *it); + ++static uint8_t maptolower[] = { ++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, ++ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, ++ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, ++ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, ++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, ++ 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, ++ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, ++ 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, ++ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, ++ 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, ++ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, ++ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, ++ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, ++ 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, ++ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, ++ 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, ++ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, ++ 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, ++ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, ++ 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, ++ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, ++ 0xfc, 0xfd, 0xfe, 0xff ++}; ++ ++static int ++memcasecmp(const void *vs1, const void *vs2, size_t len) { ++ uint8_t const *s1 = vs1; ++ uint8_t const *s2 = vs2; ++ for (size_t i = 0; i < len; i++) { ++ uint8_t u1 = s1[i]; ++ uint8_t u2 = s2[i]; ++ int U1 = maptolower[u1]; ++ int U2 = maptolower[u2]; ++ int diff = U1 - U2; ++ if (diff) { ++ return diff; ++ } ++ } ++ return 0; ++} ++ + static bool + isc__ht_node_match(isc_ht_node_t *node, const uint32_t hashval, +- const uint8_t *key, uint32_t keysize) { ++ const uint8_t *key, uint32_t keysize, bool case_sensitive) { + return (node->hashval == hashval && node->keysize == keysize && +- memcmp(node->key, key, keysize) == 0); ++ (case_sensitive ? (memcmp(node->key, key, keysize) == 0) ++ : (memcasecmp(node->key, key, keysize) == 0))); + } + + static uint32_t +@@ -341,7 +384,9 @@ nexttable: + for (isc_ht_node_t *node = ht->table[findex][hash]; node != NULL; + node = node->next) + { +- if (isc__ht_node_match(node, hashval, key, keysize)) { ++ if (isc__ht_node_match(node, hashval, key, keysize, ++ ht->case_sensitive)) ++ { + return (node); + } + } +@@ -390,7 +435,9 @@ isc__ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize, + for (isc_ht_node_t *node = ht->table[idx][hash]; node != NULL; + prev = node, node = node->next) + { +- if (isc__ht_node_match(node, hashval, key, keysize)) { ++ if (isc__ht_node_match(node, hashval, key, keysize, ++ ht->case_sensitive)) ++ { + if (prev == NULL) { + ht->table[idx][hash] = node->next; + } else { +-- +2.33.0 + diff --git a/backport-CVE-2023-50387-CVE-2023-50868.patch b/backport-CVE-2023-50387-CVE-2023-50868.patch new file mode 100644 index 0000000000000000000000000000000000000000..08472b4da4825b12703fba7bb846f0a4afdd7dc1 --- /dev/null +++ b/backport-CVE-2023-50387-CVE-2023-50868.patch @@ -0,0 +1,600 @@ +From c12608ca934c0433d280e65fe6c631013e200cfe Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= +Date: Thu, 11 Jan 2024 12:03:24 +0100 +Subject: [PATCH] Split fast and slow task queues + +Change the taskmgr (and thus netmgr) in a way that it supports fast and +slow task queues. The fast queue is used for incoming DNS traffic and +it will pass the processing to the slow queue for sending outgoing DNS +messages and processing resolver messages. + +In the future, more tasks might get moved to the slow queues, so the +cached and authoritative DNS traffic can be handled without being slowed +down by operations that take longer time to process. + +Conflict:NA +Reference:https://downloads.isc.org/isc/bind/9.18.24/patches/0004-CVE-2023-50387-CVE-2023-50868.patch + +(cherry picked from commit 1b3b0cef224e7a9e8279c5cfe2f7e188e3777cc7) +--- + lib/dns/dst_api.c | 27 +++++++++---- + lib/dns/include/dns/validator.h | 1 + + lib/dns/include/dst/dst.h | 4 ++ + lib/dns/resolver.c | 4 +- + lib/dns/validator.c | 67 +++++++++++++++------------------ + lib/isc/include/isc/netmgr.h | 3 ++ + lib/isc/netmgr/http.c | 18 ++++----- + lib/isc/netmgr/netmgr-int.h | 1 + + lib/isc/netmgr/netmgr.c | 38 ++++++++++++------- + lib/isc/netmgr/tcp.c | 6 +-- + lib/isc/netmgr/tcpdns.c | 4 +- + lib/isc/netmgr/tlsdns.c | 4 +- + lib/isc/netmgr/tlsstream.c | 12 +++--- + lib/isc/netmgr/udp.c | 6 +-- + 14 files changed, 109 insertions(+), 86 deletions(-) + +diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c +index 4ffda8b..0658c69 100644 +--- a/lib/dns/dst_api.c ++++ b/lib/dns/dst_api.c +@@ -164,7 +164,8 @@ computeid(dst_key_t *key); + static isc_result_t + frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, + unsigned int protocol, dns_rdataclass_t rdclass, +- isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp); ++ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, ++ dst_key_t **keyp); + + static isc_result_t + algorithm_status(unsigned int alg); +@@ -753,6 +754,13 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target) { + isc_result_t + dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass, + isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { ++ return (dst_key_fromdns_ex(name, rdclass, source, mctx, false, keyp)); ++} ++ ++isc_result_t ++dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass, ++ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, ++ dst_key_t **keyp) { + uint8_t alg, proto; + uint32_t flags, extflags; + dst_key_t *key = NULL; +@@ -783,7 +791,7 @@ dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass, + } + + result = frombuffer(name, alg, flags, proto, rdclass, source, mctx, +- &key); ++ no_rdata, &key); + if (result != ISC_R_SUCCESS) { + return (result); + } +@@ -804,7 +812,7 @@ dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, + REQUIRE(dst_initialized); + + result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx, +- &key); ++ false, &key); + if (result != ISC_R_SUCCESS) { + return (result); + } +@@ -2351,7 +2359,8 @@ computeid(dst_key_t *key) { + static isc_result_t + frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, + unsigned int protocol, dns_rdataclass_t rdclass, +- isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) { ++ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, ++ dst_key_t **keyp) { + dst_key_t *key; + isc_result_t ret; + +@@ -2376,10 +2385,12 @@ frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags, + return (DST_R_UNSUPPORTEDALG); + } + +- ret = key->func->fromdns(key, source); +- if (ret != ISC_R_SUCCESS) { +- dst_key_free(&key); +- return (ret); ++ if (!no_rdata) { ++ ret = key->func->fromdns(key, source); ++ if (ret != ISC_R_SUCCESS) { ++ dst_key_free(&key); ++ return (ret); ++ } + } + } + +diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h +index 383dcb4..352a60a 100644 +--- a/lib/dns/include/dns/validator.h ++++ b/lib/dns/include/dns/validator.h +@@ -148,6 +148,7 @@ struct dns_validator { + unsigned int depth; + unsigned int authcount; + unsigned int authfail; ++ bool failed; + isc_stdtime_t start; + }; + +diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h +index ca292b0..f845e9b 100644 +--- a/lib/dns/include/dst/dst.h ++++ b/lib/dns/include/dst/dst.h +@@ -482,6 +482,10 @@ dst_key_tofile(const dst_key_t *key, int type, const char *directory); + */ + + isc_result_t ++dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass, ++ isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata, ++ dst_key_t **keyp); ++isc_result_t + dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass, + isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp); + /*%< +diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c +index 4b3d1c0..60cac29 100644 +--- a/lib/dns/resolver.c ++++ b/lib/dns/resolver.c +@@ -10408,8 +10408,8 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, + * Since we have a pool of tasks we bind them to task + * queues to spread the load evenly + */ +- result = isc_task_create_bound(taskmgr, 0, +- &res->buckets[i].task, i); ++ result = isc_task_create_bound( ++ taskmgr, 0, &res->buckets[i].task, ISC_NM_TASK_SLOW(i)); + if (result != ISC_R_SUCCESS) { + ntasks = i; + isc_mutex_destroy(&res->buckets[i].lock); +diff --git a/lib/dns/validator.c b/lib/dns/validator.c +index 56a0ced..47c4813 100644 +--- a/lib/dns/validator.c ++++ b/lib/dns/validator.c +@@ -1104,8 +1104,8 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, + * 'rdataset'. If found, build a dst_key_t for it and point val->key at + * it. + * +- * If val->key is already non-NULL, locate it in the rdataset and then +- * search past it for the *next* key that could have signed 'siginfo', then ++ * If val->key is already non-NULL, start searching from the next position in ++ * 'rdataset' to find the *next* key that could have signed 'siginfo', then + * set val->key to that. + * + * Returns ISC_R_SUCCESS if a possible matching key has been found, +@@ -1118,59 +1118,59 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) { + isc_buffer_t b; + dns_rdata_t rdata = DNS_RDATA_INIT; + dst_key_t *oldkey = val->key; +- bool foundold; ++ bool no_rdata = false; + + if (oldkey == NULL) { +- foundold = true; ++ result = dns_rdataset_first(rdataset); + } else { +- foundold = false; ++ dst_key_free(&oldkey); + val->key = NULL; ++ result = dns_rdataset_next(rdataset); + } +- +- result = dns_rdataset_first(rdataset); + if (result != ISC_R_SUCCESS) { +- goto failure; ++ goto done; + } ++ + do { + dns_rdataset_current(rdataset, &rdata); + + isc_buffer_init(&b, rdata.data, rdata.length); + isc_buffer_add(&b, rdata.length); + INSIST(val->key == NULL); +- result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b, +- val->view->mctx, &val->key); ++ result = dst_key_fromdns_ex(&siginfo->signer, rdata.rdclass, &b, ++ val->view->mctx, no_rdata, ++ &val->key); + if (result == ISC_R_SUCCESS) { + if (siginfo->algorithm == + (dns_secalg_t)dst_key_alg(val->key) && + siginfo->keyid == + (dns_keytag_t)dst_key_id(val->key) && ++ (dst_key_flags(val->key) & DNS_KEYFLAG_REVOKE) == ++ 0 && + dst_key_iszonekey(val->key)) + { +- if (foundold) { +- /* +- * This is the key we're looking for. +- */ +- return (ISC_R_SUCCESS); +- } else if (dst_key_compare(oldkey, val->key)) { +- foundold = true; +- dst_key_free(&oldkey); ++ if (no_rdata) { ++ /* Retry with full key */ ++ dns_rdata_reset(&rdata); ++ dst_key_free(&val->key); ++ no_rdata = false; ++ continue; + } ++ /* This is the key we're looking for. */ ++ goto done; + } + dst_key_free(&val->key); + } + dns_rdata_reset(&rdata); + result = dns_rdataset_next(rdataset); ++ no_rdata = true; + } while (result == ISC_R_SUCCESS); + ++done: + if (result == ISC_R_NOMORE) { + result = ISC_R_NOTFOUND; + } + +-failure: +- if (oldkey != NULL) { +- dst_key_free(&oldkey); +- } +- + return (result); + } + +@@ -1589,20 +1589,9 @@ validate_answer(dns_validator_t *val, bool resume) { + continue; + } + +- do { +- isc_result_t tresult; +- vresult = verify(val, val->key, &rdata, +- val->siginfo->keyid); +- if (vresult == ISC_R_SUCCESS) { +- break; +- } +- +- tresult = select_signing_key(val, val->keyset); +- if (tresult != ISC_R_SUCCESS) { +- break; +- } +- } while (1); ++ vresult = verify(val, val->key, &rdata, val->siginfo->keyid); + if (vresult != ISC_R_SUCCESS) { ++ val->failed = true; + validator_log(val, ISC_LOG_DEBUG(3), + "failed to verify rdataset"); + } else { +@@ -1639,9 +1628,13 @@ validate_answer(dns_validator_t *val, bool resume) { + } else { + validator_log(val, ISC_LOG_DEBUG(3), + "verify failure: %s", +- isc_result_totext(result)); ++ isc_result_totext(vresult)); + resume = false; + } ++ if (val->failed) { ++ result = ISC_R_NOMORE; ++ break; ++ } + } + if (result != ISC_R_NOMORE) { + validator_log(val, ISC_LOG_DEBUG(3), +diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h +index eff33f6..d42cfe9 100644 +--- a/lib/isc/include/isc/netmgr.h ++++ b/lib/isc/include/isc/netmgr.h +@@ -750,6 +750,9 @@ isc_nm_verify_tls_peer_result_string(const isc_nmhandle_t *handle); + * \li 'handle' is a valid netmgr handle object. + */ + ++#define ISC_NM_TASK_SLOW_OFFSET -2 ++#define ISC_NM_TASK_SLOW(i) (ISC_NM_TASK_SLOW_OFFSET - 1 - i) ++ + void + isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid); + /*%< +diff --git a/lib/isc/netmgr/http.c b/lib/isc/netmgr/http.c +index d7a33d5..2220edf 100644 +--- a/lib/isc/netmgr/http.c ++++ b/lib/isc/netmgr/http.c +@@ -2969,7 +2969,7 @@ isc__nm_http_set_max_streams(isc_nmsocket_t *listener, + void + isc_nm_http_set_endpoints(isc_nmsocket_t *listener, + isc_nm_http_endpoints_t *eps) { +- size_t nworkers; ++ size_t nlisteners; + + REQUIRE(VALID_NMSOCK(listener)); + REQUIRE(listener->type == isc_nm_httplistener); +@@ -2977,8 +2977,8 @@ isc_nm_http_set_endpoints(isc_nmsocket_t *listener, + + atomic_store(&eps->in_use, true); + +- nworkers = (size_t)listener->mgr->nworkers; +- for (size_t i = 0; i < nworkers; i++) { ++ nlisteners = (size_t)listener->mgr->nlisteners; ++ for (size_t i = 0; i < nlisteners; i++) { + isc__netievent__http_eps_t *ievent = + isc__nm_get_netievent_httpendpoints(listener->mgr, + listener, eps); +@@ -3003,20 +3003,20 @@ isc__nm_async_httpendpoints(isc__networker_t *worker, isc__netievent_t *ev0) { + static void + http_init_listener_endpoints(isc_nmsocket_t *listener, + isc_nm_http_endpoints_t *epset) { +- size_t nworkers; ++ size_t nlisteners; + + REQUIRE(VALID_NMSOCK(listener)); + REQUIRE(VALID_NM(listener->mgr)); + REQUIRE(VALID_HTTP_ENDPOINTS(epset)); + +- nworkers = (size_t)listener->mgr->nworkers; +- INSIST(nworkers > 0); ++ nlisteners = (size_t)listener->mgr->nlisteners; ++ INSIST(nlisteners > 0); + + listener->h2.listener_endpoints = + isc_mem_get(listener->mgr->mctx, +- sizeof(isc_nm_http_endpoints_t *) * nworkers); +- listener->h2.n_listener_endpoints = nworkers; +- for (size_t i = 0; i < nworkers; i++) { ++ sizeof(isc_nm_http_endpoints_t *) * nlisteners); ++ listener->h2.n_listener_endpoints = nlisteners; ++ for (size_t i = 0; i < nlisteners; i++) { + listener->h2.listener_endpoints[i] = NULL; + isc_nm_http_endpoints_attach( + epset, &listener->h2.listener_endpoints[i]); +diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h +index 364a933..6aca9ab 100644 +--- a/lib/isc/netmgr/netmgr-int.h ++++ b/lib/isc/netmgr/netmgr-int.h +@@ -776,6 +776,7 @@ struct isc_nm { + isc_refcount_t references; + isc_mem_t *mctx; + int nworkers; ++ int nlisteners; + isc_mutex_t lock; + isc_condition_t wkstatecond; + isc_condition_t wkpausecond; +diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c +index b19d468..2310b4b 100644 +--- a/lib/isc/netmgr/netmgr.c ++++ b/lib/isc/netmgr/netmgr.c +@@ -189,12 +189,12 @@ isc__nm_force_tid(int tid) { + } + + static void +-isc__nm_threadpool_initialize(uint32_t workers) { ++isc__nm_threadpool_initialize(uint32_t nworkers) { + char buf[11]; + int r = uv_os_getenv("UV_THREADPOOL_SIZE", buf, + &(size_t){ sizeof(buf) }); + if (r == UV_ENOENT) { +- snprintf(buf, sizeof(buf), "%" PRIu32, workers); ++ snprintf(buf, sizeof(buf), "%" PRIu32, nworkers); + uv_os_setenv("UV_THREADPOOL_SIZE", buf); + } + } +@@ -212,11 +212,11 @@ isc__nm_threadpool_initialize(uint32_t workers) { + #endif + + void +-isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) { ++isc__netmgr_create(isc_mem_t *mctx, uint32_t nworkers, isc_nm_t **netmgrp) { + isc_nm_t *mgr = NULL; + char name[32]; + +- REQUIRE(workers > 0); ++ REQUIRE(nworkers > 0); + + #ifdef MAXIMAL_UV_VERSION + if (uv_version() > MAXIMAL_UV_VERSION) { +@@ -234,10 +234,13 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) { + uv_version_string(), UV_VERSION_STRING); + } + +- isc__nm_threadpool_initialize(workers); ++ isc__nm_threadpool_initialize(nworkers); + + mgr = isc_mem_get(mctx, sizeof(*mgr)); +- *mgr = (isc_nm_t){ .nworkers = workers }; ++ *mgr = (isc_nm_t){ ++ .nworkers = nworkers * 2, ++ .nlisteners = nworkers, ++ }; + + isc_mem_attach(mctx, &mgr->mctx); + isc_mutex_init(&mgr->lock); +@@ -272,11 +275,12 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) { + atomic_init(&mgr->keepalive, 30000); + atomic_init(&mgr->advertised, 30000); + +- isc_barrier_init(&mgr->pausing, workers); +- isc_barrier_init(&mgr->resuming, workers); ++ isc_barrier_init(&mgr->pausing, mgr->nworkers); ++ isc_barrier_init(&mgr->resuming, mgr->nworkers); + +- mgr->workers = isc_mem_get(mctx, workers * sizeof(isc__networker_t)); +- for (size_t i = 0; i < workers; i++) { ++ mgr->workers = isc_mem_get(mctx, ++ mgr->nworkers * sizeof(isc__networker_t)); ++ for (int i = 0; i < mgr->nworkers; i++) { + isc__networker_t *worker = &mgr->workers[i]; + int r; + +@@ -310,7 +314,7 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) { + mgr->workers_running++; + isc_thread_create(nm_thread, &mgr->workers[i], &worker->thread); + +- snprintf(name, sizeof(name), "isc-net-%04zu", i); ++ snprintf(name, sizeof(name), "isc-net-%04d", i); + isc_thread_setname(worker->thread, name); + } + +@@ -817,9 +821,15 @@ isc_nm_task_enqueue(isc_nm_t *nm, isc_task_t *task, int threadid) { + isc__networker_t *worker = NULL; + + if (threadid == -1) { +- tid = (int)isc_random_uniform(nm->nworkers); ++ tid = (int)isc_random_uniform(nm->nlisteners); ++ } else if (threadid == ISC_NM_TASK_SLOW_OFFSET) { ++ tid = nm->nlisteners + ++ (int)isc_random_uniform(nm->nworkers - nm->nlisteners); ++ } else if (threadid < ISC_NM_TASK_SLOW_OFFSET) { ++ tid = nm->nlisteners + (ISC_NM_TASK_SLOW(threadid) % ++ (nm->nworkers - nm->nlisteners)); + } else { +- tid = threadid % nm->nworkers; ++ tid = threadid % nm->nlisteners; + } + + worker = &nm->workers[tid]; +@@ -3778,7 +3788,7 @@ isc__nm_async_settlsctx(isc__networker_t *worker, isc__netievent_t *ev0) { + static void + set_tlsctx_workers(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) { + /* Update the TLS context reference for every worker thread. */ +- for (size_t i = 0; i < (size_t)listener->mgr->nworkers; i++) { ++ for (size_t i = 0; i < (size_t)listener->mgr->nlisteners; i++) { + isc__netievent__tlsctx_t *ievent = + isc__nm_get_netievent_settlsctx(listener->mgr, listener, + tlsctx); +diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c +index 2a644fe..16b53cc 100644 +--- a/lib/isc/netmgr/tcp.c ++++ b/lib/isc/netmgr/tcp.c +@@ -341,7 +341,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, + isc__nm_connectcb(sock, req, result, false); + } else { + isc__nmsocket_clearcb(sock); +- sock->tid = isc_random_uniform(mgr->nworkers); ++ sock->tid = isc_random_uniform(mgr->nlisteners); + isc__nm_connectcb(sock, req, result, true); + } + atomic_store(&sock->closed, true); +@@ -362,7 +362,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, + isc__nm_put_netievent_tcpconnect(mgr, ievent); + } else { + atomic_init(&sock->active, false); +- sock->tid = isc_random_uniform(mgr->nworkers); ++ sock->tid = isc_random_uniform(mgr->nlisteners); + isc__nm_enqueue_ievent(&mgr->workers[sock->tid], + (isc__netievent_t *)ievent); + } +@@ -457,7 +457,7 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_sockaddr_t *iface, + isc__nmsocket_init(sock, mgr, isc_nm_tcplistener, iface); + + atomic_init(&sock->rchildren, 0); +- sock->nchildren = mgr->nworkers; ++ sock->nchildren = mgr->nlisteners; + children_size = sock->nchildren * sizeof(sock->children[0]); + sock->children = isc_mem_get(mgr->mctx, children_size); + memset(sock->children, 0, children_size); +diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c +index eda6aa6..46958d0 100644 +--- a/lib/isc/netmgr/tcpdns.c ++++ b/lib/isc/netmgr/tcpdns.c +@@ -324,7 +324,7 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, + isc__nm_put_netievent_tcpdnsconnect(mgr, ievent); + } else { + atomic_init(&sock->active, false); +- sock->tid = isc_random_uniform(mgr->nworkers); ++ sock->tid = isc_random_uniform(mgr->nlisteners); + isc__nm_enqueue_ievent(&mgr->workers[sock->tid], + (isc__netievent_t *)ievent); + } +@@ -422,7 +422,7 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_sockaddr_t *iface, + isc__nmsocket_init(sock, mgr, isc_nm_tcpdnslistener, iface); + + atomic_init(&sock->rchildren, 0); +- sock->nchildren = mgr->nworkers; ++ sock->nchildren = mgr->nlisteners; + children_size = sock->nchildren * sizeof(sock->children[0]); + sock->children = isc_mem_get(mgr->mctx, children_size); + memset(sock->children, 0, children_size); +diff --git a/lib/isc/netmgr/tlsdns.c b/lib/isc/netmgr/tlsdns.c +index d30e33f..40e6fc8 100644 +--- a/lib/isc/netmgr/tlsdns.c ++++ b/lib/isc/netmgr/tlsdns.c +@@ -419,7 +419,7 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, + isc__nm_put_netievent_tlsdnsconnect(mgr, ievent); + } else { + atomic_init(&sock->active, false); +- sock->tid = isc_random_uniform(mgr->nworkers); ++ sock->tid = isc_random_uniform(mgr->nlisteners); + isc__nm_enqueue_ievent(&mgr->workers[sock->tid], + (isc__netievent_t *)ievent); + } +@@ -532,7 +532,7 @@ isc_nm_listentlsdns(isc_nm_t *mgr, isc_sockaddr_t *iface, + isc__nmsocket_init(sock, mgr, isc_nm_tlsdnslistener, iface); + + atomic_init(&sock->rchildren, 0); +- sock->nchildren = mgr->nworkers; ++ sock->nchildren = mgr->nlisteners; + children_size = sock->nchildren * sizeof(sock->children[0]); + sock->children = isc_mem_get(mgr->mctx, children_size); + memset(sock->children, 0, children_size); +diff --git a/lib/isc/netmgr/tlsstream.c b/lib/isc/netmgr/tlsstream.c +index 7b49071..a3fc6d2 100644 +--- a/lib/isc/netmgr/tlsstream.c ++++ b/lib/isc/netmgr/tlsstream.c +@@ -1264,18 +1264,18 @@ isc__nm_tls_verify_tls_peer_result_string(const isc_nmhandle_t *handle) { + + static void + tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) { +- size_t nworkers; ++ size_t nlisteners; + + REQUIRE(VALID_NM(listener->mgr)); + REQUIRE(ctx != NULL); + +- nworkers = (size_t)listener->mgr->nworkers; +- INSIST(nworkers > 0); ++ nlisteners = (size_t)listener->mgr->nlisteners; ++ INSIST(nlisteners > 0); + + listener->tlsstream.listener_tls_ctx = isc_mem_get( +- listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nworkers); +- listener->tlsstream.n_listener_tls_ctx = nworkers; +- for (size_t i = 0; i < nworkers; i++) { ++ listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nlisteners); ++ listener->tlsstream.n_listener_tls_ctx = nlisteners; ++ for (size_t i = 0; i < nlisteners; i++) { + listener->tlsstream.listener_tls_ctx[i] = NULL; + isc_tlsctx_attach(ctx, + &listener->tlsstream.listener_tls_ctx[i]); +diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c +index 476c799..661de96 100644 +--- a/lib/isc/netmgr/udp.c ++++ b/lib/isc/netmgr/udp.c +@@ -157,14 +157,14 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb, + REQUIRE(VALID_NM(mgr)); + + /* +- * We are creating mgr->nworkers duplicated sockets, one ++ * We are creating mgr->nlisteners duplicated sockets, one + * socket for each worker thread. + */ + sock = isc_mem_get(mgr->mctx, sizeof(isc_nmsocket_t)); + isc__nmsocket_init(sock, mgr, isc_nm_udplistener, iface); + + atomic_init(&sock->rchildren, 0); +- sock->nchildren = mgr->nworkers; ++ sock->nchildren = mgr->nlisteners; + children_size = sock->nchildren * sizeof(sock->children[0]); + sock->children = isc_mem_get(mgr->mctx, children_size); + memset(sock->children, 0, children_size); +@@ -1037,7 +1037,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, + isc__nm_put_netievent_udpconnect(mgr, event); + } else { + atomic_init(&sock->active, false); +- sock->tid = isc_random_uniform(mgr->nworkers); ++ sock->tid = isc_random_uniform(mgr->nlisteners); + isc__nm_enqueue_ievent(&mgr->workers[sock->tid], + (isc__netievent_t *)event); + } +-- +2.33.0 + diff --git a/backport-CVE-2023-5517.patch b/backport-CVE-2023-5517.patch new file mode 100644 index 0000000000000000000000000000000000000000..4f7f1bbbdfcb8d7ceb1f2d98d0ee34476875dc96 --- /dev/null +++ b/backport-CVE-2023-5517.patch @@ -0,0 +1,108 @@ +From c73262493658cb8623927ef6cc2f023501f7e809 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Tue, 10 Oct 2023 10:58:18 +1100 +Subject: [PATCH] Save the correct result value to resume with + nxdomain-redirect + +The wrong result value was being saved for resumption with +nxdomain-redirect when performing the fetch. This lead to an assert +when checking that RFC 1918 reverse queries where not leaking to +the global internet. + +Conflict:NA +Reference:https://downloads.isc.org/isc/bind/9.18.24/patches/0002-CVE-2023-5517.patch + +(cherry picked from commit 9d0fa07c5e7a39db89862a4f843d2190059afb4b) +--- + lib/ns/query.c | 22 ++++++++++------------ + 1 file changed, 10 insertions(+), 12 deletions(-) + +diff --git a/lib/ns/query.c b/lib/ns/query.c +index c1e9148..61749c8 100644 +--- a/lib/ns/query.c ++++ b/lib/ns/query.c +@@ -465,10 +465,10 @@ static void + query_addnxrrsetnsec(query_ctx_t *qctx); + + static isc_result_t +-query_nxdomain(query_ctx_t *qctx, isc_result_t res); ++query_nxdomain(query_ctx_t *qctx, isc_result_t result); + + static isc_result_t +-query_redirect(query_ctx_t *qctx); ++query_redirect(query_ctx_t *qctx, isc_result_t result); + + static isc_result_t + query_ncache(query_ctx_t *qctx, isc_result_t result); +@@ -7718,8 +7718,7 @@ query_usestale(query_ctx_t *qctx, isc_result_t result) { + * result from the search. + */ + static isc_result_t +-query_gotanswer(query_ctx_t *qctx, isc_result_t res) { +- isc_result_t result = res; ++query_gotanswer(query_ctx_t *qctx, isc_result_t result) { + char errmsg[256]; + + CCTRACE(ISC_LOG_DEBUG(3), "query_gotanswer"); +@@ -7795,7 +7794,7 @@ root_key_sentinel: + return (query_coveringnsec(qctx)); + + case DNS_R_NCACHENXDOMAIN: +- result = query_redirect(qctx); ++ result = query_redirect(qctx, result); + if (result != ISC_R_COMPLETE) { + return (result); + } +@@ -9612,11 +9611,10 @@ query_addnxrrsetnsec(query_ctx_t *qctx) { + * Handle NXDOMAIN and empty wildcard responses. + */ + static isc_result_t +-query_nxdomain(query_ctx_t *qctx, isc_result_t res) { ++query_nxdomain(query_ctx_t *qctx, isc_result_t result) { + dns_section_t section; + uint32_t ttl; +- isc_result_t result = res; +- bool empty_wild = (res == DNS_R_EMPTYWILD); ++ bool empty_wild = (result == DNS_R_EMPTYWILD); + + CCTRACE(ISC_LOG_DEBUG(3), "query_nxdomain"); + +@@ -9625,7 +9623,7 @@ query_nxdomain(query_ctx_t *qctx, isc_result_t res) { + INSIST(qctx->is_zone || REDIRECT(qctx->client)); + + if (!empty_wild) { +- result = query_redirect(qctx); ++ result = query_redirect(qctx, result); + if (result != ISC_R_COMPLETE) { + return (result); + } +@@ -9713,7 +9711,7 @@ cleanup: + * redirecting, so query processing should continue past it. + */ + static isc_result_t +-query_redirect(query_ctx_t *qctx) { ++query_redirect(query_ctx_t *qctx, isc_result_t saved_result) { + isc_result_t result; + + CCTRACE(ISC_LOG_DEBUG(3), "query_redirect"); +@@ -9754,7 +9752,7 @@ query_redirect(query_ctx_t *qctx) { + SAVE(qctx->client->query.redirect.rdataset, qctx->rdataset); + SAVE(qctx->client->query.redirect.sigrdataset, + qctx->sigrdataset); +- qctx->client->query.redirect.result = DNS_R_NCACHENXDOMAIN; ++ qctx->client->query.redirect.result = saved_result; + dns_name_copy(qctx->fname, qctx->client->query.redirect.fname); + qctx->client->query.redirect.authoritative = + qctx->authoritative; +@@ -10415,7 +10413,7 @@ query_coveringnsec(query_ctx_t *qctx) { + * We now have the proof that we have an NXDOMAIN. Apply + * NXDOMAIN redirection if configured. + */ +- result = query_redirect(qctx); ++ result = query_redirect(qctx, DNS_R_COVERINGNSEC); + if (result != ISC_R_COMPLETE) { + redirected = true; + goto cleanup; +-- +2.33.0 + diff --git a/backport-CVE-2023-5679.patch b/backport-CVE-2023-5679.patch new file mode 100644 index 0000000000000000000000000000000000000000..d593b35afeed6d02aa95308c7da8db1c409a3385 --- /dev/null +++ b/backport-CVE-2023-5679.patch @@ -0,0 +1,38 @@ +From 7db2796507127b40e2f091dafb842c6a7e86b9a8 Mon Sep 17 00:00:00 2001 +From: Mark Andrews +Date: Thu, 12 Oct 2023 12:01:46 +1100 +Subject: [PATCH] Restore dns64 state during serve-stale processing + +If we are in the process of looking for the A records as part of +dns64 processing and the server-stale timeout triggers, redo the +dns64 changes that had been made to the orignal qctx. + +Conflict:NA +Reference:https://downloads.isc.org/isc/bind/9.18.24/patches/0003-CVE-2023-5679.patch + +(cherry picked from commit 1fcc483df13e049b96f620e515f0d4d45f3680b7) +--- + lib/ns/query.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/lib/ns/query.c b/lib/ns/query.c +index 61749c8..40e1232 100644 +--- a/lib/ns/query.c ++++ b/lib/ns/query.c +@@ -6228,6 +6228,13 @@ query_lookup_stale(ns_client_t *client) { + query_ctx_t qctx; + + qctx_init(client, NULL, client->query.qtype, &qctx); ++ if (DNS64(client)) { ++ qctx.qtype = qctx.type = dns_rdatatype_a; ++ qctx.dns64 = true; ++ } ++ if (DNS64EXCLUDE(client)) { ++ qctx.dns64_exclude = true; ++ } + dns_db_attach(client->view->cachedb, &qctx.db); + client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK; + client->query.dboptions |= DNS_DBFIND_STALETIMEOUT; +-- +2.33.0 + diff --git a/bind-9.18.21.tar.xz b/bind-9.18.21.tar.xz new file mode 100644 index 0000000000000000000000000000000000000000..c2b86b24ce539ee5c1429ffe417f71daa7d6476e Binary files /dev/null and b/bind-9.18.21.tar.xz differ diff --git a/bind-9.18.21.tar.xz.asc b/bind-9.18.21.tar.xz.asc new file mode 100644 index 0000000000000000000000000000000000000000..b4b062c8a31050b6d41b41acd0b8ca88a94e0745 --- /dev/null +++ b/bind-9.18.21.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEcGtsKGIOdvkdEfffUQpkKgbFLOwFAmV3BGsACgkQUQpkKgbF +LOwu9w/+JciqKqT0JieUDwPzEhhulBCWEhbZFrHK6dFM5UkPHkaV79QkZAQEhnq1 +FXVEF99ZuTbz5s79wNAZ9I4AiU0al5RK1P5MwMBbjsQrfnkhmKnPIU1jx3FSVrCP +tC9l1xEjkLNi2vf28ZQ9KED2hUdqsgTZqDvgewEnrq1NtZ0K7ozz9nHQLfooDSJT +L5U9HDp3vf5BJWONjnKAPjJJdeRf7HPqokJVSjQcVxrT06VsMNUFFmyCbEJ0UTJm +mqDrRuEXhkAKf40DwMr0qGqiq5Q4m960yADEK1Aju/9cEf6Ag4FYyy70iyICe7Tj +T8qjVzzwboUJao3m/152+6qvzGXJKdUUZqCnNcCc2wmirmg/ES4DLLFyYYXBflj7 +hWCOLXeghF/785te4fmiH3gqcEZBEVcc0wl1HCL5m3q9kGutGgLJVOZgM5D6zf2T +0Sa60qIr5r+cKCS9OYowTH1+NqEsW4XhCVIe/RYEuXa3FFczIUbdGlUQ5t9ILBxi +zbZ04Tj0tecqUVkhoEYZfQzhHEa43LzxATdQ4Zc01USaxhbSFSoyG1+WP1tPD+PL +wqZA9tEuvKtngr/UP+BeLG0lWv5zbtShzM1V1cEg7JuoiI2onWstaN7NYXShiUMZ +oVYXIBbmNbXVmm2TYzt4mw9TotGWHkSNjPZGvvAYw/0mtcw6NXs= +=bzR1 +-----END PGP SIGNATURE----- diff --git a/bind-9.18.26.tar.xz b/bind-9.18.26.tar.xz new file mode 100644 index 0000000000000000000000000000000000000000..5350b6553ecd6088e9f2afe9d191c68d9ce6852b Binary files /dev/null and b/bind-9.18.26.tar.xz differ diff --git a/bind-9.18.26.tar.xz.asc b/bind-9.18.26.tar.xz.asc new file mode 100644 index 0000000000000000000000000000000000000000..a811d60f798a97a427a0c64d50d910931d60ae0d --- /dev/null +++ b/bind-9.18.26.tar.xz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEcGtsKGIOdvkdEfffUQpkKgbFLOwFAmYP/mwACgkQUQpkKgbF +LOxZehAAhJ6QZTQU8jTjHu78cI/m/BUbcpGiYAuo2+0qWbrZui8G29ajLD7Kk5ms +VGuUmIBHkrJwKjOYWy4qQWZq+Q9s0ohAWpTY96CfiYmq7+M6DtNf1xwKg4kNkas6 +2ftJKdTF0Bd4S/bJ1RpvuP59fWmrcOve6H96gvQuOUQ1fBx0u8q6H76EGrnsEyNg +lH2ohl734ArEtJOwIYhdZgXXv6GuqQkqidYKwF6pWyjMEtaH11/LGTSz2rXIMDRy +mFQWhe5xCQrPJ+u9FVb5CIBc6SehMS2b+g1WN2DXZYT8b4C2CsJRDhffgrKVnz/F +7oX85LmZZNPZdXqe/ax50VBq50rFZN2ywfylbBpXuJU/6mPgH2914istn0+g4Uep +DSHXcMrFcig9adGqm76kXCmFbvWkdxHVD6KUQfGdDJispilTpbiKwkWe6SDB9U1J +0hPYd9MknfJ/PRhkCh+z8r+vz7HEv9KOWxa5KyfZlSBkLgwJ8YdOKw0sJcrsULa9 +TPIu+jMw/MwcL5usSdrX+qgvdmrTlC/md4MCM/FlgWjW9hGFibxfhVkL27iS+19T +jt9i3ORdgElxe3sU5BHTcgX044Qu4s0twNmwJda85vgsFbupCBHiJFXOBFGHkiSU +k/ci85gBopV5iexFWCucIy8CeS//TpdS+N8AqNg5xtEkPzuhCOk= +=wSVb +-----END PGP SIGNATURE----- diff --git a/bind.spec b/bind.spec new file mode 100644 index 0000000000000000000000000000000000000000..a06217c56711675a77fe93bb97479ba230a45bff --- /dev/null +++ b/bind.spec @@ -0,0 +1,900 @@ +%define anolis_release 1 + +%bcond_with SYSTEMTEST +%bcond_without GSSTSIG +%bcond_without JSON +%bcond_without DLZ +%bcond_with GEOIP2 +%bcond_without UNITTEST +%bcond_with DNSTAP +%bcond_without LMDB +%bcond_without DOC +%bcond_with TSAN + +%{?!bind_uid: %global bind_uid 25} +%{?!bind_gid: %global bind_gid 25} +%{!?_pkgdocdir:%global _pkgdocdir %{_docdir}/%{name}-%{version}} +%global bind_dir /var/named +%global _unitdir /usr/lib/systemd/system +%global _tmpfilesdir /usr/lib/tmpfiles.d +%global chroot_prefix %{bind_dir}/chroot +%global chroot_create_directories /dev /run/named %{_localstatedir}/{log,named,tmp} \\\ + %{_sysconfdir}/{crypto-policies/back-ends,pki/dnssec-keys,named} \\\ + %{_libdir}/bind %{_libdir}/named %{_datadir}/GeoIP /proc/sys/net/ipv4 + +%global selinuxbooleans named_write_master_zones=1 +%define bind_export_libs isc dns isccfg irs +%{!?_export_dir:%global _export_dir /bind9-export/} +%undefine _strict_symbol_defs_build + +Summary: The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) server +Name: bind +License: MPLv2.0 +Version: 9.18.26 +Release: %{anolis_release}%{?dist} +Epoch: 32 +Url: https://www.isc.org/downloads/bind/ +# +Source0: https://downloads.isc.org/isc/bind9/%{version}/bind-%{version}.tar.xz +Source1: named.sysconfig +Source2: https://downloads.isc.org/isc/bind9/%{version}/bind-%{version}.tar.xz.asc +Source3: named.logrotate +Source4: https://downloads.isc.org/isc/pgpkeys/codesign2021.txt +Source16: named.conf +# Refresh by command: dig @a.root-servers.net. +tcp +norec +# or from URL +Source17: https://www.internic.net/domain/named.root +Source18: named.localhost +Source19: named.loopback +Source20: named.empty +Source23: named.rfc1912.zones +Source25: named.conf.sample +Source27: named.root.key +Source35: bind.tmpfiles.d +Source36: trusted-key.key +Source37: named.service +Source38: named-chroot.service +Source41: setup-named-chroot.sh +Source42: generate-rndc-key.sh +Source43: named.rwtab +Source44: named-chroot-setup.service +Source46: named-setup-rndc.service +Source48: setup-named-softhsm.sh +Source49: named-chroot.files + +# Common patches + +%{?systemd_ordering} +Requires: coreutils +Requires: shadow-utils +Requires: glibc-common +Requires: grep +Requires: bind-libs = %{EVR} +Requires: systemd +# This wild require should satisfy %%selinux_set_boolean macro only +# in case it needs to be used +Requires: policycoreutils-python-utils libselinux-utils +Requires: selinux-policy selinux-policy-base libuv +Recommends: bind-utils bind-dnssec-utils +BuildRequires: gcc, make +BuildRequires: openssl-devel, libtool, autoconf, pkgconfig, libcap-devel +BuildRequires: libidn2-devel, libxml2-devel +#BuildRequires: systemd-rpm-macros +BuildRequires: selinux-policy +# needed for %%{__python3} macro +BuildRequires: python3-devel +BuildRequires: python3-ply +BuildRequires: findutils sed +BuildRequires: libuv-devel +BuildRequires: systemd +BuildRequires: libnsl2 +BuildRequires: libnghttp2-devel +BuildRequires: chrpath + +%if %{with DLZ} +BuildRequires: openldap-devel, libpq-devel, sqlite-devel, mariadb-connector-c-devel +%endif +%if %{with UNITTEST} +# make unit dependencies +BuildRequires: libcmocka-devel kyua +%endif +%if %{with UNITTEST} || %{with SYSTEMTEST} +BuildRequires: softhsm +%endif +%if %{with SYSTEMTEST} +# bin/tests/system dependencies +BuildRequires: perl(Net::DNS) perl(Net::DNS::Nameserver) perl(Time::HiRes) perl(Getopt::Long) +# manual configuration requires this tool +BuildRequires: iproute +%endif +%if %{with GSSTSIG} +BuildRequires: krb5-devel +%endif +%if %{with LMDB} +BuildRequires: lmdb-devel +%endif +%if %{with JSON} +BuildRequires: json-c-devel +%endif +%if %{with GEOIP2} +BuildRequires: libmaxminddb-devel +%endif +%if %{with DNSTAP} +BuildRequires: fstrm-devel protobuf-c-devel +%endif +# Needed to regenerate dig.1 manpage + +BuildRequires: python3-sphinx python3-sphinx_rtd_theme +BuildRequires: doxygen + +%if %{with DOCPDF} +# Because remaining issues with COPR, allow turning off PDF (re)generation +BuildRequires: python3-sphinx-latex latexmk texlive-xetex texlive-xindy +%endif +%if %{with TSAN} +BuildRequires: libtsan +%endif + +%description +BIND (Berkeley Internet Name Domain) is an implementation of the DNS +(Domain Name System) protocols. BIND includes a DNS server (named), +which resolves host names to IP addresses; a resolver library +(routines for applications to use when interfacing with DNS); and +tools for verifying that the DNS server is operating properly. + + + +%package libs +Summary: Libraries used by the BIND DNS packages +Requires: bind-license = %{EVR} +Provides: bind-libs-lite = %{EVR} +Obsoletes: bind-libs-lite < 32:9.16.13 + +%description libs +Contains heavyweight version of BIND suite libraries used by both named DNS +server and utilities in bind-utils package. + +%package license +Summary: License of the BIND DNS suite +BuildArch:noarch + +%description license +Contains license of the BIND DNS suite. + +%package utils +Summary: Utilities for querying DNS name servers +Requires: bind-libs = %{EVR} +# For compatibility with Debian package +Provides: dnsutils = %{EVR} + +%description utils +Bind-utils contains a collection of utilities for querying DNS (Domain +Name System) name servers to find out information about Internet +hosts. These tools will provide you with the IP addresses for given +host names, as well as other information about registered domains and +network addresses. + +You should install bind-utils if you need to get information from DNS name +servers. + +%package dnssec-utils +Summary: DNSSEC keys and zones management utilities +Requires: bind-libs = %{EVR} +Recommends: bind-utils +Requires: bind-dnssec-doc = %{EVR} + +%description dnssec-utils +Bind-dnssec-utils contains a collection of utilities for editing +DNSSEC keys and BIND zone files. These tools provide generation, +revocation and verification of keys and DNSSEC signatures in zone files. + +You should install bind-dnssec-utils if you need to sign a DNS zone +or maintain keys for it. + +%package dnssec-doc +Summary: Manual pages of DNSSEC utilities +Requires: bind-license = %{EVR} +BuildArch:noarch +Conflicts: %{name}-utils < %{EVR} + +%description dnssec-doc +Bind-dnssec-doc contains manual pages for bind-dnssec-utils. + +%package devel +Summary: Header files and libraries needed for bind-dyndb-ldap +Provides: bind-lite-devel = %{EVR} +Obsoletes: bind-lite-devel < 32:9.16.6-3 +Requires: bind-libs = %{EVR} +Requires: openssl-devel libxml2-devel +Requires: libcap-devel + +%if %{with GSSTSIG} +Requires: krb5-devel +%endif +%if %{with LMDB} +Requires: lmdb-devel +%endif +%if %{with JSON} +Requires: json-c-devel +%endif +%if %{with DNSTAP} +Requires: fstrm-devel protobuf-c-devel +%endif +%if %{with GEOIP2} +Requires: libmaxminddb-devel +%endif + +%description devel +The bind-devel package contains full version of the header files and libraries +required for building bind-dyndb-ldap. Upstream no longer supports nor recommends +bind libraries for third party applications. + +%package chroot +Summary: A chroot runtime environment for the ISC BIND DNS server, named(8) +Prefix: %{chroot_prefix} +# grep is required due to setup-named-chroot.sh script +Requires: grep +Requires: bind = %{EVR} + +%description chroot +This package contains a tree of files which can be used as a +chroot(2) jail for the named(8) program from the BIND package. +Based on the code from Jan "Yenya" Kasprzak + + +%if %{with DLZ} +%package dlz-filesystem +Summary: BIND server filesystem DLZ module +Requires: bind = %{EVR} + +%description dlz-filesystem +Dynamic Loadable Zones filesystem module for BIND server. + +%package dlz-ldap +Summary: BIND server ldap DLZ module +Requires: bind = %{EVR} + +%description dlz-ldap +Dynamic Loadable Zones LDAP module for BIND server. + +%package dlz-mysql +Summary: BIND server mysql and mysqldyn DLZ modules +Requires: bind = %{EVR} +Provides: %{name}-dlz-mysqldyn = %{EVR} +Obsoletes: %{name}-dlz-mysqldyn < 32:9.16.6-3 + +%description dlz-mysql +Dynamic Loadable Zones MySQL module for BIND server. +Contains also mysqldyn module with dynamic DNS updates (DDNS) support. + +%endif + +%if %{with DOC} +%package doc +Summary: BIND 9 Administrator Reference Manual +Requires: bind-license = %{EVR} +Requires: python3-sphinx_rtd_theme +BuildArch: noarch + +%description doc +BIND (Berkeley Internet Name Domain) is an implementation of the DNS +(Domain Name System) protocols. BIND includes a DNS server (named), +which resolves host names to IP addresses; a resolver library +(routines for applications to use when interfacing with DNS); and +tools for verifying that the DNS server is operating properly. + +This package contains BIND 9 Administrator Reference Manual +in HTML and PDF format. +%end + +%endif + +%prep +%autosetup -n %{name}-%{version} -N + +# Common patches +%autopatch -p1 -m 10 + +%build +## We use out of tree configure/build for export libs +%define _configure "../configure" + +# normal and pkcs11 unit tests +%define unit_prepare_build() \ + find lib -name 'K*.key' -exec cp -uv '{}' "%{1}/{}" ';' \ + find lib -name 'testdata' -type d -exec cp -Tav '{}' "%{1}/{}" ';' \ + find lib -name 'testkeys' -type d -exec cp -Tav '{}' "%{1}/{}" ';' \ + +%define systemtest_prepare_build() \ + cp -Tuav bin/tests "%{1}/bin/tests/" \ + +CFLAGS="$CFLAGS $RPM_OPT_FLAGS" +%if %{with TSAN} + CFLAGS+=" -O1 -fsanitize=thread -fPIE -pie" +%endif +export CFLAGS +export STD_CDEFINES="$CPPFLAGS" + + +autoconf --force + +mkdir build + +%if %{with DLZ} +# DLZ modules do not support oot builds. Copy files into build +mkdir -p build/contrib/dlz +cp -frp contrib/dlz/modules build/contrib/dlz/modules +%endif + +pushd build +LIBDIR_SUFFIX= +export LIBDIR_SUFFIX +%configure \ + --localstatedir=%{_var} \ + --with-pic \ + --disable-static \ + --includedir=%{_includedir}/bind9 \ + --with-tuning=large \ + --with-libidn2 \ +%if %{with GEOIP2} + --with-maxminddb \ +%endif +%if %{with GSSTSIG} + --with-gssapi=yes \ +%endif +%if %{with LMDB} + --with-lmdb=yes \ +%else + --with-lmdb=no \ +%endif +%if %{with JSON} +--with-json-c \ +%endif +%if %{with DNSTAP} + --enable-dnstap \ +%endif +%if %{with UNITTEST} + --with-cmocka \ +%endif + --enable-fixed-rrset \ + --enable-full-report \ +; +%if %{with DNSTAP} + pushd lib + SRCLIB="../../../lib" + (cd dns && ln -s ${SRCLIB}/dns/dnstap.proto) + popd +%endif + +%if %{with DOCPDF} +# avoid using home for pdf latex files +export TEXMFVAR="`pwd`" +export TEXMFCONFIG="`pwd`" +fmtutil-user --listcfg || : +fmtutil-user --missing || : +%endif + +%make_build +%if %{with DOC} + make doc +%endif + +#%%unit_prepare_build build +#%%systemtest_prepare_build build + +%check +%if %{with UNITTEST} || %{with SYSTEMTEST} + # Tests require initialization of pkcs11 token + eval "$(bash %{SOURCE48} -A "`pwd`/softhsm-tokens")" +%endif + +%if %{with TSAN} +export TSAN_OPTIONS="log_exe_name=true log_path=ThreadSanitizer exitcode=0" +%endif + +%if %{with UNITTEST} + pushd build + CPUS=$(lscpu -p=cpu,core | grep -v '^#' | wc -l) + if [ "$CPUS" -gt 16 ]; then + ORIGFILES=$(ulimit -n) + ulimit -n 4096 || : # Requires on some machines with many cores + fi + export ISC_TASK_WORKERS=8 + make unit + e=$? + if [ "$e" -ne 0 ]; then + echo "ERROR: this build of BIND failed 'make unit'. Aborting." + exit $e; + fi; + + [ "$CPUS" -gt 16 ] && ulimit -n $ORIGFILES || : + popd +## End of UNITTEST +%endif + +%if %{with SYSTEMTEST} +# Runs system test if ip addresses are already configured +# or it is able to configure them +if perl bin/tests/system/testsock.pl +then + CONFIGURED=already + fi; +else + echo 'SKIPPED: tests require root, CAP_NET_ADMIN or already configured test addresses.' +fi +%endif +: + +%install +# Build directory hierarchy +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d +mkdir -p ${RPM_BUILD_ROOT}%{_libdir}/{bind,named} +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/named/{slaves,data,dynamic} +mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/{man1,man5,man8} +mkdir -p ${RPM_BUILD_ROOT}/run/named +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log + +#chroot +for D in %{chroot_create_directories} +do + mkdir -p ${RPM_BUILD_ROOT}/%{chroot_prefix}${D} +done + +# create symlink as it is on real filesystem +pushd ${RPM_BUILD_ROOT}/%{chroot_prefix}/var +ln -s ../run run +popd + +# these are required to prevent them being erased during upgrade of previous +touch ${RPM_BUILD_ROOT}/%{chroot_prefix}%{_sysconfdir}/named.conf +#end chroot + +pushd build +%make_install +popd + +# Remove unwanted files +rm -f ${RPM_BUILD_ROOT}/etc/bind.keys + +# Systemd unit files +mkdir -p ${RPM_BUILD_ROOT}%{_unitdir} +install -m 644 %{SOURCE37} ${RPM_BUILD_ROOT}%{_unitdir} +install -m 644 %{SOURCE38} ${RPM_BUILD_ROOT}%{_unitdir} +install -m 644 %{SOURCE44} ${RPM_BUILD_ROOT}%{_unitdir} +install -m 644 %{SOURCE46} ${RPM_BUILD_ROOT}%{_unitdir} + + +mkdir -p ${RPM_BUILD_ROOT}%{_libexecdir} +install -m 755 %{SOURCE41} ${RPM_BUILD_ROOT}%{_libexecdir}/setup-named-chroot.sh +install -m 755 %{SOURCE42} ${RPM_BUILD_ROOT}%{_libexecdir}/generate-rndc-key.sh + +install -m 755 %{SOURCE48} ${RPM_BUILD_ROOT}%{_libexecdir}/setup-named-softhsm.sh + +install -m 644 %SOURCE3 ${RPM_BUILD_ROOT}/etc/logrotate.d/named +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig +install -m 644 %{SOURCE1} ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/named +install -m 644 %{SOURCE49} ${RPM_BUILD_ROOT}%{_sysconfdir}/named-chroot.files + +pushd ${RPM_BUILD_ROOT}%{_sbindir} +# Compatibility with previous major versions, only for selected binaries +for BIN in named-checkconf named-checkzone named-compilezone +do + ln -s ../bin/$BIN $BIN +done +popd + +%if %{with DLZ} + pushd build + pushd contrib/dlz/modules + for DIR in filesystem ldap mysql mysqldyn; do + %make_install -C $DIR libdir=%{_libdir}/bind + done + pushd ${RPM_BUILD_ROOT}/%{_libdir}/named + cp -s ../bind/dlz_*.so . + popd + mkdir -p doc/{mysql,mysqldyn} + cp -p mysqldyn/testing/README doc/mysqldyn/README.testing + cp -p mysqldyn/testing/* doc/mysqldyn + cp -p mysql/testing/* doc/mysql + popd + popd +%endif + +# Remove libtool .la files: +find ${RPM_BUILD_ROOT}/%{_libdir} -name '*.la' -exec '/bin/rm' '-f' '{}' ';'; + + +# 9.16.4 installs even manual pages for tools not generated +%if %{without DNSTAP} +rm -f ${RPM_BUILD_ROOT}%{_mandir}/man1/dnstap-read.1* || true +%endif +%if %{without LMDB} +rm -f ${RPM_BUILD_ROOT}%{_mandir}/man8/named-nzd2nzf.8* || true +%endif + +pushd ${RPM_BUILD_ROOT}%{_mandir}/man8 +ln -s ddns-confgen.8.gz tsig-keygen.8.gz +popd +pushd ${RPM_BUILD_ROOT}%{_mandir}/man1 +ln -s named-checkzone.1.gz named-compilezone.1.gz +popd + +%if %{with DOC} +mkdir -p ${RPM_BUILD_ROOT}%{_pkgdocdir} +cp -a build/doc/arm/_build/html ${RPM_BUILD_ROOT}%{_pkgdocdir} +rm -rf ${RPM_BUILD_ROOT}%{_pkgdocdir}/html/.{buildinfo,doctrees} +# Backward compatible link to 9.11 documentation +(cd ${RPM_BUILD_ROOT}%{_pkgdocdir} && ln -s html/index.html Bv9ARM.html) +# Share static data from original sphinx package +for DIR in %{python3_sitelib}/sphinx_rtd_theme/static/* +do + BASE=$(basename -- "$DIR") + BINDTHEMEDIR="${RPM_BUILD_ROOT}%{_pkgdocdir}/html/_static/$BASE" + if [ -d "$BINDTHEMEDIR" ]; then + rm -rf "$BINDTHEMEDIR" + ln -s "$DIR" "$BINDTHEMEDIR" + fi +done +%endif +%if %{with DOCPDF} +cp -a build/doc/arm/_build/latex/Bv9ARM.pdf ${RPM_BUILD_ROOT}%{_pkgdocdir} +%endif + +# Ghost config files: +touch ${RPM_BUILD_ROOT}%{_localstatedir}/log/named.log + +# configuration files: +install -m 640 %{SOURCE16} ${RPM_BUILD_ROOT}%{_sysconfdir}/named.conf +touch ${RPM_BUILD_ROOT}%{_sysconfdir}/rndc.{key,conf} +install -m 644 %{SOURCE27} ${RPM_BUILD_ROOT}%{_sysconfdir}/named.root.key +install -m 644 %{SOURCE36} ${RPM_BUILD_ROOT}%{_sysconfdir}/trusted-key.key +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/named + +# data files: +mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/named +install -m 640 %{SOURCE17} ${RPM_BUILD_ROOT}%{_localstatedir}/named/named.ca +install -m 640 %{SOURCE18} ${RPM_BUILD_ROOT}%{_localstatedir}/named/named.localhost +install -m 640 %{SOURCE19} ${RPM_BUILD_ROOT}%{_localstatedir}/named/named.loopback +install -m 640 %{SOURCE20} ${RPM_BUILD_ROOT}%{_localstatedir}/named/named.empty +install -m 640 %{SOURCE23} ${RPM_BUILD_ROOT}%{_sysconfdir}/named.rfc1912.zones + +# sample bind configuration files for %%doc: +mkdir -p sample/etc sample/var/named/{data,slaves} +install -m 644 %{SOURCE25} sample/etc/named.conf +# Copy default configuration to %%doc to make it usable from system-config-bind +install -m 644 %{SOURCE16} named.conf.default +install -m 644 %{SOURCE23} sample/etc/named.rfc1912.zones +install -m 644 %{SOURCE17} sample/var/named/named.ca +for f in my.internal.zone.db slaves/my.slave.internal.zone.db slaves/my.ddns.internal.zone.db my.external.zone.db; do + echo '@ in soa localhost. root 1 3H 15M 1W 1D + ns localhost.' > sample/var/named/$f; +done +:; + +mkdir -p ${RPM_BUILD_ROOT}%{_tmpfilesdir} +install -m 644 %{SOURCE35} ${RPM_BUILD_ROOT}%{_tmpfilesdir}/named.conf + +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/rwtab.d +install -m 644 %{SOURCE43} ${RPM_BUILD_ROOT}%{_sysconfdir}/rwtab.d/named + +%pre +if [ "$1" -eq 1 ]; then + /usr/sbin/groupadd -g %{bind_gid} -f -r named >/dev/null 2>&1 || :; + /usr/sbin/useradd -u %{bind_uid} -r -N -M -g named -s /sbin/nologin -d /var/named -c Named named >/dev/null 2>&1 || :; +fi; +:; + +%post +%?ldconfig +if [ -e "%{_sysconfdir}/selinux/config" ]; then + %selinux_set_booleans -s targeted %{selinuxbooleans} + %selinux_set_booleans -s mls %{selinuxbooleans} +fi +if [ "$1" -eq 1 ]; then + # Initial installation + [ -x /sbin/restorecon ] && /sbin/restorecon /etc/rndc.* /etc/named.* >/dev/null 2>&1 ; + # rndc.key has to have correct perms and ownership, CVE-2007-6283 + [ -e /etc/rndc.key ] && chown root:named /etc/rndc.key + [ -e /etc/rndc.key ] && chmod 0640 /etc/rndc.key +else + # Upgrade, use invalid shell + if getent passwd named | grep ':/bin/false$' >/dev/null; then + /sbin/usermod -s /sbin/nologin named + fi + # Checkconf will parse out comments + if /usr/bin/named-checkconf -p /etc/named.conf 2>/dev/null | grep -q named.iscdlv.key + then + echo "Replacing obsolete named.iscdlv.key with named.root.key..." + if cp -Rf --preserve=all --remove-destination /etc/named.conf /etc/named.conf.rpmbackup; then + sed -e 's/named\.iscdlv\.key/named.root.key/' \ + /etc/named.conf.rpmbackup > /etc/named.conf || \ + mv /etc/named.conf.rpmbackup /etc/named.conf + fi + fi +fi +%systemd_post named.service +:; + +%preun +# Package removal, not upgrade +%systemd_preun named.service + +%postun +%?ldconfig +# Package upgrade, not uninstall +%systemd_postun_with_restart named.service +if [ -e "%{_sysconfdir}/selinux/config" ]; then + %selinux_unset_booleans -s targeted %{selinuxbooleans} + %selinux_unset_booleans -s mls %{selinuxbooleans} +fi + + +# Fix permissions on existing device files on upgrade +%define chroot_fix_devices() \ +if [ $1 -gt 1 ]; then \ + for DEV in "%{1}/dev"/{null,random,zero}; do \ + if [ -e "$DEV" ] && [ "$(/bin/stat --printf="%G %a" "$DEV")" = "root 644" ]; \ + then \ + /bin/chmod 0664 "$DEV" \ + /bin/chgrp named "$DEV" \ + fi \ + done \ +fi + +%triggerun -- bind < 32:9.9.0-0.6.rc1 +/sbin/chkconfig --del named >/dev/null 2>&1 || : +/bin/systemctl try-restart named.service >/dev/null 2>&1 || : + +%ldconfig_scriptlets libs + + + +%post chroot +%systemd_post named-chroot.service +%chroot_fix_devices %{chroot_prefix} +:; + +%posttrans chroot +if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then + [ -x /sbin/restorecon ] && /sbin/restorecon %{chroot_prefix}/dev/* > /dev/null 2>&1; +fi; + +%preun chroot +# wait for stop of both named-chroot and named-chroot-setup services +# on uninstall +%systemd_preun named-chroot.service named-chroot-setup.service +:; + +%postun chroot +# Package upgrade, not uninstall +%systemd_postun_with_restart named-chroot.service + + +%files +%dir %{_libdir}/bind +%dir %{_libdir}/named +%{_libdir}/bind/filter*.so +%config(noreplace) %verify(not md5 size mtime) %{_sysconfdir}/sysconfig/named +%config(noreplace) %attr(0644,root,named) %{_sysconfdir}/named.root.key +%config(noreplace) %{_sysconfdir}/logrotate.d/named +%{_tmpfilesdir}/named.conf +%{_sysconfdir}/rwtab.d/named +%{_unitdir}/named.service +%{_unitdir}/named-setup-rndc.service +%{_bindir}/named-journalprint +%{_bindir}/named-checkconf +%{_bindir}/named-rrchecker +%{_bindir}/mdig +%{_sbindir}/named +%{_sbindir}/rndc* +%{_sbindir}/named-checkconf +%{_libexecdir}/generate-rndc-key.sh +%{_libexecdir}/setup-named-softhsm.sh +%{_mandir}/man1/mdig.1* +%{_mandir}/man1/named-rrchecker.1* +%{_mandir}/man5/named.conf.5* +%{_mandir}/man5/rndc.conf.5* +%{_mandir}/man8/rndc.8* +%{_mandir}/man8/named.8* +%{_mandir}/man1/named-checkconf.1* +%{_mandir}/man8/rndc-confgen.8* +%{_mandir}/man1/named-journalprint.1* +%{_mandir}/man8/filter-*.8.* +%doc CHANGES README.md named.conf.default +%doc sample/ + +# Hide configuration +%defattr(0640,root,named,0750) +%dir %{_sysconfdir}/named +%config(noreplace) %verify(not link) %{_sysconfdir}/named.conf +%config(noreplace) %verify(not link) %{_sysconfdir}/named.rfc1912.zones +%defattr(0660,root,named,01770) +%dir %{_localstatedir}/named +%defattr(0660,named,named,0770) +%dir %{_localstatedir}/named/slaves +%dir %{_localstatedir}/named/data +%dir %{_localstatedir}/named/dynamic +%ghost %{_localstatedir}/log/named.log +%defattr(0640,root,named,0750) +%config %verify(not link) %{_localstatedir}/named/named.ca +%config %verify(not link) %{_localstatedir}/named/named.localhost +%config %verify(not link) %{_localstatedir}/named/named.loopback +%config %verify(not link) %{_localstatedir}/named/named.empty +%ghost %config(noreplace) %{_sysconfdir}/rndc.key +# ^- rndc.key now created on first install only if it does not exist +%ghost %config(noreplace) %{_sysconfdir}/rndc.conf +# ^- The default rndc.conf which uses rndc.key is in named's default internal config - +# so rndc.conf is not necessary. +%defattr(-,named,named,-) +%dir /run/named + +%files libs +%{_libdir}/libbind9-%{version}*.so +%{_libdir}/libisccc-%{version}*.so +%{_libdir}/libns-%{version}*.so +%{_libdir}/libdns-%{version}*.so +%{_libdir}/libirs-%{version}*.so +%{_libdir}/libisc-%{version}*.so +%{_libdir}/libisccfg-%{version}*.so + +%files license +%{!?_licensedir:%global license %%doc} +%license COPYRIGHT + +%files utils +%{_bindir}/dig +%{_bindir}/delv +%{_bindir}/host +%{_bindir}/nslookup +%{_bindir}/nsupdate +%{_bindir}/arpaname +%{_sbindir}/ddns-confgen +%{_sbindir}/tsig-keygen +%{_bindir}/nsec3hash +%{_bindir}/named-checkzone +%{_bindir}/named-compilezone +%{_sbindir}/named-checkzone +%{_sbindir}/named-compilezone +%if %{with DNSTAP} +%{_bindir}/dnstap-read +%{_mandir}/man1/dnstap-read.1* +%endif +%if %{with LMDB} +%{_bindir}/named-nzd2nzf +%{_mandir}/man1/named-nzd2nzf.1* +%endif +%{_mandir}/man1/host.1* +%{_mandir}/man1/nsupdate.1* +%{_mandir}/man1/dig.1* +%{_mandir}/man1/delv.1* +%{_mandir}/man1/nslookup.1* +%{_mandir}/man1/arpaname.1* +%{_mandir}/man8/ddns-confgen.8* +%{_mandir}/man8/tsig-keygen.8* +%{_mandir}/man1/nsec3hash.1* +%{_mandir}/man1/named-checkzone.1* +%{_mandir}/man1/named-compilezone.1* +%{_sysconfdir}/trusted-key.key + +%files dnssec-utils +%{_bindir}/dnssec* + +%files dnssec-doc +%{_mandir}/man1/dnssec*.1* + + +%files devel +%{_libdir}/libbind9.so +%{_libdir}/libisccc.so +%{_libdir}/libns.so +%{_libdir}/libdns.so +%{_libdir}/libirs.so +%{_libdir}/libisc.so +%{_libdir}/libisccfg.so +%dir %{_includedir}/bind9 +%{_includedir}/bind9/bind9 +%{_includedir}/bind9/isccc +%{_includedir}/bind9/ns +%{_includedir}/bind9/dns +%{_includedir}/bind9/dst +%{_includedir}/bind9/irs +%{_includedir}/bind9/isc + +%{_includedir}/bind9/isccfg + +%files chroot +%config(noreplace) %{_sysconfdir}/named-chroot.files +%{_unitdir}/named-chroot.service +%{_unitdir}/named-chroot-setup.service +%{_libexecdir}/setup-named-chroot.sh +%defattr(0664,root,named,-) +%ghost %dev(c,1,3) %verify(not mtime) %{chroot_prefix}/dev/null +%ghost %dev(c,1,8) %verify(not mtime) %{chroot_prefix}/dev/random +%ghost %dev(c,1,9) %verify(not mtime) %{chroot_prefix}/dev/urandom +%ghost %dev(c,1,5) %verify(not mtime) %{chroot_prefix}/dev/zero +%defattr(0640,root,named,0750) +%dir %{chroot_prefix} +%dir %{chroot_prefix}/dev +%dir %{chroot_prefix}%{_sysconfdir} +%dir %{chroot_prefix}%{_sysconfdir}/named +%dir %{chroot_prefix}%{_sysconfdir}/pki +%dir %{chroot_prefix}%{_sysconfdir}/pki/dnssec-keys +%dir %{chroot_prefix}%{_sysconfdir}/crypto-policies +%dir %{chroot_prefix}%{_sysconfdir}/crypto-policies/back-ends +%dir %{chroot_prefix}%{_localstatedir} +%dir %{chroot_prefix}/run +%ghost %config(noreplace) %{chroot_prefix}%{_sysconfdir}/named.conf +%defattr(-,root,root,-) +%dir %{chroot_prefix}/usr +%dir %{chroot_prefix}/%{_libdir} +%dir %{chroot_prefix}/%{_libdir}/bind +%dir %{chroot_prefix}/%{_datadir}/GeoIP +%{chroot_prefix}/proc +%defattr(0660,root,named,01770) +%dir %{chroot_prefix}%{_localstatedir}/named +%defattr(0660,named,named,0770) +%dir %{chroot_prefix}%{_localstatedir}/tmp +%dir %{chroot_prefix}%{_localstatedir}/log +%defattr(-,named,named,-) +%dir %{chroot_prefix}/run/named +%{chroot_prefix}%{_localstatedir}/run + + +%if %{with DLZ} +%files dlz-filesystem +%{_libdir}/{named,bind}/dlz_filesystem_dynamic.so + +%files dlz-mysql +%{_libdir}/{named,bind}/dlz_mysql_dynamic.so +%doc build/contrib/dlz/modules/doc/mysql +%{_libdir}/{named,bind}/dlz_mysqldyn_mod.so +%doc build/contrib/dlz/modules/doc/mysqldyn + +%files dlz-ldap +%{_libdir}/{named,bind}/dlz_ldap_dynamic.so +%doc contrib/dlz/modules/ldap/testing/* + +%endif + + +%if %{with DOC} +%files doc +%dir %{_pkgdocdir} +%doc %{_pkgdocdir}/Bv9ARM.html +%doc %{_pkgdocdir}/html +%endif +%if %{with DOCPDF} +%doc %{_pkgdocdir}/Bv9ARM.pdf +%endif + +%changelog +* Wed May 15 2024 tingyin.duan - 32:9.18.26-1 +- update to 9.18.26 + +* Wed Mar 27 2024 mgb01105731 - 32:9.18.21-1 +- update to 9.18.21 + +* Wed Dec 27 2023 Caspar Zhang - 32:9.18.16-2 +- Fix CVE-2023-3341 and CVE-2023-4236 + +* Thu Jun 22 2023 Funda Wang - 32:9.18.16-1 +- New version 9.18.16 + +* Wed Jun 07 2023 Funda Wang - 32:9.18.15-2 +- Fix executable path of systemd service files + +* Thu May 18 2023 Funda Wang - 32:9.18.15-1 +- New version 9.18.15 + +* Wed Apr 19 2023 Funda Wang - 32:9.18.14-1 +- New version 9.18.14 + +* Thu Dec 29 2022 Funda Wang - 32:9.18.10-1 +- New version 9.18.10 +- Do not build doc pdf as it imports too many build requires + +* Mon Aug 29 2022 Chunmei Xu - 32:9.18.6-1 +- update to 9.18.6 + +* Wed Mar 09 2022 DengXiewei - 32:9.18.0-1 +- Init from upstream 9.18.0 diff --git a/bind.tmpfiles.d b/bind.tmpfiles.d new file mode 100644 index 0000000000000000000000000000000000000000..640a656170fbb4ede4dd65aa2ff3f864a697f07d --- /dev/null +++ b/bind.tmpfiles.d @@ -0,0 +1 @@ +d /run/named 0755 named named - diff --git a/bind.yaml b/bind.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a6bede2b221fa262cf59c963f19cc003542cd8cd --- /dev/null +++ b/bind.yaml @@ -0,0 +1,4 @@ +version_control: git +src_repo: https://gitlab.isc.org/isc-projects/bind9.git +tag_prefix: bind9- +seperator: _ diff --git a/codesign2021.txt b/codesign2021.txt new file mode 100644 index 0000000000000000000000000000000000000000..d021b564512488bfecbd6a0083affd51d51f92d6 --- /dev/null +++ b/codesign2021.txt @@ -0,0 +1,534 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=fX+D +-----END PGP PUBLIC KEY BLOCK----- +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +4xcYgqlVpv15O7VrD+I= +=Uugw +-----END PGP PUBLIC KEY BLOCK----- diff --git a/generate-rndc-key.sh b/generate-rndc-key.sh new file mode 100755 index 0000000000000000000000000000000000000000..956bb8e4eaaadabcf5db36eb5ecdf307944dd90d --- /dev/null +++ b/generate-rndc-key.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +if [ -r /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +else +success() { + echo $" OK " +} + +failure() { + echo -n " " + echo $"FAILED" +} +fi + +# This script generates /etc/rndc.key if doesn't exist AND if there is no rndc.conf + +if [ ! -s /etc/rndc.key -a ! -s /etc/rndc.conf ]; then + echo -n $"Generating /etc/rndc.key:" + if /usr/sbin/rndc-confgen -a -A hmac-sha256 > /dev/null 2>&1 + then + chmod 640 /etc/rndc.key + chown root:named /etc/rndc.key + [ -x /sbin/restorecon ] && /sbin/restorecon /etc/rndc.key + success $"/etc/rndc.key generation" + echo + else + rc=$? + failure $"/etc/rndc.key generation" + echo + exit $rc + fi +fi diff --git a/ldap2zone.c b/ldap2zone.c new file mode 100644 index 0000000000000000000000000000000000000000..80e79199df9ff4eabec21cdecc1af2f3c7ff7b78 --- /dev/null +++ b/ldap2zone.c @@ -0,0 +1,411 @@ +/* + * Copyright (C) 2004, 2005 Stig Venaas + * $Id: ldap2zone.c,v 1.1 2007/07/24 15:18:00 atkac Exp $ + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#define LDAP_DEPRECATED 1 + +#include +#include +#include +#include + +#include + +struct string { + void *data; + size_t len; +}; + +struct assstack_entry { + struct string key; + struct string val; + struct assstack_entry *next; +}; + +struct assstack_entry *assstack_find(struct assstack_entry *stack, struct string *key); +void assstack_push(struct assstack_entry **stack, struct assstack_entry *item); +void assstack_insertbottom(struct assstack_entry **stack, struct assstack_entry *item); +void printsoa(struct string *soa); +void printrrs(char *defaultttl, struct assstack_entry *item); +void print_zone(char *defaultttl, struct assstack_entry *stack); +void usage(char *name); +void err(char *name, const char *msg); +int putrr(struct assstack_entry **stack, struct berval *name, char *type, char *ttl, struct berval *val); + +struct assstack_entry *assstack_find(struct assstack_entry *stack, struct string *key) { + for (; stack; stack = stack->next) + if (stack->key.len == key->len && !memcmp(stack->key.data, key->data, key->len)) + return stack; + return NULL; +} + +void assstack_push(struct assstack_entry **stack, struct assstack_entry *item) { + item->next = *stack; + *stack = item; +} + +void assstack_insertbottom(struct assstack_entry **stack, struct assstack_entry *item) { + struct assstack_entry *p; + + item->next = NULL; + if (!*stack) { + *stack = item; + return; + } + /* find end, should keep track of end somewhere */ + /* really a queue, not a stack */ + p = *stack; + while (p->next) + p = p->next; + p->next = item; +} + +void printsoa(struct string *soa) { + char *s; + size_t i; + + s = (char *)soa->data; + i = 0; + while (i < soa->len) { + putchar(s[i]); + if (s[i++] == ' ') + break; + } + while (i < soa->len) { + putchar(s[i]); + if (s[i++] == ' ') + break; + } + printf("(\n\t\t\t\t"); + while (i < soa->len) { + putchar(s[i]); + if (s[i++] == ' ') + break; + } + printf("; Serialnumber\n\t\t\t\t"); + while (i < soa->len) { + if (s[i] == ' ') + break; + putchar(s[i++]); + } + i++; + printf("\t; Refresh\n\t\t\t\t"); + while (i < soa->len) { + if (s[i] == ' ') + break; + putchar(s[i++]); + } + i++; + printf("\t; Retry\n\t\t\t\t"); + while (i < soa->len) { + if (s[i] == ' ') + break; + putchar(s[i++]); + } + i++; + printf("\t; Expire\n\t\t\t\t"); + while (i < soa->len) { + putchar(s[i++]); + } + printf(" )\t; Minimum TTL\n"); +} + +void printrrs(char *defaultttl, struct assstack_entry *item) { + struct assstack_entry *stack; + char *s; + int first; + size_t i; + char *ttl, *type; + int top; + + s = (char *)item->key.data; + + if (item->key.len == 1 && *s == '@') { + top = 1; + printf("@\t"); + } else { + top = 0; + for (i = 0; i < item->key.len; i++) + putchar(s[i]); + if (item->key.len < 8) + putchar('\t'); + putchar('\t'); + } + + first = 1; + for (stack = (struct assstack_entry *) item->val.data; stack; stack = stack->next) { + ttl = (char *)stack->key.data; + s = strchr(ttl, ' '); + *s++ = '\0'; + type = s; + + if (first) + first = 0; + else + printf("\t\t"); + + if (strcmp(defaultttl, ttl)) + printf("%s", ttl); + putchar('\t'); + + if (top) { + top = 0; + printf("IN\t%s\t", type); + /* Should always be SOA here */ + if (!strcmp(type, "SOA")) { + printsoa(&stack->val); + continue; + } + } else + printf("%s\t", type); + + s = (char *)stack->val.data; + for (i = 0; i < stack->val.len; i++) + putchar(s[i]); + putchar('\n'); + } +} + +void print_zone(char *defaultttl, struct assstack_entry *stack) { + printf("$TTL %s\n", defaultttl); + for (; stack; stack = stack->next) + printrrs(defaultttl, stack); +}; + +void usage(char *name) { + fprintf(stderr, "Usage:%s zone-name LDAP-URL default-ttl [serial]\n", name); + exit(1); +}; + +void err(char *name, const char *msg) { + fprintf(stderr, "%s: %s\n", name, msg); + exit(1); +}; + +int putrr(struct assstack_entry **stack, struct berval *name, char *type, char *ttl, struct berval *val) { + struct string key; + struct assstack_entry *rr, *rrdata; + + /* Do nothing if name or value have 0 length */ + if (!name->bv_len || !val->bv_len) + return 0; + + /* see if already have an entry for this name */ + key.len = name->bv_len; + key.data = name->bv_val; + + rr = assstack_find(*stack, &key); + if (!rr) { + /* Not found, create and push new entry */ + rr = (struct assstack_entry *) malloc(sizeof(struct assstack_entry)); + if (!rr) + return -1; + rr->key.len = name->bv_len; + rr->key.data = (void *) malloc(rr->key.len); + if (!rr->key.data) { + free(rr); + return -1; + } + memcpy(rr->key.data, name->bv_val, name->bv_len); + rr->val.len = sizeof(void *); + rr->val.data = NULL; + if (name->bv_len == 1 && *(char *)name->bv_val == '@') + assstack_push(stack, rr); + else + assstack_insertbottom(stack, rr); + } + + rrdata = (struct assstack_entry *) malloc(sizeof(struct assstack_entry)); + if (!rrdata) { + free(rr->key.data); + free(rr); + return -1; + } + rrdata->key.len = strlen(type) + strlen(ttl) + 1; + rrdata->key.data = (void *) malloc(rrdata->key.len); + if (!rrdata->key.data) { + free(rrdata); + free(rr->key.data); + free(rr); + return -1; + } + sprintf((char *)rrdata->key.data, "%s %s", ttl, type); + + rrdata->val.len = val->bv_len; + rrdata->val.data = (void *) malloc(val->bv_len); + if (!rrdata->val.data) { + free(rrdata->key.data); + free(rrdata); + free(rr->key.data); + free(rr); + return -1; + } + memcpy(rrdata->val.data, val->bv_val, val->bv_len); + + if (!strcmp(type, "SOA")) + assstack_push((struct assstack_entry **) &(rr->val.data), rrdata); + else + assstack_insertbottom((struct assstack_entry **) &(rr->val.data), rrdata); + return 0; +} + +int main(int argc, char **argv) { + char *s, *hostporturl, *base = NULL; + char *ttl, *defaultttl; + LDAP *ld; + char *fltr = NULL; + LDAPMessage *res, *e; + char *a, **ttlvals, **soavals, *serial; + struct berval **vals, **names; + char type[64]; + BerElement *ptr; + int i, j, rc, msgid; + struct assstack_entry *zone = NULL; + + if (argc < 4 || argc > 5) + usage(argv[0]); + + hostporturl = argv[2]; + + if (hostporturl != strstr( hostporturl, "ldap")) + err(argv[0], "Not an LDAP URL"); + + s = strchr(hostporturl, ':'); + + if (!s || strlen(s) < 3 || s[1] != '/' || s[2] != '/') + err(argv[0], "Not an LDAP URL"); + + s = strchr(s+3, '/'); + if (s) { + *s++ = '\0'; + base = s; + s = strchr(base, '?'); + if (s) + err(argv[0], "LDAP URL can only contain host, port and base"); + } + + defaultttl = argv[3]; + + rc = ldap_initialize(&ld, hostporturl); + if (rc != LDAP_SUCCESS) + err(argv[0], "ldap_initialize() failed"); + + if (argc == 5) { + /* serial number specified, check if different from one in SOA */ + fltr = (char *)malloc(strlen(argv[1]) + strlen("(&(relativeDomainName=@)(zoneName=))") + 1); + sprintf(fltr, "(&(relativeDomainName=@)(zoneName=%s))", argv[1]); + msgid = ldap_search(ld, base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0); + if (msgid == -1) + err(argv[0], "ldap_search() failed"); + + while ((rc = ldap_result(ld, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) { + /* not supporting continuation references at present */ + if (rc != LDAP_RES_SEARCH_ENTRY) + err(argv[0], "ldap_result() returned cont.ref? Exiting"); + + /* only one entry per result message */ + e = ldap_first_entry(ld, res); + if (e == NULL) { + ldap_msgfree(res); + err(argv[0], "ldap_first_entry() failed"); + } + + soavals = ldap_get_values(ld, e, "SOARecord"); + if (soavals) + break; + } + + ldap_msgfree(res); + if (!soavals) { + err(argv[0], "No SOA Record found"); + } + + /* We have a SOA, compare serial numbers */ + /* Only checkinf first value, should be only one */ + s = strchr(soavals[0], ' '); + s++; + s = strchr(s, ' '); + s++; + serial = s; + s = strchr(s, ' '); + *s = '\0'; + if (!strcmp(serial, argv[4])) { + ldap_value_free(soavals); + err(argv[0], "serial numbers match"); + } + ldap_value_free(soavals); + } + + if (!fltr) + fltr = (char *)malloc(strlen(argv[1]) + strlen("(zoneName=)") + 1); + if (!fltr) + err(argv[0], "Malloc failed"); + sprintf(fltr, "(zoneName=%s)", argv[1]); + + msgid = ldap_search(ld, base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0); + if (msgid == -1) + err(argv[0], "ldap_search() failed"); + + while ((rc = ldap_result(ld, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) { + /* not supporting continuation references at present */ + if (rc != LDAP_RES_SEARCH_ENTRY) + err(argv[0], "ldap_result() returned cont.ref? Exiting"); + + /* only one entry per result message */ + e = ldap_first_entry(ld, res); + if (e == NULL) { + ldap_msgfree(res); + err(argv[0], "ldap_first_entry() failed"); + } + + names = ldap_get_values_len(ld, e, "relativeDomainName"); + if (!names) + continue; + + ttlvals = ldap_get_values(ld, e, "dNSTTL"); + ttl = ttlvals ? ttlvals[0] : defaultttl; + + for (a = ldap_first_attribute(ld, e, &ptr); a != NULL; a = ldap_next_attribute(ld, e, ptr)) { + char *s; + + for (s = a; *s; s++) + *s = toupper(*s); + s = strstr(a, "RECORD"); + if ((s == NULL) || (s == a) || (s - a >= (signed int)sizeof(type))) { + ldap_memfree(a); + continue; + } + + strncpy(type, a, s - a); + type[s - a] = '\0'; + vals = ldap_get_values_len(ld, e, a); + if (vals) { + for (i = 0; vals[i]; i++) + for (j = 0; names[j]; j++) + if (putrr(&zone, names[j], type, ttl, vals[i])) + err(argv[0], "malloc failed"); + ldap_value_free_len(vals); + } + ldap_memfree(a); + } + + if (ptr) + ber_free(ptr, 0); + if (ttlvals) + ldap_value_free(ttlvals); + ldap_value_free_len(names); + /* free this result */ + ldap_msgfree(res); + } + + /* free final result */ + ldap_msgfree(res); + + print_zone(defaultttl, zone); + return 0; +} diff --git a/makefile-replace-libs.py b/makefile-replace-libs.py new file mode 100755 index 0000000000000000000000000000000000000000..86689a4009ed7b111f798035fe3f331afb8157fd --- /dev/null +++ b/makefile-replace-libs.py @@ -0,0 +1,127 @@ +#!/usr/bin/python3 + +import re +import argparse + +""" +Script for replacing Makefile ISC_INCLUDES with runtime flags. + +Should translate part of Makefile to use isc-config.sh instead static linked sources. +ISC_INCLUDES = -I/home/pemensik/rhel/bind/bind-9.11.12/build/lib/isc/include \ + -I${top_srcdir}/lib/isc \ + -I${top_srcdir}/lib/isc/include \ + -I${top_srcdir}/lib/isc/unix/include \ + -I${top_srcdir}/lib/isc/pthreads/include \ + -I${top_srcdir}/lib/isc/x86_32/include + +Should be translated to: +ISC_INCLUDES = $(shell isc-config.sh --cflags isc) +""" + +def isc_config(mode, lib): + if mode: + return '$(shell isc-config.sh {mode} {lib})'.format(mode=mode, lib=lib) + else: + return '' + +def check_match(match, debug=False): + """ + Check this definition is handled by internal library + """ + if not match: + return False + lib = match.group(2).lower() + ok = not lib_filter or lib in lib_filter + if debug: + print('{status} {lib}: {text}'.format(status=ok, lib=lib, text=match.group(1))) + return ok + +def fix_line(match, mode): + lib = match.group(2).lower() + return match.group(1)+isc_config(mode, lib)+"\n" + +def fix_file_lines(path, debug=False): + """ + Opens file and scans fixes selected parameters + + Returns list of lines if something should be changed, + None if no action is required + """ + fixed = [] + changed = False + with open(path, 'r') as fin: + fout = None + + line = next(fin, None) + while line: + appended = False + while line.endswith("\\\n"): + line += next(fin, None) + + inc = re_includes.match(line) + deplibs = re_deplibs.match(line) + libs = re_libs.match(line) + newline = None + if check_match(inc, debug=debug): + newline = fix_line(inc, '--cflags') + elif check_match(deplibs, debug=debug): + newline = fix_line(libs, None) + elif check_match(libs, debug=debug): + newline = fix_line(libs, '--libs') + + if newline and line != newline: + changed = True + line = newline + + fixed.append(line) + line = next(fin, None) + + if not changed: + return None + else: + return fixed + +def write_lines(path, lines): + fout = open(path, 'w') + for line in lines: + fout.write(line) + fout.close() + +def print_lines(lines): + for line in lines: + print(line, end='') + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Makefile multiline include replacer') + parser.add_argument('files', nargs='+') + parser.add_argument('--filter', type=str, + default='isc isccc isccfg dns lwres bind9 irs', + help='List of libraries supported by isc-config.sh') + parser.add_argument('--check', action='store_true', + help='Test file only') + parser.add_argument('--print', action='store_true', + help='Print changed file only') + parser.add_argument('--debug', action='store_true', + help='Enable debug outputs') + + args = parser.parse_args() + lib_filter = None + + re_includes = re.compile(r'^\s*((\w+)_INCLUDES\s+=\s*).*') + re_deplibs = re.compile(r'^\s*((\w+)DEPLIBS\s*=).*') + re_libs = re.compile(r'^\s*((\w+)LIBS\s*=).*') + + if args.filter: + lib_filter = set(args.filter.split(' ')) + pass + + for path in args.files: + lines = fix_file_lines(path, debug=args.debug) + if lines: + if args.print: + print_lines(lines) + elif not args.check: + write_lines(path, lines) + print('File {path} was fixed'.format(path=path)) + else: + print('File {path} does not need fixing'.format(path=path)) diff --git a/named-chroot-setup.service b/named-chroot-setup.service new file mode 100644 index 0000000000000000000000000000000000000000..237a909299b5648a8aa458e959c6d1d0210e890b --- /dev/null +++ b/named-chroot-setup.service @@ -0,0 +1,12 @@ +[Unit] +Description=Set-up/destroy chroot environment for named (DNS) +BindsTo=named-chroot.service +Wants=named-setup-rndc.service +After=named-setup-rndc.service + + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/libexec/setup-named-chroot.sh /var/named/chroot on /etc/named-chroot.files +ExecStop=/usr/libexec/setup-named-chroot.sh /var/named/chroot off /etc/named-chroot.files diff --git a/named-chroot.files b/named-chroot.files new file mode 100644 index 0000000000000000000000000000000000000000..9a768e4b7705afb6a911fbe69160ad849090ec43 --- /dev/null +++ b/named-chroot.files @@ -0,0 +1,26 @@ +# Configuration of files used in chroot +# Following files are made available after named-chroot.service start +# if they are missing or empty in target directory. +/etc/localtime +/etc/named.root.key +/etc/named.conf +/etc/named.rfc1912.zones +/etc/rndc.conf +/etc/rndc.key +/etc/named.iscdlv.key +/etc/crypto-policies/back-ends/bind.config +/etc/protocols +/etc/services +/etc/named.dnssec.keys +/etc/pki/dnssec-keys +/etc/named +/usr/lib64/bind +/usr/lib/bind +/usr/lib64/named +/usr/lib/named +/usr/share/GeoIP +/run/named +# Warning: the order is important +# If a directory containing $ROOTDIR is listed here, +# it MUST be listed last. (/var/named contains /var/named/chroot) +/var/named diff --git a/named-chroot.service b/named-chroot.service new file mode 100644 index 0000000000000000000000000000000000000000..a49df15c58fe7072ab2cccc83292439922536139 --- /dev/null +++ b/named-chroot.service @@ -0,0 +1,30 @@ +# Don't forget to add "$AddUnixListenSocket /var/named/chroot/dev/log" +# line to your /etc/rsyslog.conf file. Otherwise your logging becomes +# broken when rsyslogd daemon is restarted (due update, for example). + +[Unit] +Description=Berkeley Internet Name Domain (DNS) +Wants=nss-lookup.target +Requires=named-chroot-setup.service +Before=nss-lookup.target +After=named-chroot-setup.service +After=network.target + +[Service] +Type=forking +Environment=NAMEDCONF=/etc/named.conf +EnvironmentFile=-/etc/sysconfig/named +Environment=KRB5_KTNAME=/etc/named.keytab +PIDFile=/var/named/chroot/run/named/named.pid + +ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -t /var/named/chroot -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi' +ExecStart=/usr/sbin/named -u named -c ${NAMEDCONF} -t /var/named/chroot $OPTIONS + +ExecReload=/bin/sh -c 'if /usr/sbin/rndc null > /dev/null 2>&1; then /usr/sbin/rndc reload; else /bin/kill -HUP $MAINPID; fi' + +ExecStop=/bin/sh -c '/usr/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID' + +PrivateTmp=false + +[Install] +WantedBy=multi-user.target diff --git a/named-pkcs11.service b/named-pkcs11.service new file mode 100644 index 0000000000000000000000000000000000000000..27e06935caf9dcb80b41b4e36635de1931bd09bc --- /dev/null +++ b/named-pkcs11.service @@ -0,0 +1,26 @@ +[Unit] +Description=Berkeley Internet Name Domain (DNS) with native PKCS#11 +Wants=nss-lookup.target +Wants=named-setup-rndc.service +Before=nss-lookup.target +After=network.target +After=named-setup-rndc.service + +[Service] +Type=forking +Environment=NAMEDCONF=/etc/named.conf +EnvironmentFile=-/etc/sysconfig/named +Environment=KRB5_KTNAME=/etc/named.keytab +PIDFile=/run/named/named.pid + +ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi' +ExecStart=/usr/sbin/named-pkcs11 -u named -c ${NAMEDCONF} $OPTIONS + +ExecReload=/bin/sh -c 'if /usr/sbin/rndc null > /dev/null 2>&1; then /usr/sbin/rndc reload; else /bin/kill -HUP $MAINPID; fi' + +ExecStop=/bin/sh -c '/usr/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID' + +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/named-setup-rndc.service b/named-setup-rndc.service new file mode 100644 index 0000000000000000000000000000000000000000..ff85e3c745634227df913d775f14d075d3c9730a --- /dev/null +++ b/named-setup-rndc.service @@ -0,0 +1,7 @@ +[Unit] +Description=Generate rndc key for BIND (DNS) + +[Service] +Type=oneshot + +ExecStart=/usr/libexec/generate-rndc-key.sh diff --git a/named.conf b/named.conf new file mode 100644 index 0000000000000000000000000000000000000000..d62d3890cedc5b72cdcd0f6a9f981b8902a28ba8 --- /dev/null +++ b/named.conf @@ -0,0 +1,57 @@ +// +// named.conf +// +// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS +// server as a caching only nameserver (as a localhost DNS resolver only). +// +// See /usr/share/doc/bind*/sample/ for example named configuration files. +// + +options { + listen-on port 53 { 127.0.0.1; }; + listen-on-v6 port 53 { ::1; }; + directory "/var/named"; + dump-file "/var/named/data/cache_dump.db"; + statistics-file "/var/named/data/named_stats.txt"; + memstatistics-file "/var/named/data/named_mem_stats.txt"; + secroots-file "/var/named/data/named.secroots"; + recursing-file "/var/named/data/named.recursing"; + allow-query { localhost; }; + + /* + - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion. + - If you are building a RECURSIVE (caching) DNS server, you need to enable + recursion. + - If your recursive DNS server has a public IP address, you MUST enable access + control to limit queries to your legitimate users. Failing to do so will + cause your server to become part of large scale DNS amplification + attacks. Implementing BCP38 within your network would greatly + reduce such attack surface + */ + recursion yes; + + dnssec-validation yes; + + managed-keys-directory "/var/named/dynamic"; + + pid-file "/run/named/named.pid"; + session-keyfile "/run/named/session.key"; + + include "/etc/crypto-policies/back-ends/bind.config"; +}; + +logging { + channel default_debug { + file "data/named.run"; + severity dynamic; + }; +}; + +zone "." IN { + type hint; + file "named.ca"; +}; + +include "/etc/named.rfc1912.zones"; +include "/etc/named.root.key"; + diff --git a/named.conf.sample b/named.conf.sample new file mode 100644 index 0000000000000000000000000000000000000000..a49004ec850cae45c50f328a670d49d3d7cb401c --- /dev/null +++ b/named.conf.sample @@ -0,0 +1,241 @@ +/* + Sample named.conf BIND DNS server 'named' configuration file + for the Red Hat BIND distribution. + + See the BIND Administrator's Reference Manual (ARM) for details, in: + file:///usr/share/doc/bind-{version}/arm/Bv9ARM.html + Also see the BIND Configuration GUI : /usr/bin/system-config-bind and + its manual. +*/ + +options +{ + // Put files that named is allowed to write in the data/ directory: + directory "/var/named"; // "Working" directory + dump-file "data/cache_dump.db"; + statistics-file "data/named_stats.txt"; + memstatistics-file "data/named_mem_stats.txt"; + secroots-file "data/named.secroots"; + recursing-file "data/named.recursing"; + + + /* + Specify listenning interfaces. You can use list of addresses (';' is + delimiter) or keywords "any"/"none" + */ + //listen-on port 53 { any; }; + listen-on port 53 { 127.0.0.1; }; + + //listen-on-v6 port 53 { any; }; + listen-on-v6 port 53 { ::1; }; + + /* + Access restrictions + + There are two important options: + allow-query { argument; }; + - allow queries for authoritative data + + allow-query-cache { argument; }; + - allow queries for non-authoritative data (mostly cached data) + + You can use address, network address or keywords "any"/"localhost"/"none" as argument + Examples: + allow-query { localhost; 10.0.0.1; 192.168.1.0/8; }; + allow-query-cache { ::1; fe80::5c63:a8ff:fe2f:4526; 10.0.0.1; }; + */ + + allow-query { localhost; }; + allow-query-cache { localhost; }; + + /* Enable/disable recursion - recursion yes/no; + + - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion. + - If you are building a RECURSIVE (caching) DNS server, you need to enable + recursion. + - If your recursive DNS server has a public IP address, you MUST enable access + control to limit queries to your legitimate users. Failing to do so will + cause your server to become part of large scale DNS amplification + attacks. Implementing BCP38 within your network would greatly + reduce such attack surface + */ + recursion yes; + + /* DNSSEC related options. See information about keys ("Trusted keys", bellow) */ + + /* Enable DNSSEC validation on recursive servers */ + dnssec-validation yes; + + /* In Fedora we use /run/named instead of default /var/run/named + so we have to configure paths properly. */ + pid-file "/run/named/named.pid"; + session-keyfile "/run/named/session.key"; + + managed-keys-directory "/var/named/dynamic"; + + include "/etc/crypto-policies/back-ends/bind.config"; +}; + +logging +{ +/* If you want to enable debugging, eg. using the 'rndc trace' command, + * named will try to write the 'named.run' file in the $directory (/var/named). + * By default, SELinux policy does not allow named to modify the /var/named directory, + * so put the default debug log file in data/ : + */ + channel default_debug { + file "data/named.run"; + severity dynamic; + }; +}; + +/* + Views let a name server answer a DNS query differently depending on who is asking. + + By default, if named.conf contains no "view" clauses, all zones are in the + "default" view, which matches all clients. + + Views are processed sequentially. The first match is used so the last view should + match "any" - it's fallback and the most restricted view. + + If named.conf contains any "view" clause, then all zones MUST be in a view. +*/ + +view "localhost_resolver" +{ +/* This view sets up named to be a localhost resolver ( caching only nameserver ). + * If all you want is a caching-only nameserver, then you need only define this view: + */ + match-clients { localhost; }; + recursion yes; + + # all views must contain the root hints zone: + zone "." IN { + type hint; + file "/var/named/named.ca"; + }; + + /* these are zones that contain definitions for all the localhost + * names and addresses, as recommended in RFC1912 - these names should + * not leak to the other nameservers: + */ + include "/etc/named.rfc1912.zones"; +}; +view "internal" +{ +/* This view will contain zones you want to serve only to "internal" clients + that connect via your directly attached LAN interfaces - "localnets" . + */ + match-clients { localnets; }; + recursion yes; + + zone "." IN { + type hint; + file "/var/named/named.ca"; + }; + + /* these are zones that contain definitions for all the localhost + * names and addresses, as recommended in RFC1912 - these names should + * not leak to the other nameservers: + */ + include "/etc/named.rfc1912.zones"; + + // These are your "authoritative" internal zones, and would probably + // also be included in the "localhost_resolver" view above : + + /* + NOTE for dynamic DNS zones and secondary zones: + + DO NOT USE SAME FILES IN MULTIPLE VIEWS! + + If you are using views and DDNS/secondary zones it is strongly + recommended to read FAQ on ISC site (www.isc.org), section + "Configuration and Setup Questions", questions + "How do I share a dynamic zone between multiple views?" and + "How can I make a server a slave for both an internal and an external + view at the same time?" + */ + + zone "my.internal.zone" { + type master; + file "my.internal.zone.db"; + }; + zone "my.slave.internal.zone" { + type slave; + file "slaves/my.slave.internal.zone.db"; + masters { /* put master nameserver IPs here */ 127.0.0.1; } ; + // put slave zones in the slaves/ directory so named can update them + }; + zone "my.ddns.internal.zone" { + type master; + allow-update { key ddns_key; }; + file "dynamic/my.ddns.internal.zone.db"; + // put dynamically updateable zones in the slaves/ directory so named can update them + }; +}; + +key ddns_key +{ + algorithm hmac-sha256; + secret "use /usr/sbin/ddns-confgen to generate TSIG keys"; +}; + +view "external" +{ +/* This view will contain zones you want to serve only to "external" clients + * that have addresses that are not match any above view: + */ + match-clients { any; }; + + zone "." IN { + type hint; + file "/var/named/named.ca"; + }; + + recursion no; + // you'd probably want to deny recursion to external clients, so you don't + // end up providing free DNS service to all takers + + // These are your "authoritative" external zones, and would probably + // contain entries for just your web and mail servers: + + zone "my.external.zone" { + type master; + file "my.external.zone.db"; + }; +}; + +/* Trusted keys + + This statement contains DNSSEC keys. If you want DNSSEC aware resolver you + should configure at least one trusted key. + + Note that no key written below is valid. Especially root key because root zone + is not signed yet. +*/ +/* +trust-anchors { +// Root Key +. initial-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv + ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF + 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e + oZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfd + RUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwN + R1AkUTV74bU="; + +// Key for forward zone +example.com. static-key 257 3 8 "AwEAAZ0aqu1rJ6orJynrRfNpPmayJZoAx9Ic2/Rl9VQW + LMHyjxxem3VUSoNUIFXERQbj0A9Ogp0zDM9YIccKLRd6 + LmWiDCt7UJQxVdD+heb5Ec4qlqGmyX9MDabkvX2NvMws + UecbYBq8oXeTT9LRmCUt9KUt/WOi6DKECxoG/bWTykrX + yBR8elD+SQY43OAVjlWrVltHxgp4/rhBCvRbmdflunaP + Igu27eE2U4myDSLT8a4A0rB5uHG4PkOa9dIRs9y00M2m + Wf4lyPee7vi5few2dbayHXmieGcaAHrx76NGAABeY393 + xjlmDNcUkF1gpNWUla4fWZbbaYQzA93mLdrng+M="; + + +// Key for reverse zone. +2.0.192.IN-ADDRPA.NET. initial-ds 31406 8 2 "F78CF3344F72137235098ECBBD08947C2C9001C7F6A085A17F518B5D8F6B916D"; +}; +*/ diff --git a/named.empty b/named.empty new file mode 100644 index 0000000000000000000000000000000000000000..8e271e7e2a94ed03c338bc37b83dd8d27550b6b0 --- /dev/null +++ b/named.empty @@ -0,0 +1,10 @@ +$TTL 3H +@ IN SOA @ rname.invalid. ( + 0 ; serial + 1D ; refresh + 1H ; retry + 1W ; expire + 3H ) ; minimum + NS @ + A 127.0.0.1 + AAAA ::1 diff --git a/named.localhost b/named.localhost new file mode 100644 index 0000000000000000000000000000000000000000..6fe6a5258a5f54bd0a134389c0b9b5ee402d9a94 --- /dev/null +++ b/named.localhost @@ -0,0 +1,10 @@ +$TTL 1D +@ IN SOA @ rname.invalid. ( + 0 ; serial + 1D ; refresh + 1H ; retry + 1W ; expire + 3H ) ; minimum + NS @ + A 127.0.0.1 + AAAA ::1 diff --git a/named.logrotate b/named.logrotate new file mode 100644 index 0000000000000000000000000000000000000000..5df448f80a7be6f705a3a5b26acc352ed54a443f --- /dev/null +++ b/named.logrotate @@ -0,0 +1,12 @@ +/var/named/data/named.run { + missingok + su named named + create 0644 named named + postrotate + /usr/bin/systemctl reload named.service > /dev/null 2>&1 || true + /usr/bin/systemctl reload named-chroot.service > /dev/null 2>&1 || true + /usr/bin/systemctl reload named-sdb.service > /dev/null 2>&1 || true + /usr/bin/systemctl reload named-sdb-chroot.service > /dev/null 2>&1 || true + /usr/bin/systemctl reload named-pkcs11.service > /dev/null 2>&1 || true + endscript +} diff --git a/named.loopback b/named.loopback new file mode 100644 index 0000000000000000000000000000000000000000..7f3d862793a9485f95368cbfaf6d5a28eb719203 --- /dev/null +++ b/named.loopback @@ -0,0 +1,11 @@ +$TTL 1D +@ IN SOA @ rname.invalid. ( + 0 ; serial + 1D ; refresh + 1H ; retry + 1W ; expire + 3H ) ; minimum + NS @ + A 127.0.0.1 + AAAA ::1 + PTR localhost. diff --git a/named.rfc1912.zones b/named.rfc1912.zones new file mode 100644 index 0000000000000000000000000000000000000000..fa8caf58544eb06f96641a74456488b5dc0d4e7f --- /dev/null +++ b/named.rfc1912.zones @@ -0,0 +1,45 @@ +// named.rfc1912.zones: +// +// Provided by Red Hat caching-nameserver package +// +// ISC BIND named zone configuration for zones recommended by +// RFC 1912 section 4.1 : localhost TLDs and address zones +// and https://tools.ietf.org/html/rfc6303 +// (c)2007 R W Franks +// +// See /usr/share/doc/bind*/sample/ for example named configuration files. +// +// Note: empty-zones-enable yes; option is default. +// If private ranges should be forwarded, add +// disable-empty-zone "."; into options +// + +zone "localhost.localdomain" IN { + type master; + file "named.localhost"; + allow-update { none; }; +}; + +zone "localhost" IN { + type master; + file "named.localhost"; + allow-update { none; }; +}; + +zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" IN { + type master; + file "named.loopback"; + allow-update { none; }; +}; + +zone "1.0.0.127.in-addr.arpa" IN { + type master; + file "named.loopback"; + allow-update { none; }; +}; + +zone "0.in-addr.arpa" IN { + type master; + file "named.empty"; + allow-update { none; }; +}; diff --git a/named.root b/named.root new file mode 100644 index 0000000000000000000000000000000000000000..532d4ff82d011640092f69076eed290ed03a1077 --- /dev/null +++ b/named.root @@ -0,0 +1,61 @@ + +; <<>> DiG 9.11.3-RedHat-9.11.3-3.fc27 <<>> +bufsize=1200 +norec @a.root-servers.net +; (2 servers found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46900 +;; flags: qr aa; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 27 + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 1472 +;; QUESTION SECTION: +;. IN NS + +;; ANSWER SECTION: +. 518400 IN NS a.root-servers.net. +. 518400 IN NS b.root-servers.net. +. 518400 IN NS c.root-servers.net. +. 518400 IN NS d.root-servers.net. +. 518400 IN NS e.root-servers.net. +. 518400 IN NS f.root-servers.net. +. 518400 IN NS g.root-servers.net. +. 518400 IN NS h.root-servers.net. +. 518400 IN NS i.root-servers.net. +. 518400 IN NS j.root-servers.net. +. 518400 IN NS k.root-servers.net. +. 518400 IN NS l.root-servers.net. +. 518400 IN NS m.root-servers.net. + +;; ADDITIONAL SECTION: +a.root-servers.net. 518400 IN A 198.41.0.4 +b.root-servers.net. 518400 IN A 199.9.14.201 +c.root-servers.net. 518400 IN A 192.33.4.12 +d.root-servers.net. 518400 IN A 199.7.91.13 +e.root-servers.net. 518400 IN A 192.203.230.10 +f.root-servers.net. 518400 IN A 192.5.5.241 +g.root-servers.net. 518400 IN A 192.112.36.4 +h.root-servers.net. 518400 IN A 198.97.190.53 +i.root-servers.net. 518400 IN A 192.36.148.17 +j.root-servers.net. 518400 IN A 192.58.128.30 +k.root-servers.net. 518400 IN A 193.0.14.129 +l.root-servers.net. 518400 IN A 199.7.83.42 +m.root-servers.net. 518400 IN A 202.12.27.33 +a.root-servers.net. 518400 IN AAAA 2001:503:ba3e::2:30 +b.root-servers.net. 518400 IN AAAA 2001:500:200::b +c.root-servers.net. 518400 IN AAAA 2001:500:2::c +d.root-servers.net. 518400 IN AAAA 2001:500:2d::d +e.root-servers.net. 518400 IN AAAA 2001:500:a8::e +f.root-servers.net. 518400 IN AAAA 2001:500:2f::f +g.root-servers.net. 518400 IN AAAA 2001:500:12::d0d +h.root-servers.net. 518400 IN AAAA 2001:500:1::53 +i.root-servers.net. 518400 IN AAAA 2001:7fe::53 +j.root-servers.net. 518400 IN AAAA 2001:503:c27::2:30 +k.root-servers.net. 518400 IN AAAA 2001:7fd::1 +l.root-servers.net. 518400 IN AAAA 2001:500:9f::42 +m.root-servers.net. 518400 IN AAAA 2001:dc3::35 + +;; Query time: 24 msec +;; SERVER: 198.41.0.4#53(198.41.0.4) +;; WHEN: Thu Apr 05 15:57:34 CEST 2018 +;; MSG SIZE rcvd: 811 + diff --git a/named.root.key b/named.root.key new file mode 100644 index 0000000000000000000000000000000000000000..fbcb5d330a5caf230dc17aaadd03e2c4a33127b0 --- /dev/null +++ b/named.root.key @@ -0,0 +1,13 @@ +trust-anchors { + # ROOT KEYS: See https://data.iana.org/root-anchors/root-anchors.xml + # for current trust anchor information. + # + # This key (20326) was published in the root zone in 2017. + # Servers which were already using the old key (19036) should + # roll seamlessly to this new one via RFC 5011 rollover. Servers + # being set up for the first time can use the contents of this + # file as initializing keys; thereafter, the keys in the + # managed key database will be trusted and maintained + # automatically. + . initial-ds 20326 8 2 "E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D"; +}; diff --git a/named.rwtab b/named.rwtab new file mode 100644 index 0000000000000000000000000000000000000000..2cb3a41807f7e97dc018c50745cbe4d18b1509f2 --- /dev/null +++ b/named.rwtab @@ -0,0 +1,6 @@ +dirs /var/named + +files /var/named/named.ca +files /var/named/named.empty +files /var/named/named.localhost +files /var/named/named.loopback diff --git a/named.service b/named.service new file mode 100644 index 0000000000000000000000000000000000000000..7cd6d3452b318a774310db1705301f60f106fd7b --- /dev/null +++ b/named.service @@ -0,0 +1,25 @@ +[Unit] +Description=Berkeley Internet Name Domain (DNS) +Wants=nss-lookup.target +Wants=named-setup-rndc.service +Before=nss-lookup.target +After=named-setup-rndc.service +After=network.target + +[Service] +Type=forking +Environment=NAMEDCONF=/etc/named.conf +EnvironmentFile=-/etc/sysconfig/named +Environment=KRB5_KTNAME=/etc/named.keytab +PIDFile=/run/named/named.pid + +ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/sbin/named-checkconf -z "$NAMEDCONF"; else echo "Checking of zone files is disabled"; fi' +ExecStart=/usr/sbin/named -u named -c ${NAMEDCONF} $OPTIONS +ExecReload=/bin/sh -c 'if /usr/sbin/rndc null > /dev/null 2>&1; then /usr/sbin/rndc reload; else /bin/kill -HUP $MAINPID; fi' + +ExecStop=/bin/sh -c '/usr/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID' + +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/named.sysconfig b/named.sysconfig new file mode 100644 index 0000000000000000000000000000000000000000..5f6f81769fcac7b3ac6eb13fb3b5022c312007e1 --- /dev/null +++ b/named.sysconfig @@ -0,0 +1,17 @@ +# BIND named process options +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# OPTIONS="whatever" -- These additional options will be passed to named +# at startup. Don't add -t here, enable proper +# -chroot.service unit file. +# +# NAMEDCONF=/etc/named/alternate.conf +# -- Don't use -c to change configuration file. +# Extend systemd named.service instead or use this +# variable. +# +# DISABLE_ZONE_CHECKING -- By default, service file calls named-checkzone +# utility for every zone to ensure all zones are +# valid before named starts. If you set this option +# to 'yes' then service file doesn't perform those +# checks. diff --git a/setup-named-chroot.sh b/setup-named-chroot.sh new file mode 100755 index 0000000000000000000000000000000000000000..5e68915266c6e081e04893dad9a3f9f5c9846525 --- /dev/null +++ b/setup-named-chroot.sh @@ -0,0 +1,117 @@ +#!/bin/bash + +ROOTDIR="$1" +CONFIG_FILES="${3:-/etc/named-chroot.files}" + +usage() +{ + echo + echo 'This script setups chroot environment for BIND' + echo 'Usage: setup-named-chroot.sh ROOTDIR [chroot.files]' +} + +if ! [ "$#" -ge 2 -a "$#" -le 3 ]; then + echo 'Wrong number of arguments' + usage + exit 1 +fi + +# Exit if ROOTDIR doesn't exist +if ! [ -d "$ROOTDIR" ]; then + echo "Root directory $ROOTDIR doesn't exist" + usage + exit 1 +fi + +if ! [ -r "$CONFIG_FILES" ]; then + echo "Files list $CONFIG_FILES doesn't exist" 2>&1 + usage + exit 1 +fi + +dev_create() +{ + DEVNAME="$ROOTDIR/dev/$1" + shift + if ! [ -e "$DEVNAME" ]; then + /bin/mknod -m 0664 "$DEVNAME" $@ + /bin/chgrp named "$DEVNAME" + if [ -x /usr/sbin/selinuxenabled -a -x /sbin/restorecon ]; then + /usr/sbin/selinuxenabled && /sbin/restorecon "$DEVNAME" > /dev/null || : + fi + fi +} + +dev_chroot_prep() +{ + dev_create random c 1 8 + dev_create urandom c 1 9 + dev_create zero c 1 5 + dev_create null c 1 3 +} + +files_comment_filter() +{ + if [ -d "$1" ]; then + grep -v '^[[:space:]]*#' "$1"/*.files + else + grep -v '^[[:space:]]*#' "$1" + fi +} + +mount_chroot_conf() +{ + if [ -n "$ROOTDIR" ]; then + # Check devices are prepared + dev_chroot_prep + files_comment_filter "$CONFIG_FILES" | while read -r all; do + # Skip nonexistant files + [ -e "$all" ] || continue + + # If mount source is a file + if ! [ -d "$all" ]; then + # mount it only if it is not present in chroot or it is empty + if ! [ -e "$ROOTDIR$all" ] || [ `stat -c'%s' "$ROOTDIR$all"` -eq 0 ]; then + touch "$ROOTDIR$all" + mount --bind "$all" "$ROOTDIR$all" + fi + else + # Mount source is a directory. Mount it only if directory in chroot is + # empty. + if [ -e "$all" ] && [ `ls -1A $ROOTDIR$all | wc -l` -eq 0 ]; then + mount --bind --make-private "$all" "$ROOTDIR$all" + fi + fi + done + fi +} + +umount_chroot_conf() +{ + if [ -n "$ROOTDIR" ]; then + files_comment_filter "$CONFIG_FILES" | while read -r all; do + # Check if file is mount target. Do not use /proc/mounts because detecting + # of modified mounted files can fail. + if mount | grep -q '.* on '"$ROOTDIR$all"' .*'; then + umount "$ROOTDIR$all" + # Remove temporary created files + [ -f "$all" ] && rm -f "$ROOTDIR$all" + fi + done + fi +} + +case "$2" in + on) + mount_chroot_conf + ;; + off) + umount_chroot_conf + ;; + *) + echo 'Second argument has to be "on" or "off"' + usage + exit 1 +esac + +exit 0 diff --git a/setup-named-softhsm.sh b/setup-named-softhsm.sh new file mode 100755 index 0000000000000000000000000000000000000000..c0f8445a11b345773d385c3b614bdb27cc1736d1 --- /dev/null +++ b/setup-named-softhsm.sh @@ -0,0 +1,124 @@ +#!/bin/sh +# +# This script will initialise token storage of softhsm PKCS11 provider +# in custom location. Is useful to store tokens in non-standard location. +# +# Output can be evaluated from bash, it will prepare it for usage of temporary tokens. +# Quotes around eval are mandatory! +# Recommended use: +# eval "$(bash setup-named-softhsm.sh -A)" +# + +SOFTHSM2_CONF="$1" +TOKENPATH="$2" +GROUPNAME="$3" +# Do not use this script for real keys worth protection +# This is intended for crypto accelerators using PKCS11 interface. +# Uninitialized token would fail any crypto operation. +PIN=1234 +SO_PIN=1234 +LABEL=rpm + +set -e + +echo_i() +{ + echo "#" $@ +} + +random() +{ + if [ -x "$(which openssl 2>/dev/null)" ]; then + openssl rand -base64 $1 + else + dd if=/dev/urandom bs=1c count=$1 | base64 + fi +} + +usage() +{ + echo "Usage: $0 -A [token directory] [group]" + echo " or: $0 [group]" +} + +if [ "$SOFTHSM2_CONF" = "-A" -a -z "$TOKENPATH" ]; then + TOKENPATH=$(mktemp -d /var/tmp/softhsm-XXXXXX) +fi + +if [ -z "$SOFTHSM2_CONF" -o -z "$TOKENPATH" ]; then + usage >&2 + exit 1 +fi + +if [ "$SOFTHSM2_CONF" = "-A" ]; then + # Automagic mode instead + MODE=secure + SOFTHSM2_CONF="$TOKENPATH/softhsm2.conf" + PIN_SOURCE="$TOKENPATH/pin" + SOPIN_SOURCE="$TOKENPATH/so-pin" + TOKENPATH="$TOKENPATH/tokens" +else + MODE=legacy +fi + +[ -d "$TOKENPATH" ] || mkdir -p "$TOKENPATH" + +umask 0022 + +if ! [ -f "$SOFTHSM2_CONF" ]; then +cat << SED > "$SOFTHSM2_CONF" +# SoftHSM v2 configuration file + +directories.tokendir = ${TOKENPATH} +objectstore.backend = file + +# ERROR, WARNING, INFO, DEBUG +log.level = ERROR + +# If CKF_REMOVABLE_DEVICE flag should be set +slots.removable = false +SED +else + echo_i "Config file $SOFTHSM2_CONF already exists" >&2 +fi + +if [ -n "$PIN_SOURCE" ]; then + touch "$PIN_SOURCE" "$SOPIN_SOURCE" + chmod 0600 "$PIN_SOURCE" "$SOPIN_SOURCE" + if [ -n "$GROUPNAME" ]; then + chgrp "$GROUPNAME" "$PIN_SOURCE" "$SOPIN_SOURCE" + chmod g+r "$PIN_SOURCE" "$SOPIN_SOURCE" + fi +fi + +export SOFTHSM2_CONF + +if softhsm2-util --show-slots | grep 'Initialized:[[:space:]]*yes' > /dev/null +then + echo_i "Token in ${TOKENPATH} is already initialized" >&2 + + [ -f "$PIN_SOURCE" ] && PIN=$(cat "$PIN_SOURCE") + [ -f "$SOPIN_SOURCE" ] && SO_PIN=$(cat "$SOPIN_SOURCE") +else + PIN=$(random 6) + SO_PIN=$(random 18) + if [ -n "$PIN_SOURCE" ]; then + echo -n "$PIN" > "$PIN_SOURCE" + echo -n "$SO_PIN" > "$SOPIN_SOURCE" + fi + + echo_i "Initializing tokens to ${TOKENPATH}..." + softhsm2-util --init-token --free --label "$LABEL" --pin "$PIN" --so-pin "$SO_PIN" | sed -e 's/^/# /' + + if [ -n "$GROUPNAME" ]; then + chgrp -R -- "$GROUPNAME" "$TOKENPATH" + chmod -R -- g=rX,o= "$TOKENPATH" + fi +fi + +echo "export SOFTHSM2_CONF=\"$SOFTHSM2_CONF\"" +echo "export PIN_SOURCE=\"$PIN_SOURCE\"" +echo "export SOPIN_SOURCE=\"$SOPIN_SOURCE\"" +# These are intentionaly not exported +echo "PIN=\"$PIN\"" +echo "SO_PIN=\"$SO_PIN\"" diff --git a/softhsm2.conf.in b/softhsm2.conf.in new file mode 100644 index 0000000000000000000000000000000000000000..1f393201e6ed4b1d9ad001274bd4cc4e3579ff9e --- /dev/null +++ b/softhsm2.conf.in @@ -0,0 +1,10 @@ +# SoftHSM v2 configuration file + +directories.tokendir = @TOKENPATH@ +objectstore.backend = file + +# ERROR, WARNING, INFO, DEBUG +log.level = ERROR + +# If CKF_REMOVABLE_DEVICE flag should be set +slots.removable = false diff --git a/trusted-key.key b/trusted-key.key new file mode 100644 index 0000000000000000000000000000000000000000..7b845f3bd015275c66c23c8c09d4132c830fbb53 --- /dev/null +++ b/trusted-key.key @@ -0,0 +1 @@ +. 3600 IN DNSKEY 257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU=