From: Stefan Metzmacher Date: Thu, 9 Sep 2010 13:45:51 +0000 (+0200) Subject: lib/tdb: maintain reference hashes with the hash function that's used at create time X-Git-Url: http://git.samba.org/?a=commitdiff_plain;ds=sidebyside;h=b2b69f1281c36c2fa67407856e443260b7868f4e;p=metze%2Fsamba%2Fwip.git lib/tdb: maintain reference hashes with the hash function that's used at create time If the hashes are available and the current hash function can't verify them, we reject the open. metze --- diff --git a/lib/tdb/common/open.c b/lib/tdb/common/open.c index 49b8e85f1264..ff0fd376017b 100644 --- a/lib/tdb/common/open.c +++ b/lib/tdb/common/open.c @@ -52,6 +52,7 @@ static int tdb_new_database(struct tdb_context *tdb, int hash_size) size_t size; int ret = -1; ssize_t written; + TDB_DATA hash_key; /* We make it up in memory, then write it out if not internal */ size = sizeof(struct tdb_header) + (hash_size+1)*sizeof(tdb_off_t); @@ -61,6 +62,15 @@ static int tdb_new_database(struct tdb_context *tdb, int hash_size) /* Fill in the header */ newdb->version = TDB_VERSION; newdb->hash_size = hash_size; + + hash_key.dptr = discard_const_p(uint8_t, TDB_MAGIC_FOOD); + hash_key.dsize = sizeof(TDB_MAGIC_FOOD); + newdb->magic_food_hash = tdb->hash_fn(&hash_key); + + hash_key.dptr = discard_const_p(uint8_t, TDB_MAGIC_HASH_VERIFY_KEY); + hash_key.dsize = sizeof(TDB_MAGIC_HASH_VERIFY_KEY); + newdb->verify_key_hash = tdb->hash_fn(&hash_key); + if (tdb->flags & TDB_INTERNAL) { tdb->map_size = size; tdb->map_ptr = (char *)newdb; @@ -153,6 +163,10 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, unsigned char *vp; uint32_t vertest; unsigned v; + TDB_DATA hash_key; + uint32_t magic_food_hash; + uint32_t verify_key_hash; + const char *hash_alg; if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) { /* Can't log this */ @@ -171,7 +185,14 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, tdb->log.log_fn = null_log_fn; tdb->log.log_private = NULL; } - tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash; + + if (hash_fn) { + tdb->hash_fn = hash_fn; + hash_alg = "user_defined"; + } else { + tdb->hash_fn = default_tdb_hash; + hash_alg = "default"; + } /* cache the page size */ tdb->page_size = getpagesize(); @@ -270,6 +291,35 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, goto fail; } + hash_key.dptr = discard_const_p(uint8_t, TDB_MAGIC_FOOD); + hash_key.dsize = sizeof(TDB_MAGIC_FOOD); + magic_food_hash = tdb->hash_fn(&hash_key); + + hash_key.dptr = discard_const_p(uint8_t, TDB_MAGIC_HASH_VERIFY_KEY); + hash_key.dsize = sizeof(TDB_MAGIC_HASH_VERIFY_KEY); + verify_key_hash = tdb->hash_fn(&hash_key); + + if ((tdb->header.magic_food_hash == 0) && + (tdb->header.verify_key_hash == 0)) { + /* older TDB without magic hash references */ + } else if ((tdb->header.magic_food_hash != magic_food_hash) || + (tdb->header.verify_key_hash != verify_key_hash)) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: %s " + "was created with a different hash function current[%s]" + "magic_food_hash[0x%08X %s 0x%08X] " + "verify_key_hash[0x%08X %s 0x%08X]\n", + name, + hash_alg, + tdb->header.magic_food_hash, + (tdb->header.magic_food_hash == magic_food_hash)?"==":"!=", + magic_food_hash, + tdb->header.verify_key_hash, + (tdb->header.verify_key_hash == verify_key_hash)?"==":"!=", + verify_key_hash)); + errno = EINVAL; + goto fail; + } + /* Is it already in the open list? If so, fail. */ if (tdb_already_open(st.st_dev, st.st_ino)) { TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: " diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h index 562b813ff115..226ace279c50 100644 --- a/lib/tdb/common/tdb_private.h +++ b/lib/tdb/common/tdb_private.h @@ -48,6 +48,7 @@ typedef uint32_t tdb_off_t; #define TDB_FREE_MAGIC (~TDB_MAGIC) #define TDB_DEAD_MAGIC (0xFEE1DEAD) #define TDB_RECOVERY_MAGIC (0xf53bc0e7U) +#define TDB_MAGIC_HASH_VERIFY_KEY "!TDB_MAGIC_HASH_VERIFY_KEY!" #define TDB_ALIGNMENT 4 #define DEFAULT_HASH_SIZE 131 #define FREELIST_TOP (sizeof(struct tdb_header)) @@ -114,7 +115,9 @@ struct tdb_header { tdb_off_t rwlocks; /* obsolete - kept to detect old formats */ tdb_off_t recovery_start; /* offset of transaction recovery region */ tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */ - tdb_off_t reserved[29]; + uint32_t magic_food_hash; + uint32_t verify_key_hash; + tdb_off_t reserved[27]; }; struct tdb_lock_type {