diff options
author | Michael Adam <obnox@samba.org> | 2011-08-15 01:30:32 +0200 |
---|---|---|
committer | Michael Adam <obnox@samba.org> | 2011-08-15 17:15:14 +0200 |
commit | 32b74111040f503cf033cdca8d1fbd621543004b (patch) | |
tree | f1c6f891f22917fc8ae75216e36a9cde75933c7c /source3/registry/reg_backend_db.c | |
parent | 8a36e721407dd8eb3b1df71fbbbc7a6e3c804e48 (diff) | |
download | samba-32b74111040f503cf033cdca8d1fbd621543004b.tar.gz samba-32b74111040f503cf033cdca8d1fbd621543004b.tar.xz samba-32b74111040f503cf033cdca8d1fbd621543004b.zip |
s3:registry: fix regdb_key_exists: the record has to contain at least the 4-byte subkey counter
More precisley, we return false if the record does not match the required
structure of a leading 4-byte subkey counter followed by the corresponding
number zero-terminated strings.
Diffstat (limited to 'source3/registry/reg_backend_db.c')
-rw-r--r-- | source3/registry/reg_backend_db.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c index 57d6d3980c..4e10bf652a 100644 --- a/source3/registry/reg_backend_db.c +++ b/source3/registry/reg_backend_db.c @@ -1389,6 +1389,11 @@ static TDB_DATA regdb_fetch_key_internal(struct db_context *db, * Existence of a key is authoritatively defined by * the existence of the record that contains the list * of its subkeys. + * + * Return false, if the record does not match the correct + * structure of an initial 4-byte counter and then a + * list of the corresponding number of zero-terminated + * strings. */ static bool regdb_key_exists(struct db_context *db, const char *key) { @@ -1396,6 +1401,10 @@ static bool regdb_key_exists(struct db_context *db, const char *key) TDB_DATA value; bool ret = false; char *path; + uint32_t buflen; + const char *buf; + uint32_t num_items, i; + int32_t len; if (key == NULL) { goto done; @@ -1412,7 +1421,69 @@ static bool regdb_key_exists(struct db_context *db, const char *key) } value = regdb_fetch_key_internal(db, mem_ctx, path); - ret = (value.dptr != NULL); + if (value.dptr == NULL) { + goto done; + } + + if (value.dsize == 0) { + DEBUG(10, ("regdb_key_exists: subkeylist-record for key " + "[%s] is empty: Could be a deleted record in a " + "clustered (ctdb) environment?\n", + path)); + goto done; + } + + len = tdb_unpack(value.dptr, value.dsize, "d", &num_items); + if (len == (int32_t)-1) { + DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key " + "[%s] is invalid: Could not parse initial 4-byte " + "counter. record data length is %u.\n", + path, (unsigned int)value.dsize)); + goto done; + } + + /* + * Note: the tdb_unpack check above implies that len <= value.dsize + */ + buflen = value.dsize - len; + buf = (const char *)value.dptr + len; + + len = 0; + + for (i = 0; i < num_items; i++) { + if (buflen == 0) { + break; + } + len = strnlen(buf, buflen) + 1; + if (buflen < len) { + DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record " + "for key [%s] is corrupt: %u items expected, " + "item number %u is not zero terminated.\n", + path, num_items, i+1)); + goto done; + } + + buf += len; + buflen -= len; + } + + if (buflen > 0) { + DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key " + "[%s] is corrupt: %u items expected and found, but " + "the record contains additional %u bytes\n", + path, num_items, buflen)); + goto done; + } + + if (i < num_items) { + DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key " + "[%s] is corrupt: %u items expected, but only %u " + "items found.\n", + path, num_items, i+1)); + goto done; + } + + ret = true; done: TALLOC_FREE(mem_ctx); |