2
0
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:
Evan Hunt 2013-05-01 22:20:02 -07:00
parent a4fe161bd3
commit 03b5d2689d
7 changed files with 244 additions and 61 deletions

View File

@ -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]

View File

@ -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

View File

@ -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`

View File

@ -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.

View 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

View File

@ -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;

View File

@ -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)