mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 05:57:52 +00:00
[master] add hash to map files
3562. [func] Update map file header format to include a SHA-1 hash of the database content, so that corrupted map files can be rejected at load time. [RT #32459]
This commit is contained in:
parent
a4fe161bd3
commit
03b5d2689d
4
CHANGES
4
CHANGES
@ -1,3 +1,7 @@
|
||||
3562. [func] Update map file header format to include a SHA-1 hash
|
||||
of the database content, so that corrupted map files
|
||||
can be rejected at load time. [RT #32459]
|
||||
|
||||
3561. [bug] dig: issue a warning if an EDNS query returns FORMERR
|
||||
or NOTIMP. Adjust usage message. [RT #33363]
|
||||
|
||||
|
@ -31,5 +31,4 @@ rm -f ns2/formerly-text.db
|
||||
rm -f ns2/db-*
|
||||
rm -f ns2/large.bk
|
||||
rm -f ns3/example.db.map ns3/dynamic.db.map
|
||||
rm -f baseline.txt text.1 text.2 raw.1 raw.2 map.1 map.2
|
||||
|
||||
rm -f baseline.txt text.1 text.2 raw.1 raw.2 map.1 map.2 map.5 text.5 badmap
|
||||
|
@ -58,6 +58,16 @@ sourceserial () {
|
||||
}' < $1
|
||||
}
|
||||
|
||||
stomp () {
|
||||
perl -e 'open(my $file, "+<", $ARGV[0]);
|
||||
binmode $file;
|
||||
seek($file, $ARGV[1], 0);
|
||||
for (my $i = 0; $i < $ARGV[2]; $i++) {
|
||||
print $file pack('C', $ARGV[3]);
|
||||
}
|
||||
close($file);' $1 $2 $3 $4
|
||||
}
|
||||
|
||||
restart () {
|
||||
sleep 1
|
||||
(cd ..; $PERL start.pl --noclean --restart masterformat ns3)
|
||||
@ -218,7 +228,28 @@ for i in 0 1 2 3 4 5 6 7 8 9; do
|
||||
[ $lret -eq 0 ] && break;
|
||||
done
|
||||
[ $lret -eq 1 ] && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
# stomp on the file data so it hashes differently.
|
||||
# these are small and subtle changes, so that the resulting file
|
||||
# would appear to be a legitimate map file and would not trigger an
|
||||
# assertion failure if loaded into memory, but should still fail to
|
||||
# load because of a SHA1 hash mismatch.
|
||||
echo "I:checking corrupt map files fail to load (bad node header)"
|
||||
ret=0
|
||||
./named-compilezone -D -f text -F map -o map.5 example.nil baseline.txt > /dev/null
|
||||
cp map.5 badmap
|
||||
stomp badmap 2754 2 99
|
||||
./named-compilezone -D -f map -F text -o text.5 example.nil badmap > /dev/null && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo "I:checking corrupt map files fail to load (bad node data)"
|
||||
ret=0
|
||||
cp map.5 badmap
|
||||
stomp badmap 2897 5 127
|
||||
./named-compilezone -D -f map -F text -o text.5 example.nil badmap > /dev/null && ret=1
|
||||
[ $ret -eq 0 ] || echo "I:failed"
|
||||
status=`expr $status + $ret`
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <isc/lang.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/sha1.h>
|
||||
|
||||
#include <dns/types.h>
|
||||
|
||||
@ -152,7 +153,10 @@ typedef isc_result_t (*dns_rbtfindcallback_t)(dns_rbtnode_t *node,
|
||||
|
||||
typedef isc_result_t (*dns_rbtdatawriter_t)(FILE *file,
|
||||
unsigned char *data,
|
||||
isc_uint32_t version);
|
||||
isc_uint32_t version,
|
||||
isc_sha1_t *sha1);
|
||||
|
||||
typedef void (*dns_rbtdatafixer_t)(dns_rbtnode_t *rbtnode, isc_sha1_t *sha1);
|
||||
|
||||
/*****
|
||||
***** Chain Info
|
||||
@ -705,7 +709,7 @@ isc_result_t
|
||||
dns_rbt_deserialize_tree(void *base_address, off_t header_offset,
|
||||
isc_mem_t *mctx,
|
||||
void (*deleter)(void *, void *), void *deleter_arg,
|
||||
void (*data_fixer)(dns_rbtnode_t *),
|
||||
dns_rbtdatafixer_t datafixer,
|
||||
dns_rbtnode_t **originp, dns_rbt_t **rbtp);
|
||||
/*%<
|
||||
* Read a RBT structure and its data from a file.
|
||||
|
@ -2193,7 +2193,7 @@ openfile_map(dns_loadctx_t *lctx, const char *master_file) {
|
||||
*/
|
||||
static isc_result_t
|
||||
load_map(dns_loadctx_t *lctx) {
|
||||
isc_result_t result;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
dns_rdatacallbacks_t *callbacks;
|
||||
|
||||
REQUIRE(DNS_LCTX_VALID(lctx));
|
||||
@ -2205,12 +2205,12 @@ load_map(dns_loadctx_t *lctx) {
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
(*callbacks->deserialize)(callbacks->deserialize_private,
|
||||
lctx->f,
|
||||
sizeof(dns_masterrawheader_t));
|
||||
result = (*callbacks->deserialize)
|
||||
(callbacks->deserialize_private,
|
||||
lctx->f, sizeof(dns_masterrawheader_t));
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
|
168
lib/dns/rbt.c
168
lib/dns/rbt.c
@ -29,10 +29,12 @@
|
||||
#endif
|
||||
|
||||
#include <isc/file.h>
|
||||
#include <isc/hex.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/platform.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/sha1.h>
|
||||
#include <isc/socket.h>
|
||||
#include <isc/stdio.h>
|
||||
#include <isc/string.h>
|
||||
@ -117,6 +119,7 @@ struct file_header {
|
||||
unsigned int bigendian:1; /* big or little endian system */
|
||||
unsigned int rdataset_fixed:1; /* compiled with --enable-rrset-fixed */
|
||||
unsigned int nodecount; /* shadow from rbt structure */
|
||||
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
|
||||
char version2[32]; /* repeated; must match version1 */
|
||||
};
|
||||
|
||||
@ -143,17 +146,18 @@ static isc_result_t
|
||||
dns_rbt_zero_header(FILE *file);
|
||||
|
||||
static isc_result_t
|
||||
write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset);
|
||||
write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
|
||||
unsigned char *digest);
|
||||
|
||||
static isc_result_t
|
||||
serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
|
||||
uintptr_t right, uintptr_t down, uintptr_t parent,
|
||||
uintptr_t data);
|
||||
uintptr_t data, isc_sha1_t *sha1);
|
||||
|
||||
static isc_result_t
|
||||
serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
|
||||
dns_rbtdatawriter_t datawriter, isc_uint32_t serial,
|
||||
uintptr_t *where);
|
||||
uintptr_t *where, isc_sha1_t *sha1);
|
||||
/*
|
||||
* The following functions allow you to get the actual address of a pointer
|
||||
* without having to use an if statement to check to see if that address is
|
||||
@ -302,6 +306,20 @@ Name(dns_rbtnode_t *node) {
|
||||
}
|
||||
|
||||
static void printnodename(dns_rbtnode_t *node);
|
||||
|
||||
static void
|
||||
hexdump(const char *desc, unsigned char *data, size_t size) {
|
||||
char hexdump[BUFSIZ];
|
||||
isc_buffer_t b;
|
||||
isc_region_t r;
|
||||
|
||||
isc_buffer_init(&b, hexdump, sizeof(hexdump));
|
||||
r.base = data;
|
||||
r.length = size;
|
||||
isc_hex_totext(&r, 0, "", &b);
|
||||
isc_buffer_putuint8(&b, 0);
|
||||
fprintf(stderr, "%s: %s\n", desc, hexdump);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline dns_rbtnode_t *
|
||||
@ -349,7 +367,7 @@ deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp);
|
||||
|
||||
static void
|
||||
treefix(dns_rbt_t *rbt, dns_rbtnode_t *n, dns_name_t *name,
|
||||
void (*data_fixer)(dns_rbtnode_t *));
|
||||
dns_rbtdatafixer_t datafixer, isc_sha1_t *sha1);
|
||||
|
||||
static isc_result_t
|
||||
deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node);
|
||||
@ -393,7 +411,9 @@ dns_rbt_zero_header(FILE *file) {
|
||||
* here.
|
||||
*/
|
||||
static isc_result_t
|
||||
write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset) {
|
||||
write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset,
|
||||
unsigned char *digest)
|
||||
{
|
||||
file_header_t header;
|
||||
isc_result_t result;
|
||||
long location;
|
||||
@ -419,6 +439,8 @@ write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset) {
|
||||
|
||||
header.nodecount = rbt->nodecount;
|
||||
|
||||
memcpy(header.digest, digest, sizeof(header.digest));
|
||||
|
||||
location = ftell(file);
|
||||
if (location < 0)
|
||||
return (ISC_R_FAILURE);
|
||||
@ -437,13 +459,16 @@ write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset) {
|
||||
static isc_result_t
|
||||
serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
|
||||
uintptr_t right, uintptr_t down, uintptr_t parent,
|
||||
uintptr_t data)
|
||||
uintptr_t data, isc_sha1_t *sha1)
|
||||
{
|
||||
dns_rbtnode_t temp_node;
|
||||
long file_position;
|
||||
unsigned char *node_data;
|
||||
size_t datasize;
|
||||
isc_result_t result;
|
||||
#ifdef DEBUG
|
||||
dns_name_t nodename;
|
||||
#endif
|
||||
|
||||
INSIST(node != NULL);
|
||||
|
||||
@ -494,9 +519,23 @@ serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
|
||||
|
||||
CHECK(isc_stdio_write(&temp_node, 1, sizeof(dns_rbtnode_t),
|
||||
file, NULL));
|
||||
|
||||
CHECK(isc_stdio_write(node_data, 1, datasize, file, NULL));
|
||||
|
||||
#ifdef DEBUG
|
||||
dns_name_init(&nodename, NULL);
|
||||
NODENAME(node, &nodename);
|
||||
fprintf(stderr, "serialize ");
|
||||
dns_name_print(&nodename, stderr);
|
||||
fprintf(stderr, "\n");
|
||||
hexdump("node header", (unsigned char*) &temp_node,
|
||||
sizeof(dns_rbtnode_t));
|
||||
hexdump("node data", node_data, datasize);
|
||||
#endif
|
||||
|
||||
isc_sha1_update(sha1, (const isc_uint8_t *) &temp_node,
|
||||
sizeof(dns_rbtnode_t));
|
||||
isc_sha1_update(sha1, (const isc_uint8_t *) node_data, datasize);
|
||||
|
||||
cleanup:
|
||||
return (result);
|
||||
}
|
||||
@ -504,7 +543,7 @@ serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
|
||||
static isc_result_t
|
||||
serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
|
||||
dns_rbtdatawriter_t datawriter, isc_uint32_t serial,
|
||||
uintptr_t *where)
|
||||
uintptr_t *where, isc_sha1_t *sha1)
|
||||
{
|
||||
uintptr_t left = 0, right = 0, down = 0, data = 0;
|
||||
long location = 0;
|
||||
@ -517,7 +556,7 @@ serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/* Reserve space for current node */
|
||||
/* Reserve space for current node. */
|
||||
location = ftell(file);
|
||||
if (location < 0)
|
||||
return (ISC_R_FAILURE);
|
||||
@ -530,13 +569,18 @@ serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
|
||||
offset_adjust = dns_rbt_serialize_align(location + NODE_SIZE(node));
|
||||
CHECK(isc_stdio_seek(file, offset_adjust, SEEK_SET));
|
||||
|
||||
/* Serialize the rest of the tree */
|
||||
/*
|
||||
* Serialize the rest of the tree.
|
||||
*
|
||||
* WARNING: A change in the order (from left, right, down)
|
||||
* will break the way the sha1 hash is computed.
|
||||
*/
|
||||
CHECK(serialize_nodes(file, getleft(node, NULL), location,
|
||||
datawriter, serial, &left));
|
||||
datawriter, serial, &left, sha1));
|
||||
CHECK(serialize_nodes(file, getright(node, NULL), location,
|
||||
datawriter, serial, &right));
|
||||
datawriter, serial, &right, sha1));
|
||||
CHECK(serialize_nodes(file, getdown(node, NULL), location,
|
||||
datawriter, serial, &down));
|
||||
datawriter, serial, &down, sha1));
|
||||
|
||||
if (node->data != NULL) {
|
||||
long ret;
|
||||
@ -553,14 +597,15 @@ serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
|
||||
return (ISC_R_FAILURE);
|
||||
data = ret;
|
||||
|
||||
datawriter(file, node->data, serial);
|
||||
datawriter(file, node->data, serial, sha1);
|
||||
}
|
||||
|
||||
/* Seek back to reserved space */
|
||||
/* Seek back to reserved space. */
|
||||
CHECK(isc_stdio_seek(file, location, SEEK_SET));
|
||||
|
||||
/* Serialize the current node */
|
||||
CHECK(serialize_node(file, node, left, right, down, parent, data));
|
||||
/* Serialize the current node. */
|
||||
CHECK(serialize_node(file, node, left, right, down, parent, data,
|
||||
sha1));
|
||||
|
||||
/* Ensure we are always at the end of the file. */
|
||||
CHECK(isc_stdio_seek(file, 0, SEEK_END));
|
||||
@ -589,11 +634,15 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
|
||||
{
|
||||
isc_result_t result;
|
||||
long header_position, node_position, end_position;
|
||||
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
|
||||
isc_sha1_t sha1;
|
||||
|
||||
REQUIRE(file != NULL);
|
||||
|
||||
CHECK(isc_file_isplainfilefd(fileno(file)));
|
||||
|
||||
isc_sha1_init(&sha1);
|
||||
|
||||
header_position = ftell(file);
|
||||
if (header_position < 0)
|
||||
return (ISC_R_FAILURE);
|
||||
@ -606,7 +655,8 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
|
||||
if (node_position < 0)
|
||||
return (ISC_R_FAILURE);
|
||||
|
||||
CHECK(serialize_nodes(file, rbt->root, 0, datawriter, serial, NULL));
|
||||
CHECK(serialize_nodes(file, rbt->root, 0, datawriter, serial, NULL,
|
||||
&sha1));
|
||||
end_position = ftell(file);
|
||||
if (end_position < 0)
|
||||
return (ISC_R_FAILURE);
|
||||
@ -617,9 +667,14 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_sha1_final(&sha1, digest);
|
||||
#ifdef DEBUG
|
||||
hexdump("serializing digest", digest, sizeof(digest));
|
||||
#endif
|
||||
|
||||
/* Serialize header */
|
||||
CHECK(isc_stdio_seek(file, header_position, SEEK_SET));
|
||||
CHECK(write_header(file, rbt, HEADER_LENGTH));
|
||||
CHECK(write_header(file, rbt, HEADER_LENGTH, digest));
|
||||
|
||||
/* Ensure we are always at the end of the file. */
|
||||
CHECK(isc_stdio_seek(file, 0, SEEK_END));
|
||||
@ -631,11 +686,14 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
|
||||
|
||||
static void
|
||||
treefix(dns_rbt_t *rbt, dns_rbtnode_t *n, dns_name_t *name,
|
||||
void (*data_fixer)(dns_rbtnode_t *))
|
||||
dns_rbtdatafixer_t datafixer, isc_sha1_t *sha1)
|
||||
{
|
||||
isc_result_t result;
|
||||
dns_fixedname_t fixed;
|
||||
dns_name_t nodename, *fullname;
|
||||
unsigned char *node_data;
|
||||
dns_rbtnode_t header;
|
||||
size_t datasize;
|
||||
|
||||
if (n == NULL)
|
||||
return;
|
||||
@ -652,6 +710,9 @@ treefix(dns_rbt_t *rbt, dns_rbtnode_t *n, dns_name_t *name,
|
||||
/* XXX: we need to catch errors better than this */
|
||||
}
|
||||
|
||||
/* memorize header contents prior to fixup */
|
||||
memcpy(&header, n, sizeof(header));
|
||||
|
||||
INSIST(!n->parent_is_relative || n->parent != NULL);
|
||||
INSIST(!n->right_is_relative || n->right != NULL);
|
||||
INSIST(!n->left_is_relative || n->left != NULL);
|
||||
@ -675,15 +736,32 @@ treefix(dns_rbt_t *rbt, dns_rbtnode_t *n, dns_name_t *name,
|
||||
|
||||
hash_node(rbt, n, fullname);
|
||||
|
||||
if (data_fixer != NULL && n->data != NULL)
|
||||
data_fixer(n);
|
||||
|
||||
if (n->right != NULL)
|
||||
treefix(rbt, n->right, name, data_fixer);
|
||||
/* a change in the order (from left, right, down) will break hashing*/
|
||||
if (n->left != NULL)
|
||||
treefix(rbt, n->left, name, data_fixer);
|
||||
treefix(rbt, n->left, name, datafixer, sha1);
|
||||
if (n->right != NULL)
|
||||
treefix(rbt, n->right, name, datafixer, sha1);
|
||||
if (n->down != NULL)
|
||||
treefix(rbt, n->down, fullname, data_fixer);
|
||||
treefix(rbt, n->down, fullname, datafixer, sha1);
|
||||
|
||||
if (datafixer != NULL && n->data != NULL)
|
||||
datafixer(n, sha1);
|
||||
|
||||
node_data = (unsigned char *) n + sizeof(dns_rbtnode_t);
|
||||
datasize = NODE_SIZE(n) - sizeof(dns_rbtnode_t);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "deserialize ");
|
||||
dns_name_print(&nodename, stderr);
|
||||
fprintf(stderr, "\n");
|
||||
hexdump("node header", (unsigned char *) &header,
|
||||
sizeof(dns_rbtnode_t));
|
||||
hexdump("node data", node_data, datasize);
|
||||
#endif
|
||||
isc_sha1_update(sha1, (const isc_uint8_t *) &header,
|
||||
sizeof(dns_rbtnode_t));
|
||||
isc_sha1_update(sha1, (const isc_uint8_t *) node_data,
|
||||
datasize);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
@ -691,14 +769,18 @@ dns_rbt_deserialize_tree(void *base_address, off_t header_offset,
|
||||
isc_mem_t *mctx,
|
||||
void (*deleter)(void *, void *),
|
||||
void *deleter_arg,
|
||||
void (*data_fixer)(dns_rbtnode_t *),
|
||||
dns_rbtdatafixer_t datafixer,
|
||||
dns_rbtnode_t **originp, dns_rbt_t **rbtp)
|
||||
{
|
||||
isc_result_t result;
|
||||
file_header_t *header;
|
||||
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
|
||||
isc_sha1_t sha1;
|
||||
|
||||
REQUIRE(originp == NULL || *originp == NULL);
|
||||
|
||||
isc_sha1_init(&sha1);
|
||||
|
||||
result = dns_rbt_create(mctx, deleter, deleter_arg, rbtp);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
@ -729,7 +811,15 @@ dns_rbt_deserialize_tree(void *base_address, off_t header_offset,
|
||||
(*rbtp)->root = (dns_rbtnode_t *)((char *)base_address +
|
||||
header_offset + header->first_node_offset);
|
||||
(*rbtp)->nodecount = header->nodecount;
|
||||
treefix(*rbtp, (*rbtp)->root, dns_rootname, data_fixer);
|
||||
treefix(*rbtp, (*rbtp)->root, dns_rootname, datafixer, &sha1);
|
||||
|
||||
isc_sha1_final(&sha1, digest);
|
||||
#ifdef DEBUG
|
||||
hexdump("deserializing digest", digest, sizeof(digest));
|
||||
#endif
|
||||
|
||||
if (memcmp(header->digest, digest, sizeof(digest)) != 0)
|
||||
return (ISC_R_INVALIDFILE);
|
||||
|
||||
if (originp != NULL)
|
||||
*originp = (*rbtp)->root;
|
||||
@ -749,7 +839,6 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
|
||||
#endif
|
||||
dns_rbt_t *rbt;
|
||||
|
||||
|
||||
REQUIRE(mctx != NULL);
|
||||
REQUIRE(rbtp != NULL && *rbtp == NULL);
|
||||
REQUIRE(deleter == NULL ? deleter_arg == NULL : 1);
|
||||
@ -820,13 +909,17 @@ dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
|
||||
|
||||
unsigned int
|
||||
dns_rbt_nodecount(dns_rbt_t *rbt) {
|
||||
|
||||
REQUIRE(VALID_RBT(rbt));
|
||||
|
||||
return (rbt->nodecount);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
dns_rbt_hashsize(dns_rbt_t *rbt) {
|
||||
|
||||
REQUIRE(VALID_RBT(rbt));
|
||||
|
||||
return (rbt->hashsize);
|
||||
}
|
||||
|
||||
@ -2552,6 +2645,7 @@ deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) {
|
||||
static isc_result_t
|
||||
deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
REQUIRE(VALID_RBT(rbt));
|
||||
|
||||
if (node == NULL)
|
||||
@ -2607,6 +2701,7 @@ static void
|
||||
deletetreeflat(dns_rbt_t *rbt, unsigned int quantum, dns_rbtnode_t **nodep) {
|
||||
dns_rbtnode_t *parent;
|
||||
dns_rbtnode_t *node = *nodep;
|
||||
|
||||
REQUIRE(VALID_RBT(rbt));
|
||||
|
||||
again:
|
||||
@ -2760,6 +2855,7 @@ dns_rbt_printtree(dns_rbtnode_t *root, dns_rbtnode_t *parent,
|
||||
|
||||
void
|
||||
dns_rbt_printall(dns_rbt_t *rbt, void (*data_printer)(FILE *, void *)) {
|
||||
|
||||
REQUIRE(VALID_RBT(rbt));
|
||||
|
||||
dns_rbt_printtree(rbt->root, NULL, 0, "root", data_printer);
|
||||
@ -2771,12 +2867,12 @@ dns_rbt_printall(dns_rbt_t *rbt, void (*data_printer)(FILE *, void *)) {
|
||||
|
||||
void
|
||||
dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
|
||||
/*
|
||||
* Initialize 'chain'.
|
||||
*/
|
||||
|
||||
REQUIRE(chain != NULL);
|
||||
|
||||
/*
|
||||
* Initialize 'chain'.
|
||||
*/
|
||||
chain->mctx = mctx;
|
||||
chain->end = NULL;
|
||||
chain->level_count = 0;
|
||||
@ -3217,13 +3313,13 @@ dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
|
||||
|
||||
void
|
||||
dns_rbtnodechain_reset(dns_rbtnodechain_t *chain) {
|
||||
|
||||
REQUIRE(VALID_CHAIN(chain));
|
||||
|
||||
/*
|
||||
* Free any dynamic storage associated with 'chain', and then
|
||||
* reinitialize 'chain'.
|
||||
*/
|
||||
|
||||
REQUIRE(VALID_CHAIN(chain));
|
||||
|
||||
chain->end = NULL;
|
||||
chain->level_count = 0;
|
||||
chain->level_matches = 0;
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <isc/event.h>
|
||||
#include <isc/heap.h>
|
||||
#include <isc/file.h>
|
||||
#include <isc/hex.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/mutex.h>
|
||||
#include <isc/platform.h>
|
||||
@ -728,6 +729,25 @@ static unsigned int init_count;
|
||||
* For zone databases the node for the origin of the zone MUST NOT be deleted.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Debugging routines
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
hexdump(const char *desc, unsigned char *data, size_t size) {
|
||||
char hexdump[BUFSIZ];
|
||||
isc_buffer_t b;
|
||||
isc_region_t r;
|
||||
|
||||
isc_buffer_init(&b, hexdump, sizeof(hexdump));
|
||||
r.base = data;
|
||||
r.length = size;
|
||||
isc_hex_totext(&r, 0, "", &b);
|
||||
isc_buffer_putuint8(&b, 0);
|
||||
fprintf(stderr, "%s: %s\n", desc, hexdump);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* DB Routines
|
||||
@ -6976,7 +6996,7 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
|
||||
}
|
||||
|
||||
static void
|
||||
fix_data(dns_rbtnode_t *rbtnode) {
|
||||
rbt_datafixer(dns_rbtnode_t *rbtnode, isc_sha1_t *sha1) {
|
||||
rdatasetheader_t *header;
|
||||
unsigned char *p;
|
||||
size_t size;
|
||||
@ -6984,12 +7004,18 @@ fix_data(dns_rbtnode_t *rbtnode) {
|
||||
REQUIRE(rbtnode != NULL);
|
||||
|
||||
for (header = rbtnode->data; header != NULL; header = header->next) {
|
||||
p = (unsigned char *) header;
|
||||
size = dns_rdataslab_size(p, sizeof(*header));
|
||||
isc_sha1_update(sha1, p, size);
|
||||
#ifdef DEBUG
|
||||
hexdump("hashing header", p, sizeof(rdatasetheader_t));
|
||||
hexdump("hashing slab", p + sizeof(rdatasetheader_t),
|
||||
size - sizeof(rdatasetheader_t));
|
||||
#endif
|
||||
header->serial = 1;
|
||||
header->is_mmapped = 1;
|
||||
header->node = rbtnode;
|
||||
header->node_is_relative = 0;
|
||||
p = (unsigned char *) header;
|
||||
size = dns_rdataslab_size(p, sizeof(*header));
|
||||
if (header->next != NULL) {
|
||||
header->next = (rdatasetheader_t *)(p + size);
|
||||
header->next_is_relative = 0;
|
||||
@ -7002,6 +7028,7 @@ fix_data(dns_rbtnode_t *rbtnode) {
|
||||
*/
|
||||
static isc_result_t
|
||||
deserialize(void *arg, FILE *f, off_t offset) {
|
||||
isc_result_t result;
|
||||
rbtdb_load_t *loadctx = arg;
|
||||
dns_rbtdb_t *rbtdb = loadctx->rbtdb;
|
||||
rbtdb_file_header_t *header;
|
||||
@ -7039,11 +7066,12 @@ deserialize(void *arg, FILE *f, off_t offset) {
|
||||
rbtdb->origin_node = NULL;
|
||||
|
||||
if (header->tree != 0) {
|
||||
dns_rbt_deserialize_tree(base, header->tree,
|
||||
rbtdb->common.mctx, delete_callback,
|
||||
rbtdb, fix_data,
|
||||
&rbtdb->origin_node,
|
||||
&temporary_rbt);
|
||||
result = dns_rbt_deserialize_tree(base, header->tree,
|
||||
rbtdb->common.mctx,
|
||||
delete_callback,
|
||||
rbtdb, rbt_datafixer,
|
||||
&rbtdb->origin_node,
|
||||
&temporary_rbt);
|
||||
if (temporary_rbt != NULL) {
|
||||
dns_rbt_destroy(&rbtdb->tree);
|
||||
rbtdb->tree = temporary_rbt;
|
||||
@ -7052,28 +7080,38 @@ deserialize(void *arg, FILE *f, off_t offset) {
|
||||
rbtdb->origin_node =
|
||||
(dns_rbtnode_t *)(header->tree + base + 1024);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
|
||||
if (header->nsec != 0) {
|
||||
dns_rbt_deserialize_tree(base, header->nsec,
|
||||
rbtdb->common.mctx, delete_callback,
|
||||
rbtdb, fix_data, NULL, &temporary_rbt);
|
||||
result = dns_rbt_deserialize_tree(base, header->nsec,
|
||||
rbtdb->common.mctx,
|
||||
delete_callback,
|
||||
rbtdb, rbt_datafixer,
|
||||
NULL, &temporary_rbt);
|
||||
if (temporary_rbt != NULL) {
|
||||
dns_rbt_destroy(&rbtdb->nsec);
|
||||
rbtdb->nsec = temporary_rbt;
|
||||
temporary_rbt = NULL;
|
||||
}
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
|
||||
if (header->nsec3 != 0) {
|
||||
dns_rbt_deserialize_tree(base, header->nsec3,
|
||||
rbtdb->common.mctx, delete_callback,
|
||||
rbtdb, fix_data, NULL, &temporary_rbt);
|
||||
result = dns_rbt_deserialize_tree(base, header->nsec3,
|
||||
rbtdb->common.mctx,
|
||||
delete_callback,
|
||||
rbtdb, rbt_datafixer,
|
||||
NULL, &temporary_rbt);
|
||||
if (temporary_rbt != NULL) {
|
||||
dns_rbt_destroy(&rbtdb->nsec3);
|
||||
rbtdb->nsec3 = temporary_rbt;
|
||||
temporary_rbt = NULL;
|
||||
}
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
@ -7151,7 +7189,7 @@ endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
|
||||
* If there's a KEY rdataset at the zone origin containing a
|
||||
* zone key, we consider the zone secure.
|
||||
*/
|
||||
if (! IS_CACHE(rbtdb))
|
||||
if (! IS_CACHE(rbtdb) && rbtdb->origin_node != NULL)
|
||||
iszonesecure(db, rbtdb->current_version, rbtdb->origin_node);
|
||||
|
||||
callbacks->add = NULL;
|
||||
@ -7169,7 +7207,8 @@ endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
|
||||
* by the void *data pointer in the dns_rbtnode
|
||||
*/
|
||||
static isc_result_t
|
||||
rbt_datawriter(FILE *rbtfile, unsigned char *data, isc_uint32_t serial) {
|
||||
rbt_datawriter(FILE *rbtfile, unsigned char *data, isc_uint32_t serial,
|
||||
isc_sha1_t *sha1) {
|
||||
rdatasetheader_t newheader;
|
||||
rdatasetheader_t *header = (rdatasetheader_t *) data, *next;
|
||||
size_t where, size;
|
||||
@ -7210,12 +7249,22 @@ rbt_datawriter(FILE *rbtfile, unsigned char *data, isc_uint32_t serial) {
|
||||
newheader.next_is_relative = 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
hexdump("writing header", (unsigned char *) &newheader,
|
||||
sizeof(rdatasetheader_t));
|
||||
hexdump("writing slab", p + sizeof(rdatasetheader_t),
|
||||
size - sizeof(rdatasetheader_t));
|
||||
#endif
|
||||
isc_sha1_update(sha1, (unsigned char *) &newheader,
|
||||
sizeof(rdatasetheader_t));
|
||||
result = isc_stdio_write(&newheader,
|
||||
sizeof(rdatasetheader_t), 1,
|
||||
rbtfile, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
isc_sha1_update(sha1, p + sizeof(rdatasetheader_t),
|
||||
size - sizeof(rdatasetheader_t));
|
||||
result = isc_stdio_write(p + sizeof(rdatasetheader_t),
|
||||
size - sizeof(rdatasetheader_t), 1, rbtfile, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
|
Loading…
x
Reference in New Issue
Block a user