2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 14:07:59 +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 3561. [bug] dig: issue a warning if an EDNS query returns FORMERR
or NOTIMP. Adjust usage message. [RT #33363] 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/db-*
rm -f ns2/large.bk rm -f ns2/large.bk
rm -f ns3/example.db.map ns3/dynamic.db.map 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 }' < $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 () { restart () {
sleep 1 sleep 1
(cd ..; $PERL start.pl --noclean --restart masterformat ns3) (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; [ $lret -eq 0 ] && break;
done done
[ $lret -eq 1 ] && ret=1 [ $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" [ $ret -eq 0 ] || echo "I:failed"
status=`expr $status + $ret` status=`expr $status + $ret`

View File

@@ -25,6 +25,7 @@
#include <isc/lang.h> #include <isc/lang.h>
#include <isc/magic.h> #include <isc/magic.h>
#include <isc/refcount.h> #include <isc/refcount.h>
#include <isc/sha1.h>
#include <dns/types.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, typedef isc_result_t (*dns_rbtdatawriter_t)(FILE *file,
unsigned char *data, 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 ***** Chain Info
@@ -705,7 +709,7 @@ isc_result_t
dns_rbt_deserialize_tree(void *base_address, off_t header_offset, dns_rbt_deserialize_tree(void *base_address, off_t header_offset,
isc_mem_t *mctx, isc_mem_t *mctx,
void (*deleter)(void *, void *), void *deleter_arg, 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); dns_rbtnode_t **originp, dns_rbt_t **rbtp);
/*%< /*%<
* Read a RBT structure and its data from a file. * 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 static isc_result_t
load_map(dns_loadctx_t *lctx) { load_map(dns_loadctx_t *lctx) {
isc_result_t result; isc_result_t result = ISC_R_SUCCESS;
dns_rdatacallbacks_t *callbacks; dns_rdatacallbacks_t *callbacks;
REQUIRE(DNS_LCTX_VALID(lctx)); REQUIRE(DNS_LCTX_VALID(lctx));
@@ -2205,12 +2205,12 @@ load_map(dns_loadctx_t *lctx) {
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
(*callbacks->deserialize)(callbacks->deserialize_private, result = (*callbacks->deserialize)
lctx->f, (callbacks->deserialize_private,
sizeof(dns_masterrawheader_t)); lctx->f, sizeof(dns_masterrawheader_t));
} }
return (ISC_R_SUCCESS); return (result);
} }
static isc_result_t static isc_result_t

View File

@@ -29,10 +29,12 @@
#endif #endif
#include <isc/file.h> #include <isc/file.h>
#include <isc/hex.h>
#include <isc/mem.h> #include <isc/mem.h>
#include <isc/platform.h> #include <isc/platform.h>
#include <isc/print.h> #include <isc/print.h>
#include <isc/refcount.h> #include <isc/refcount.h>
#include <isc/sha1.h>
#include <isc/socket.h> #include <isc/socket.h>
#include <isc/stdio.h> #include <isc/stdio.h>
#include <isc/string.h> #include <isc/string.h>
@@ -117,6 +119,7 @@ struct file_header {
unsigned int bigendian:1; /* big or little endian system */ unsigned int bigendian:1; /* big or little endian system */
unsigned int rdataset_fixed:1; /* compiled with --enable-rrset-fixed */ unsigned int rdataset_fixed:1; /* compiled with --enable-rrset-fixed */
unsigned int nodecount; /* shadow from rbt structure */ unsigned int nodecount; /* shadow from rbt structure */
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
char version2[32]; /* repeated; must match version1 */ char version2[32]; /* repeated; must match version1 */
}; };
@@ -143,17 +146,18 @@ static isc_result_t
dns_rbt_zero_header(FILE *file); dns_rbt_zero_header(FILE *file);
static isc_result_t 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 static isc_result_t
serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left, serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
uintptr_t right, uintptr_t down, uintptr_t parent, uintptr_t right, uintptr_t down, uintptr_t parent,
uintptr_t data); uintptr_t data, isc_sha1_t *sha1);
static isc_result_t static isc_result_t
serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
dns_rbtdatawriter_t datawriter, isc_uint32_t serial, 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 * 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 * 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 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 #endif
static inline dns_rbtnode_t * static inline dns_rbtnode_t *
@@ -349,7 +367,7 @@ deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp);
static void static void
treefix(dns_rbt_t *rbt, dns_rbtnode_t *n, dns_name_t *name, 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 static isc_result_t
deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node); deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node);
@@ -393,7 +411,9 @@ dns_rbt_zero_header(FILE *file) {
* here. * here.
*/ */
static isc_result_t 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; file_header_t header;
isc_result_t result; isc_result_t result;
long location; long location;
@@ -419,6 +439,8 @@ write_header(FILE *file, dns_rbt_t *rbt, isc_uint64_t first_node_offset) {
header.nodecount = rbt->nodecount; header.nodecount = rbt->nodecount;
memcpy(header.digest, digest, sizeof(header.digest));
location = ftell(file); location = ftell(file);
if (location < 0) if (location < 0)
return (ISC_R_FAILURE); 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 static isc_result_t
serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left, serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
uintptr_t right, uintptr_t down, uintptr_t parent, uintptr_t right, uintptr_t down, uintptr_t parent,
uintptr_t data) uintptr_t data, isc_sha1_t *sha1)
{ {
dns_rbtnode_t temp_node; dns_rbtnode_t temp_node;
long file_position; long file_position;
unsigned char *node_data; unsigned char *node_data;
size_t datasize; size_t datasize;
isc_result_t result; isc_result_t result;
#ifdef DEBUG
dns_name_t nodename;
#endif
INSIST(node != NULL); 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), CHECK(isc_stdio_write(&temp_node, 1, sizeof(dns_rbtnode_t),
file, NULL)); file, NULL));
CHECK(isc_stdio_write(node_data, 1, datasize, 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: cleanup:
return (result); return (result);
} }
@@ -504,7 +543,7 @@ serialize_node(FILE *file, dns_rbtnode_t *node, uintptr_t left,
static isc_result_t static isc_result_t
serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent, serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
dns_rbtdatawriter_t datawriter, isc_uint32_t serial, 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; uintptr_t left = 0, right = 0, down = 0, data = 0;
long location = 0; long location = 0;
@@ -517,7 +556,7 @@ serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
/* Reserve space for current node */ /* Reserve space for current node. */
location = ftell(file); location = ftell(file);
if (location < 0) if (location < 0)
return (ISC_R_FAILURE); 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)); offset_adjust = dns_rbt_serialize_align(location + NODE_SIZE(node));
CHECK(isc_stdio_seek(file, offset_adjust, SEEK_SET)); 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, CHECK(serialize_nodes(file, getleft(node, NULL), location,
datawriter, serial, &left)); datawriter, serial, &left, sha1));
CHECK(serialize_nodes(file, getright(node, NULL), location, CHECK(serialize_nodes(file, getright(node, NULL), location,
datawriter, serial, &right)); datawriter, serial, &right, sha1));
CHECK(serialize_nodes(file, getdown(node, NULL), location, CHECK(serialize_nodes(file, getdown(node, NULL), location,
datawriter, serial, &down)); datawriter, serial, &down, sha1));
if (node->data != NULL) { if (node->data != NULL) {
long ret; long ret;
@@ -553,14 +597,15 @@ serialize_nodes(FILE *file, dns_rbtnode_t *node, uintptr_t parent,
return (ISC_R_FAILURE); return (ISC_R_FAILURE);
data = ret; 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)); CHECK(isc_stdio_seek(file, location, SEEK_SET));
/* Serialize the current node */ /* Serialize the current node. */
CHECK(serialize_node(file, node, left, right, down, parent, data)); CHECK(serialize_node(file, node, left, right, down, parent, data,
sha1));
/* Ensure we are always at the end of the file. */ /* Ensure we are always at the end of the file. */
CHECK(isc_stdio_seek(file, 0, SEEK_END)); 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; isc_result_t result;
long header_position, node_position, end_position; long header_position, node_position, end_position;
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
isc_sha1_t sha1;
REQUIRE(file != NULL); REQUIRE(file != NULL);
CHECK(isc_file_isplainfilefd(fileno(file))); CHECK(isc_file_isplainfilefd(fileno(file)));
isc_sha1_init(&sha1);
header_position = ftell(file); header_position = ftell(file);
if (header_position < 0) if (header_position < 0)
return (ISC_R_FAILURE); return (ISC_R_FAILURE);
@@ -606,7 +655,8 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
if (node_position < 0) if (node_position < 0)
return (ISC_R_FAILURE); 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); end_position = ftell(file);
if (end_position < 0) if (end_position < 0)
return (ISC_R_FAILURE); return (ISC_R_FAILURE);
@@ -617,9 +667,14 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
isc_sha1_final(&sha1, digest);
#ifdef DEBUG
hexdump("serializing digest", digest, sizeof(digest));
#endif
/* Serialize header */ /* Serialize header */
CHECK(isc_stdio_seek(file, header_position, SEEK_SET)); 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. */ /* Ensure we are always at the end of the file. */
CHECK(isc_stdio_seek(file, 0, SEEK_END)); CHECK(isc_stdio_seek(file, 0, SEEK_END));
@@ -631,11 +686,14 @@ dns_rbt_serialize_tree(FILE *file, dns_rbt_t *rbt,
static void static void
treefix(dns_rbt_t *rbt, dns_rbtnode_t *n, dns_name_t *name, 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; isc_result_t result;
dns_fixedname_t fixed; dns_fixedname_t fixed;
dns_name_t nodename, *fullname; dns_name_t nodename, *fullname;
unsigned char *node_data;
dns_rbtnode_t header;
size_t datasize;
if (n == NULL) if (n == NULL)
return; 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 */ /* 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->parent_is_relative || n->parent != NULL);
INSIST(!n->right_is_relative || n->right != NULL); INSIST(!n->right_is_relative || n->right != NULL);
INSIST(!n->left_is_relative || n->left != 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); hash_node(rbt, n, fullname);
if (data_fixer != NULL && n->data != NULL) /* a change in the order (from left, right, down) will break hashing*/
data_fixer(n);
if (n->right != NULL)
treefix(rbt, n->right, name, data_fixer);
if (n->left != NULL) 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) 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 isc_result_t
@@ -691,14 +769,18 @@ dns_rbt_deserialize_tree(void *base_address, off_t header_offset,
isc_mem_t *mctx, isc_mem_t *mctx,
void (*deleter)(void *, void *), void (*deleter)(void *, void *),
void *deleter_arg, void *deleter_arg,
void (*data_fixer)(dns_rbtnode_t *), dns_rbtdatafixer_t datafixer,
dns_rbtnode_t **originp, dns_rbt_t **rbtp) dns_rbtnode_t **originp, dns_rbt_t **rbtp)
{ {
isc_result_t result; isc_result_t result;
file_header_t *header; file_header_t *header;
unsigned char digest[ISC_SHA1_DIGESTLENGTH];
isc_sha1_t sha1;
REQUIRE(originp == NULL || *originp == NULL); REQUIRE(originp == NULL || *originp == NULL);
isc_sha1_init(&sha1);
result = dns_rbt_create(mctx, deleter, deleter_arg, rbtp); result = dns_rbt_create(mctx, deleter, deleter_arg, rbtp);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); 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 + (*rbtp)->root = (dns_rbtnode_t *)((char *)base_address +
header_offset + header->first_node_offset); header_offset + header->first_node_offset);
(*rbtp)->nodecount = header->nodecount; (*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) if (originp != NULL)
*originp = (*rbtp)->root; *originp = (*rbtp)->root;
@@ -749,7 +839,6 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
#endif #endif
dns_rbt_t *rbt; dns_rbt_t *rbt;
REQUIRE(mctx != NULL); REQUIRE(mctx != NULL);
REQUIRE(rbtp != NULL && *rbtp == NULL); REQUIRE(rbtp != NULL && *rbtp == NULL);
REQUIRE(deleter == NULL ? deleter_arg == NULL : 1); REQUIRE(deleter == NULL ? deleter_arg == NULL : 1);
@@ -820,13 +909,17 @@ dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
unsigned int unsigned int
dns_rbt_nodecount(dns_rbt_t *rbt) { dns_rbt_nodecount(dns_rbt_t *rbt) {
REQUIRE(VALID_RBT(rbt)); REQUIRE(VALID_RBT(rbt));
return (rbt->nodecount); return (rbt->nodecount);
} }
unsigned int unsigned int
dns_rbt_hashsize(dns_rbt_t *rbt) { dns_rbt_hashsize(dns_rbt_t *rbt) {
REQUIRE(VALID_RBT(rbt)); REQUIRE(VALID_RBT(rbt));
return (rbt->hashsize); return (rbt->hashsize);
} }
@@ -2552,6 +2645,7 @@ deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) {
static isc_result_t static isc_result_t
deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) { deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {
isc_result_t result = ISC_R_SUCCESS; isc_result_t result = ISC_R_SUCCESS;
REQUIRE(VALID_RBT(rbt)); REQUIRE(VALID_RBT(rbt));
if (node == NULL) if (node == NULL)
@@ -2607,6 +2701,7 @@ static void
deletetreeflat(dns_rbt_t *rbt, unsigned int quantum, dns_rbtnode_t **nodep) { deletetreeflat(dns_rbt_t *rbt, unsigned int quantum, dns_rbtnode_t **nodep) {
dns_rbtnode_t *parent; dns_rbtnode_t *parent;
dns_rbtnode_t *node = *nodep; dns_rbtnode_t *node = *nodep;
REQUIRE(VALID_RBT(rbt)); REQUIRE(VALID_RBT(rbt));
again: again:
@@ -2760,6 +2855,7 @@ dns_rbt_printtree(dns_rbtnode_t *root, dns_rbtnode_t *parent,
void void
dns_rbt_printall(dns_rbt_t *rbt, void (*data_printer)(FILE *, void *)) { dns_rbt_printall(dns_rbt_t *rbt, void (*data_printer)(FILE *, void *)) {
REQUIRE(VALID_RBT(rbt)); REQUIRE(VALID_RBT(rbt));
dns_rbt_printtree(rbt->root, NULL, 0, "root", data_printer); 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 void
dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) { dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
/*
* Initialize 'chain'.
*/
REQUIRE(chain != NULL); REQUIRE(chain != NULL);
/*
* Initialize 'chain'.
*/
chain->mctx = mctx; chain->mctx = mctx;
chain->end = NULL; chain->end = NULL;
chain->level_count = 0; chain->level_count = 0;
@@ -3217,13 +3313,13 @@ dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
void void
dns_rbtnodechain_reset(dns_rbtnodechain_t *chain) { dns_rbtnodechain_reset(dns_rbtnodechain_t *chain) {
REQUIRE(VALID_CHAIN(chain));
/* /*
* Free any dynamic storage associated with 'chain', and then * Free any dynamic storage associated with 'chain', and then
* reinitialize 'chain'. * reinitialize 'chain'.
*/ */
REQUIRE(VALID_CHAIN(chain));
chain->end = NULL; chain->end = NULL;
chain->level_count = 0; chain->level_count = 0;
chain->level_matches = 0; chain->level_matches = 0;

View File

@@ -30,6 +30,7 @@
#include <isc/event.h> #include <isc/event.h>
#include <isc/heap.h> #include <isc/heap.h>
#include <isc/file.h> #include <isc/file.h>
#include <isc/hex.h>
#include <isc/mem.h> #include <isc/mem.h>
#include <isc/mutex.h> #include <isc/mutex.h>
#include <isc/platform.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. * 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 * DB Routines
@@ -6976,7 +6996,7 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
} }
static void static void
fix_data(dns_rbtnode_t *rbtnode) { rbt_datafixer(dns_rbtnode_t *rbtnode, isc_sha1_t *sha1) {
rdatasetheader_t *header; rdatasetheader_t *header;
unsigned char *p; unsigned char *p;
size_t size; size_t size;
@@ -6984,12 +7004,18 @@ fix_data(dns_rbtnode_t *rbtnode) {
REQUIRE(rbtnode != NULL); REQUIRE(rbtnode != NULL);
for (header = rbtnode->data; header != NULL; header = header->next) { 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->serial = 1;
header->is_mmapped = 1; header->is_mmapped = 1;
header->node = rbtnode; header->node = rbtnode;
header->node_is_relative = 0; header->node_is_relative = 0;
p = (unsigned char *) header;
size = dns_rdataslab_size(p, sizeof(*header));
if (header->next != NULL) { if (header->next != NULL) {
header->next = (rdatasetheader_t *)(p + size); header->next = (rdatasetheader_t *)(p + size);
header->next_is_relative = 0; header->next_is_relative = 0;
@@ -7002,6 +7028,7 @@ fix_data(dns_rbtnode_t *rbtnode) {
*/ */
static isc_result_t static isc_result_t
deserialize(void *arg, FILE *f, off_t offset) { deserialize(void *arg, FILE *f, off_t offset) {
isc_result_t result;
rbtdb_load_t *loadctx = arg; rbtdb_load_t *loadctx = arg;
dns_rbtdb_t *rbtdb = loadctx->rbtdb; dns_rbtdb_t *rbtdb = loadctx->rbtdb;
rbtdb_file_header_t *header; rbtdb_file_header_t *header;
@@ -7039,11 +7066,12 @@ deserialize(void *arg, FILE *f, off_t offset) {
rbtdb->origin_node = NULL; rbtdb->origin_node = NULL;
if (header->tree != 0) { if (header->tree != 0) {
dns_rbt_deserialize_tree(base, header->tree, result = dns_rbt_deserialize_tree(base, header->tree,
rbtdb->common.mctx, delete_callback, rbtdb->common.mctx,
rbtdb, fix_data, delete_callback,
&rbtdb->origin_node, rbtdb, rbt_datafixer,
&temporary_rbt); &rbtdb->origin_node,
&temporary_rbt);
if (temporary_rbt != NULL) { if (temporary_rbt != NULL) {
dns_rbt_destroy(&rbtdb->tree); dns_rbt_destroy(&rbtdb->tree);
rbtdb->tree = temporary_rbt; rbtdb->tree = temporary_rbt;
@@ -7052,28 +7080,38 @@ deserialize(void *arg, FILE *f, off_t offset) {
rbtdb->origin_node = rbtdb->origin_node =
(dns_rbtnode_t *)(header->tree + base + 1024); (dns_rbtnode_t *)(header->tree + base + 1024);
} }
if (result != ISC_R_SUCCESS)
return (result);
} }
if (header->nsec != 0) { if (header->nsec != 0) {
dns_rbt_deserialize_tree(base, header->nsec, result = dns_rbt_deserialize_tree(base, header->nsec,
rbtdb->common.mctx, delete_callback, rbtdb->common.mctx,
rbtdb, fix_data, NULL, &temporary_rbt); delete_callback,
rbtdb, rbt_datafixer,
NULL, &temporary_rbt);
if (temporary_rbt != NULL) { if (temporary_rbt != NULL) {
dns_rbt_destroy(&rbtdb->nsec); dns_rbt_destroy(&rbtdb->nsec);
rbtdb->nsec = temporary_rbt; rbtdb->nsec = temporary_rbt;
temporary_rbt = NULL; temporary_rbt = NULL;
} }
if (result != ISC_R_SUCCESS)
return (result);
} }
if (header->nsec3 != 0) { if (header->nsec3 != 0) {
dns_rbt_deserialize_tree(base, header->nsec3, result = dns_rbt_deserialize_tree(base, header->nsec3,
rbtdb->common.mctx, delete_callback, rbtdb->common.mctx,
rbtdb, fix_data, NULL, &temporary_rbt); delete_callback,
rbtdb, rbt_datafixer,
NULL, &temporary_rbt);
if (temporary_rbt != NULL) { if (temporary_rbt != NULL) {
dns_rbt_destroy(&rbtdb->nsec3); dns_rbt_destroy(&rbtdb->nsec3);
rbtdb->nsec3 = temporary_rbt; rbtdb->nsec3 = temporary_rbt;
temporary_rbt = NULL; temporary_rbt = NULL;
} }
if (result != ISC_R_SUCCESS)
return (result);
} }
return (ISC_R_SUCCESS); 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 * If there's a KEY rdataset at the zone origin containing a
* zone key, we consider the zone secure. * 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); iszonesecure(db, rbtdb->current_version, rbtdb->origin_node);
callbacks->add = NULL; 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 * by the void *data pointer in the dns_rbtnode
*/ */
static isc_result_t 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 newheader;
rdatasetheader_t *header = (rdatasetheader_t *) data, *next; rdatasetheader_t *header = (rdatasetheader_t *) data, *next;
size_t where, size; size_t where, size;
@@ -7210,12 +7249,22 @@ rbt_datawriter(FILE *rbtfile, unsigned char *data, isc_uint32_t serial) {
newheader.next_is_relative = 1; 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, result = isc_stdio_write(&newheader,
sizeof(rdatasetheader_t), 1, sizeof(rdatasetheader_t), 1,
rbtfile, NULL); rbtfile, NULL);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
isc_sha1_update(sha1, p + sizeof(rdatasetheader_t),
size - sizeof(rdatasetheader_t));
result = isc_stdio_write(p + sizeof(rdatasetheader_t), result = isc_stdio_write(p + sizeof(rdatasetheader_t),
size - sizeof(rdatasetheader_t), 1, rbtfile, NULL); size - sizeof(rdatasetheader_t), 1, rbtfile, NULL);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)