2 Samba CIFS implementation
3 Registry backend for REGF files
4 Copyright (C) 2005-2007 Jelmer Vernooij, jelmer@samba.org
5 Copyright (C) 2006 Wilco Baan Hofman, wilco@baanhofman.nl
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include "lib/registry/hive.h"
22 #include "system/filesys.h"
23 #include "system/time.h"
24 #include "lib/registry/tdr_regf.h"
25 #include "librpc/gen_ndr/ndr_security.h"
26 #include "librpc/gen_ndr/winreg.h"
27 #include "param/param.h"
29 static struct hive_operations reg_backend_regf;
32 * There are several places on the web where the REGF format is explained;
38 * - Return error codes that make more sense
40 * - do more things in-memory
44 * Read HBIN blocks into memory
49 struct hbin_block **hbins;
50 struct regf_hdr *header;
51 struct smb_iconv_convenience *iconv_convenience;
54 static WERROR regf_save_hbin(struct regf_data *data);
56 struct regf_key_data {
58 struct regf_data *hive;
63 static struct hbin_block *hbin_by_offset(const struct regf_data *data,
64 uint32_t offset, uint32_t *rel_offset)
68 for (i = 0; data->hbins[i]; i++) {
69 if (offset >= data->hbins[i]->offset_from_first &&
70 offset < data->hbins[i]->offset_from_first+
71 data->hbins[i]->offset_to_next) {
72 if (rel_offset != NULL)
73 *rel_offset = offset - data->hbins[i]->offset_from_first - 0x20;
74 return data->hbins[i];
82 * Validate a regf header
83 * For now, do nothing, but we should check the checksum
85 static uint32_t regf_hdr_checksum(const uint8_t *buffer)
87 uint32_t checksum = 0, x;
90 for (i = 0; i < 0x01FB; i+= 4) {
99 * Obtain the contents of a HBIN block
101 static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset)
104 struct hbin_block *hbin;
110 hbin = hbin_by_offset(data, offset, &rel_offset);
113 DEBUG(1, ("Can't find HBIN containing 0x%04x\n", offset));
117 ret.length = IVAL(hbin->data, rel_offset);
118 if (!(ret.length & 0x80000000)) {
119 DEBUG(0, ("Trying to use dirty block at 0x%04x\n", offset));
123 /* remove high bit */
124 ret.length = (ret.length ^ 0xffffffff) + 1;
126 ret.length -= 4; /* 4 bytes for the length... */
127 ret.data = hbin->data +
128 (offset - hbin->offset_from_first - 0x20) + 4;
133 static bool hbin_get_tdr(struct regf_data *regf, uint32_t offset,
134 TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p)
136 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
138 pull->data = hbin_get(regf, offset);
139 if (!pull->data.data) {
140 DEBUG(1, ("Unable to get data at 0x%04x\n", offset));
145 if (NT_STATUS_IS_ERR(pull_fn(pull, ctx, p))) {
146 DEBUG(1, ("Error parsing record at 0x%04x using tdr\n",
156 /* Allocate some new data */
157 static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size,
161 uint32_t rel_offset = -1; /* Relative offset ! */
162 struct hbin_block *hbin = NULL;
168 return data_blob(NULL, 0);
170 size += 4; /* Need to include int32 for the length */
172 /* Allocate as a multiple of 8 */
173 size = (size + 7) & ~7;
178 for (i = 0; (hbin = data->hbins[i]); i++) {
181 for (j = 0; j < hbin->offset_to_next-0x20; j+= my_size) {
182 my_size = IVALS(hbin->data, j);
184 if (my_size == 0x0) {
185 DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
189 if (my_size % 8 != 0) {
190 DEBUG(0, ("Encountered non-aligned block!\n"));
193 if (my_size < 0) { /* Used... */
195 } else if (my_size == size) { /* exact match */
197 DEBUG(4, ("Found free block of exact size %d in middle of HBIN\n",
200 } else if (my_size > size) { /* data will remain */
202 /* Split this block and mark the next block as free */
203 SIVAL(hbin->data, rel_offset+size, my_size-size);
204 DEBUG(4, ("Found free block of size %d (needing %d) in middle of HBIN\n",
210 if (rel_offset != -1)
214 /* No space available in previous hbins,
215 * allocate new one */
216 if (data->hbins[i] == NULL) {
217 DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n",
219 data->hbins = talloc_realloc(data, data->hbins,
220 struct hbin_block *, i+2);
221 hbin = talloc(data->hbins, struct hbin_block);
222 SMB_ASSERT(hbin != NULL);
224 data->hbins[i] = hbin;
225 data->hbins[i+1] = NULL;
227 hbin->HBIN_ID = talloc_strdup(hbin, "hbin");
228 hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next);
229 hbin->offset_to_next = 0x1000;
230 hbin->unknown[0] = 0;
231 hbin->unknown[0] = 0;
232 unix_to_nt_time(&hbin->last_change, time(NULL));
233 hbin->block_size = hbin->offset_to_next;
234 hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20);
237 SIVAL(hbin->data, size, hbin->block_size - size - 0x20);
240 /* Set size and mark as used */
241 SIVAL(hbin->data, rel_offset, -size);
243 ret.data = hbin->data + rel_offset + 0x4; /* Skip past length */
244 ret.length = size - 0x4;
246 uint32_t new_rel_offset;
247 *offset = hbin->offset_from_first + rel_offset + 0x20;
248 SMB_ASSERT(hbin_by_offset(data, *offset, &new_rel_offset) == hbin);
249 SMB_ASSERT(new_rel_offset == rel_offset);
255 /* Store a data blob. Return the offset at which it was stored */
256 static uint32_t hbin_store (struct regf_data *data, DATA_BLOB blob)
259 DATA_BLOB dest = hbin_alloc(data, blob.length, &ret);
261 memcpy(dest.data, blob.data, blob.length);
266 static uint32_t hbin_store_tdr(struct regf_data *data,
267 tdr_push_fn_t push_fn, void *p)
269 struct tdr_push *push = tdr_push_init(data, data->iconv_convenience);
272 if (NT_STATUS_IS_ERR(push_fn(push, p))) {
273 DEBUG(0, ("Error during push\n"));
277 ret = hbin_store(data, push->data);
285 /* Free existing data */
286 static void hbin_free (struct regf_data *data, uint32_t offset)
291 struct hbin_block *hbin;
293 SMB_ASSERT (offset > 0);
295 hbin = hbin_by_offset(data, offset, &rel_offset);
300 /* Get original size */
301 size = IVALS(hbin->data, rel_offset);
304 DEBUG(1, ("Trying to free already freed block at 0x%04x\n",
311 /* If the next block is free, merge into big free block */
312 if (rel_offset + size < hbin->offset_to_next) {
313 next_size = IVALS(hbin->data, rel_offset+size);
319 /* Write block size */
320 SIVALS(hbin->data, rel_offset, size);
324 * Store a data blob data was already stored, but has changed in size
325 * Will try to save it at the current location if possible, otherwise
326 * does a free + store */
327 static uint32_t hbin_store_resize(struct regf_data *data,
328 uint32_t orig_offset, DATA_BLOB blob)
331 struct hbin_block *hbin = hbin_by_offset(data, orig_offset,
336 int32_t possible_size;
339 SMB_ASSERT(orig_offset > 0);
342 return hbin_store(data, blob);
344 /* Get original size */
345 orig_size = -IVALS(hbin->data, rel_offset);
347 needed_size = blob.length + 4; /* Add int32 containing length */
348 needed_size = (needed_size + 7) & ~7; /* Align */
350 /* Fits into current allocated block */
351 if (orig_size >= needed_size) {
352 memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length);
353 /* If the difference in size is greater than 0x4, split the block
354 * and free/merge it */
355 if (orig_size - needed_size > 0x4) {
356 SIVALS(hbin->data, rel_offset, -needed_size);
357 SIVALS(hbin->data, rel_offset + needed_size,
358 needed_size-orig_size);
359 hbin_free(data, orig_offset + needed_size);
364 possible_size = orig_size;
366 /* Check if it can be combined with the next few free records */
367 for (i = rel_offset; i < hbin->offset_to_next - 0x20; i += my_size) {
368 if (IVALS(hbin->data, i) < 0) /* Used */
371 my_size = IVALS(hbin->data, i);
373 if (my_size == 0x0) {
374 DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
377 possible_size += my_size;
380 if (possible_size >= blob.length) {
381 SIVAL(hbin->data, rel_offset, -possible_size);
382 memcpy(hbin->data + rel_offset + 0x4,
383 blob.data, blob.length);
388 hbin_free(data, orig_offset);
389 return hbin_store(data, blob);
392 static uint32_t hbin_store_tdr_resize(struct regf_data *regf,
393 tdr_push_fn_t push_fn,
394 uint32_t orig_offset, void *p)
396 struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience);
399 if (NT_STATUS_IS_ERR(push_fn(push, p))) {
400 DEBUG(0, ("Error during push\n"));
404 ret = hbin_store_resize(regf, orig_offset, push->data);
411 static uint32_t regf_create_lh_hash(const char *name)
417 hash_name = strupper_talloc(NULL, name);
418 for (i = 0; *(hash_name + i) != 0; i++) {
420 ret += *(hash_name + i);
422 talloc_free(hash_name);
426 static WERROR regf_get_info(TALLOC_CTX *mem_ctx,
427 const struct hive_key *key,
428 const char **classname,
429 uint32_t *num_subkeys,
430 uint32_t *num_values,
431 NTTIME *last_mod_time,
432 uint32_t *max_subkeynamelen,
433 uint32_t *max_valnamelen,
434 uint32_t *max_valbufsize)
436 const struct regf_key_data *private_data =
437 (const struct regf_key_data *)key;
439 if (num_subkeys != NULL)
440 *num_subkeys = private_data->nk->num_subkeys;
442 if (num_values != NULL)
443 *num_values = private_data->nk->num_values;
445 if (classname != NULL) {
446 if (private_data->nk->clsname_offset != -1) {
447 DATA_BLOB data = hbin_get(private_data->hive,
448 private_data->nk->clsname_offset);
449 *classname = talloc_strndup(mem_ctx,
451 private_data->nk->clsname_length);
456 /* TODO: Last mod time */
458 /* TODO: max valnamelen */
460 /* TODO: max valbufsize */
462 /* TODO: max subkeynamelen */
467 static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx,
468 struct regf_data *regf,
472 struct regf_key_data *ret;
474 ret = talloc_zero(ctx, struct regf_key_data);
475 ret->key.ops = ®_backend_regf;
476 ret->hive = talloc_reference(ret, regf);
477 ret->offset = offset;
478 nk = talloc(ret, struct nk_block);
484 if (!hbin_get_tdr(regf, offset, nk,
485 (tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
486 DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
490 if (strcmp(nk->header, "nk") != 0) {
491 DEBUG(0, ("Expected nk record, got %s\n", nk->header));
500 static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key,
501 int idx, const char **name,
502 uint32_t *data_type, DATA_BLOB *data)
504 const struct regf_key_data *private_data =
505 (const struct regf_key_data *)key;
507 struct regf_data *regf = private_data->hive;
511 if (idx >= private_data->nk->num_values)
512 return WERR_NO_MORE_ITEMS;
514 tmp = hbin_get(regf, private_data->nk->values_offset);
516 DEBUG(0, ("Unable to find value list\n"));
517 return WERR_GENERAL_FAILURE;
520 if (tmp.length < private_data->nk->num_values * 4) {
521 DEBUG(1, ("Value counts mismatch\n"));
524 vk_offset = IVAL(tmp.data, idx * 4);
526 vk = talloc(NULL, struct vk_block);
527 W_ERROR_HAVE_NO_MEMORY(vk);
529 if (!hbin_get_tdr(regf, vk_offset, vk,
530 (tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
531 DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));
533 return WERR_GENERAL_FAILURE;
536 /* FIXME: name character set ?*/
538 *name = talloc_strndup(ctx, vk->data_name, vk->name_length);
540 if (data_type != NULL)
541 *data_type = vk->data_type;
543 if (vk->data_length & 0x80000000) {
544 vk->data_length &=~0x80000000;
545 data->data = (uint8_t *)&vk->data_offset;
546 data->length = vk->data_length;
548 *data = hbin_get(regf, vk->data_offset);
551 if (data->length < vk->data_length) {
552 DEBUG(1, ("Read data less than indicated data length!\n"));
560 static WERROR regf_get_value_by_name(TALLOC_CTX *mem_ctx,
561 struct hive_key *key, const char *name,
562 uint32_t *type, DATA_BLOB *data)
568 /* FIXME: Do binary search? Is this list sorted at all? */
570 for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i,
571 &vname, type, data));
573 if (!strcmp(vname, name))
577 if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
584 static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx,
585 const struct hive_key *key,
586 uint32_t idx, const char **name,
587 const char **classname,
588 NTTIME *last_mod_time)
591 struct regf_key_data *ret;
592 const struct regf_key_data *private_data = (const struct regf_key_data *)key;
593 struct nk_block *nk = private_data->nk;
596 if (idx >= nk->num_subkeys)
597 return WERR_NO_MORE_ITEMS;
599 data = hbin_get(private_data->hive, nk->subkeys_offset);
601 DEBUG(0, ("Unable to find subkey list\n"));
602 return WERR_GENERAL_FAILURE;
605 if (!strncmp((char *)data.data, "li", 2)) {
607 struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
609 DEBUG(10, ("Subkeys in LI list\n"));
612 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) {
613 DEBUG(0, ("Error parsing LI list\n"));
615 return WERR_GENERAL_FAILURE;
618 SMB_ASSERT(!strncmp(li.header, "li", 2));
620 if (li.key_count != nk->num_subkeys) {
621 DEBUG(0, ("Subkey counts don't match\n"));
622 return WERR_GENERAL_FAILURE;
624 key_off = li.nk_offset[idx];
626 } else if (!strncmp((char *)data.data, "lf", 2)) {
628 struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
630 DEBUG(10, ("Subkeys in LF list\n"));
633 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) {
634 DEBUG(0, ("Error parsing LF list\n"));
636 return WERR_GENERAL_FAILURE;
639 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
641 if (lf.key_count != nk->num_subkeys) {
642 DEBUG(0, ("Subkey counts don't match\n"));
643 return WERR_GENERAL_FAILURE;
646 key_off = lf.hr[idx].nk_offset;
647 } else if (!strncmp((char *)data.data, "lh", 2)) {
649 struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
651 DEBUG(10, ("Subkeys in LH list\n"));
654 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) {
655 DEBUG(0, ("Error parsing LH list\n"));
657 return WERR_GENERAL_FAILURE;
660 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
662 if (lh.key_count != nk->num_subkeys) {
663 DEBUG(0, ("Subkey counts don't match\n"));
664 return WERR_GENERAL_FAILURE;
666 key_off = lh.hr[idx].nk_offset;
667 } else if (!strncmp((char *)data.data, "ri", 2)) {
669 struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
671 uint16_t sublist_count = 0;
673 DEBUG(10, ("Subkeys in RI list\n"));
676 if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) {
677 DEBUG(0, ("Error parsing RI list\n"));
679 return WERR_GENERAL_FAILURE;
681 SMB_ASSERT(!strncmp(ri.header, "ri", 2));
683 for (i = 0; i < ri.key_count; i++) {
686 /* Get sublist data blob */
687 list_data = hbin_get(private_data->hive, ri.offset[i]);
688 if (!list_data.data) {
689 DEBUG(0, ("Error getting RI list."));
691 return WERR_GENERAL_FAILURE;
694 pull->data = list_data;
696 if (!strncmp((char *)list_data.data, "li", 2)) {
699 DEBUG(10, ("Subkeys in RI->LI list\n"));
701 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull,
704 DEBUG(0, ("Error parsing LI list from RI\n"));
706 return WERR_GENERAL_FAILURE;
708 SMB_ASSERT(!strncmp(li.header, "li", 2));
710 /* Advance to next sublist if necessary */
711 if (idx >= sublist_count + li.key_count) {
712 sublist_count += li.key_count;
715 key_off = li.nk_offset[idx - sublist_count];
716 sublist_count += li.key_count;
718 } else if (!strncmp((char *)list_data.data, "lh", 2)) {
721 DEBUG(10, ("Subkeys in RI->LH list\n"));
723 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull,
726 DEBUG(0, ("Error parsing LH list from RI\n"));
728 return WERR_GENERAL_FAILURE;
730 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
732 /* Advance to next sublist if necessary */
733 if (idx >= sublist_count + lh.key_count) {
734 sublist_count += lh.key_count;
737 key_off = lh.hr[idx - sublist_count].nk_offset;
738 sublist_count += lh.key_count;
741 DEBUG(0,("Unknown sublist in ri block\n"));
744 return WERR_GENERAL_FAILURE;
751 if (idx > sublist_count) {
752 return WERR_NO_MORE_ITEMS;
756 DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n",
757 nk->subkeys_offset, data.data[0], data.data[1]));
758 return WERR_GENERAL_FAILURE;
761 ret = regf_get_key (ctx, private_data->hive, key_off);
763 if (classname != NULL) {
764 if (ret->nk->clsname_offset != -1) {
765 DATA_BLOB db = hbin_get(ret->hive,
766 ret->nk->clsname_offset);
767 *classname = talloc_strndup(ctx,
769 ret->nk->clsname_length);
774 if (last_mod_time != NULL)
775 *last_mod_time = ret->nk->last_change;
778 *name = talloc_steal(ctx, ret->nk->key_name);
785 static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx,
786 const struct hive_key *key,
788 const char *name, uint32_t *ret)
790 DATA_BLOB subkey_data;
791 struct nk_block subkey;
792 struct tdr_pull *pull;
793 const struct regf_key_data *private_data =
794 (const struct regf_key_data *)key;
796 subkey_data = hbin_get(private_data->hive, offset);
797 if (!subkey_data.data) {
798 DEBUG(0, ("Unable to retrieve subkey HBIN\n"));
799 return WERR_GENERAL_FAILURE;
802 pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
804 pull->data = subkey_data;
806 if (NT_STATUS_IS_ERR(tdr_pull_nk_block(pull, ctx, &subkey))) {
807 DEBUG(0, ("Error parsing NK structure.\n"));
809 return WERR_GENERAL_FAILURE;
813 if (strncmp(subkey.header, "nk", 2)) {
814 DEBUG(0, ("Not an NK structure.\n"));
815 return WERR_GENERAL_FAILURE;
818 if (!strcasecmp(subkey.key_name, name)) {
826 static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx,
827 const struct hive_key *key,
829 struct hive_key **ret)
832 const struct regf_key_data *private_data =
833 (const struct regf_key_data *)key;
834 struct nk_block *nk = private_data->nk;
835 uint32_t key_off = 0;
837 data = hbin_get(private_data->hive, nk->subkeys_offset);
839 DEBUG(0, ("Unable to find subkey list\n"));
840 return WERR_GENERAL_FAILURE;
843 if (!strncmp((char *)data.data, "li", 2)) {
845 struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
848 DEBUG(10, ("Subkeys in LI list\n"));
851 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) {
852 DEBUG(0, ("Error parsing LI list\n"));
854 return WERR_GENERAL_FAILURE;
857 SMB_ASSERT(!strncmp(li.header, "li", 2));
859 if (li.key_count != nk->num_subkeys) {
860 DEBUG(0, ("Subkey counts don't match\n"));
861 return WERR_GENERAL_FAILURE;
864 for (i = 0; i < li.key_count; i++) {
865 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
874 } else if (!strncmp((char *)data.data, "lf", 2)) {
876 struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
879 DEBUG(10, ("Subkeys in LF list\n"));
882 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) {
883 DEBUG(0, ("Error parsing LF list\n"));
885 return WERR_GENERAL_FAILURE;
888 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
890 if (lf.key_count != nk->num_subkeys) {
891 DEBUG(0, ("Subkey counts don't match\n"));
892 return WERR_GENERAL_FAILURE;
895 for (i = 0; i < lf.key_count; i++) {
896 if (strncmp(lf.hr[i].hash, name, 4)) {
899 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
909 } else if (!strncmp((char *)data.data, "lh", 2)) {
911 struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
915 DEBUG(10, ("Subkeys in LH list\n"));
918 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) {
919 DEBUG(0, ("Error parsing LH list\n"));
921 return WERR_GENERAL_FAILURE;
924 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
926 if (lh.key_count != nk->num_subkeys) {
927 DEBUG(0, ("Subkey counts don't match\n"));
928 return WERR_GENERAL_FAILURE;
931 hash = regf_create_lh_hash(name);
932 for (i = 0; i < lh.key_count; i++) {
933 if (lh.hr[i].base37 != hash) {
936 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
946 } else if (!strncmp((char *)data.data, "ri", 2)) {
948 struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
951 DEBUG(10, ("Subkeys in RI list\n"));
954 if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) {
955 DEBUG(0, ("Error parsing RI list\n"));
957 return WERR_GENERAL_FAILURE;
959 SMB_ASSERT(!strncmp(ri.header, "ri", 2));
961 for (i = 0; i < ri.key_count; i++) {
964 /* Get sublist data blob */
965 list_data = hbin_get(private_data->hive, ri.offset[i]);
966 if (list_data.data == NULL) {
967 DEBUG(0, ("Error getting RI list."));
969 return WERR_GENERAL_FAILURE;
972 pull->data = list_data;
974 if (!strncmp((char *)list_data.data, "li", 2)) {
977 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull,
980 DEBUG(0, ("Error parsing LI list from RI\n"));
982 return WERR_GENERAL_FAILURE;
984 SMB_ASSERT(!strncmp(li.header, "li", 2));
986 for (j = 0; j < li.key_count; j++) {
987 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
994 } else if (!strncmp((char *)list_data.data, "lh", 2)) {
998 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull,
1001 DEBUG(0, ("Error parsing LH list from RI\n"));
1003 return WERR_GENERAL_FAILURE;
1005 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1007 hash = regf_create_lh_hash(name);
1008 for (j = 0; j < lh.key_count; j++) {
1009 if (lh.hr[j].base37 != hash) {
1012 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
1025 return WERR_BADFILE;
1027 DEBUG(0, ("Unknown subkey list type.\n"));
1028 return WERR_GENERAL_FAILURE;
1031 *ret = (struct hive_key *)regf_get_key(ctx, private_data->hive,
1036 static WERROR regf_set_sec_desc(struct hive_key *key,
1037 const struct security_descriptor *sec_desc)
1039 const struct regf_key_data *private_data =
1040 (const struct regf_key_data *)key;
1041 struct sk_block cur_sk, sk, new_sk;
1042 struct regf_data *regf = private_data->hive;
1043 struct nk_block root;
1045 uint32_t sk_offset, cur_sk_offset;
1046 bool update_cur_sk = false;
1048 /* Get the root nk */
1049 hbin_get_tdr(regf, regf->header->data_offset, regf,
1050 (tdr_pull_fn_t) tdr_pull_nk_block, &root);
1052 /* Push the security descriptor to a blob */
1053 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL,
1054 sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
1055 DEBUG(0, ("Unable to push security descriptor\n"));
1056 return WERR_GENERAL_FAILURE;
1059 /* Get the current security descriptor for the key */
1060 if (!hbin_get_tdr(regf, private_data->nk->sk_offset, regf,
1061 (tdr_pull_fn_t) tdr_pull_sk_block, &cur_sk)) {
1062 DEBUG(0, ("Unable to find security descriptor for current key\n"));
1063 return WERR_BADFILE;
1065 /* If there's no change, change nothing. */
1066 if (memcmp(data.data, cur_sk.sec_desc,
1067 MIN(data.length, cur_sk.rec_size)) == 0) {
1071 /* Delete the current sk if only this key is using it */
1072 if (cur_sk.ref_cnt == 1) {
1073 /* Get the previous security descriptor for the key */
1074 if (!hbin_get_tdr(regf, cur_sk.prev_offset, regf,
1075 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1076 DEBUG(0, ("Unable to find prev security descriptor for current key\n"));
1077 return WERR_BADFILE;
1079 /* Change and store the previous security descriptor */
1080 sk.next_offset = cur_sk.next_offset;
1081 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block,
1082 cur_sk.prev_offset, &sk);
1084 /* Get the next security descriptor for the key */
1085 if (!hbin_get_tdr(regf, cur_sk.next_offset, regf,
1086 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1087 DEBUG(0, ("Unable to find next security descriptor for current key\n"));
1088 return WERR_BADFILE;
1090 /* Change and store the next security descriptor */
1091 sk.prev_offset = cur_sk.prev_offset;
1092 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block,
1093 cur_sk.next_offset, &sk);
1095 hbin_free(regf, private_data->nk->sk_offset);
1097 /* This key will no longer be referring to this sk */
1099 update_cur_sk = true;
1102 sk_offset = root.sk_offset;
1105 cur_sk_offset = sk_offset;
1106 if (!hbin_get_tdr(regf, sk_offset, regf,
1107 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1108 DEBUG(0, ("Unable to find security descriptor\n"));
1109 return WERR_BADFILE;
1111 if (memcmp(data.data, sk.sec_desc, MIN(data.length, sk.rec_size)) == 0) {
1112 private_data->nk->sk_offset = sk_offset;
1114 hbin_store_tdr_resize(regf,
1115 (tdr_push_fn_t) tdr_push_sk_block,
1117 hbin_store_tdr_resize(regf,
1118 (tdr_push_fn_t) tdr_push_nk_block,
1119 private_data->offset,
1123 sk_offset = sk.next_offset;
1124 } while (sk_offset != root.sk_offset);
1126 ZERO_STRUCT(new_sk);
1127 new_sk.header = "sk";
1128 new_sk.prev_offset = cur_sk_offset;
1129 new_sk.next_offset = root.sk_offset;
1131 new_sk.rec_size = data.length;
1132 new_sk.sec_desc = data.data;
1134 sk_offset = hbin_store_tdr(regf,
1135 (tdr_push_fn_t) tdr_push_sk_block,
1137 if (sk_offset == -1) {
1138 DEBUG(0, ("Error storing sk block\n"));
1139 return WERR_GENERAL_FAILURE;
1141 private_data->nk->sk_offset = sk_offset;
1143 if (update_cur_sk) {
1144 hbin_store_tdr_resize(regf,
1145 (tdr_push_fn_t) tdr_push_sk_block,
1146 private_data->nk->sk_offset, &cur_sk);
1149 /* Get the previous security descriptor for the key */
1150 if (!hbin_get_tdr(regf, new_sk.prev_offset, regf,
1151 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1152 DEBUG(0, ("Unable to find security descriptor for previous key\n"));
1153 return WERR_BADFILE;
1155 /* Change and store the previous security descriptor */
1156 sk.next_offset = sk_offset;
1157 hbin_store_tdr_resize(regf,
1158 (tdr_push_fn_t) tdr_push_sk_block,
1159 cur_sk.prev_offset, &sk);
1161 /* Get the next security descriptor for the key (always root, as we append) */
1162 if (!hbin_get_tdr(regf, new_sk.next_offset, regf,
1163 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1164 DEBUG(0, ("Unable to find security descriptor for current key\n"));
1165 return WERR_BADFILE;
1167 /* Change and store the next security descriptor (always root, as we append) */
1168 sk.prev_offset = sk_offset;
1169 hbin_store_tdr_resize(regf,
1170 (tdr_push_fn_t) tdr_push_sk_block,
1171 root.sk_offset, &sk);
1175 hbin_store_tdr_resize(regf,
1176 (tdr_push_fn_t) tdr_push_sk_block,
1177 private_data->offset, private_data->nk);
1181 static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key,
1182 struct security_descriptor **sd)
1184 const struct regf_key_data *private_data =
1185 (const struct regf_key_data *)key;
1187 struct regf_data *regf = private_data->hive;
1190 if (!hbin_get_tdr(regf, private_data->nk->sk_offset, ctx,
1191 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1192 DEBUG(0, ("Unable to find security descriptor\n"));
1193 return WERR_GENERAL_FAILURE;
1196 if (strcmp(sk.header, "sk") != 0) {
1197 DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header));
1198 return WERR_GENERAL_FAILURE;
1201 *sd = talloc(ctx, struct security_descriptor);
1202 W_ERROR_HAVE_NO_MEMORY(*sd);
1204 data.data = sk.sec_desc;
1205 data.length = sk.rec_size;
1206 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, NULL, *sd,
1207 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) {
1208 DEBUG(0, ("Error parsing security descriptor\n"));
1209 return WERR_GENERAL_FAILURE;
1215 static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset,
1217 uint32_t key_offset, uint32_t *ret)
1221 /* Create a new key if necessary */
1222 if (list_offset == -1) {
1223 if (regf->header->version.major != 1) {
1224 DEBUG(0, ("Can't store keys in unknown registry format\n"));
1225 return WERR_NOT_SUPPORTED;
1227 if (regf->header->version.minor < 3) {
1234 li.nk_offset = talloc_array(regf, uint32_t, 1);
1235 W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1236 li.nk_offset[0] = key_offset;
1238 *ret = hbin_store_tdr(regf,
1239 (tdr_push_fn_t) tdr_push_li_block,
1242 talloc_free(li.nk_offset);
1243 } else if (regf->header->version.minor == 3 ||
1244 regf->header->version.minor == 4) {
1251 lf.hr = talloc_array(regf, struct hash_record, 1);
1252 W_ERROR_HAVE_NO_MEMORY(lf.hr);
1253 lf.hr[0].nk_offset = key_offset;
1254 lf.hr[0].hash = talloc_strndup(lf.hr, name, 4);
1255 W_ERROR_HAVE_NO_MEMORY(lf.hr[0].hash);
1257 *ret = hbin_store_tdr(regf,
1258 (tdr_push_fn_t) tdr_push_lf_block,
1262 } else if (regf->header->version.minor == 5) {
1269 lh.hr = talloc_array(regf, struct lh_hash, 1);
1270 W_ERROR_HAVE_NO_MEMORY(lh.hr);
1271 lh.hr[0].nk_offset = key_offset;
1272 lh.hr[0].base37 = regf_create_lh_hash(name);
1274 *ret = hbin_store_tdr(regf,
1275 (tdr_push_fn_t) tdr_push_lh_block,
1283 data = hbin_get(regf, list_offset);
1285 DEBUG(0, ("Unable to find subkey list\n"));
1286 return WERR_BADFILE;
1289 if (!strncmp((char *)data.data, "li", 2)) {
1290 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1295 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) {
1296 DEBUG(0, ("Error parsing LI list\n"));
1298 return WERR_BADFILE;
1302 if (strncmp(li.header, "li", 2) != 0) {
1304 DEBUG(0, ("LI header corrupt\n"));
1305 return WERR_BADFILE;
1308 li.nk_offset = talloc_realloc(regf, li.nk_offset,
1309 uint32_t, li.key_count+1);
1310 W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1311 li.nk_offset[li.key_count] = key_offset;
1313 *ret = hbin_store_tdr_resize(regf,
1314 (tdr_push_fn_t)tdr_push_li_block,
1317 talloc_free(li.nk_offset);
1318 } else if (!strncmp((char *)data.data, "lf", 2)) {
1319 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1324 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) {
1325 DEBUG(0, ("Error parsing LF list\n"));
1327 return WERR_BADFILE;
1330 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1332 lf.hr = talloc_realloc(regf, lf.hr, struct hash_record,
1334 W_ERROR_HAVE_NO_MEMORY(lf.hr);
1335 lf.hr[lf.key_count].nk_offset = key_offset;
1336 lf.hr[lf.key_count].hash = talloc_strndup(lf.hr, name, 4);
1337 W_ERROR_HAVE_NO_MEMORY(lf.hr[lf.key_count].hash);
1339 *ret = hbin_store_tdr_resize(regf,
1340 (tdr_push_fn_t)tdr_push_lf_block,
1344 } else if (!strncmp((char *)data.data, "lh", 2)) {
1345 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1350 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) {
1351 DEBUG(0, ("Error parsing LH list\n"));
1353 return WERR_BADFILE;
1356 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1358 lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash,
1360 W_ERROR_HAVE_NO_MEMORY(lh.hr);
1361 lh.hr[lh.key_count].nk_offset = key_offset;
1362 lh.hr[lh.key_count].base37 = regf_create_lh_hash(name);
1364 *ret = hbin_store_tdr_resize(regf,
1365 (tdr_push_fn_t)tdr_push_lh_block,
1369 } else if (!strncmp((char *)data.data, "ri", 2)) {
1371 DEBUG(0, ("Adding to 'ri' subkey list is not supported yet.\n"));
1372 return WERR_NOT_SUPPORTED;
1374 DEBUG(0, ("Cannot add to unknown subkey list\n"));
1375 return WERR_BADFILE;
1381 static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset,
1382 uint32_t key_offset, uint32_t *ret)
1386 data = hbin_get(regf, list_offset);
1388 DEBUG(0, ("Unable to find subkey list\n"));
1389 return WERR_BADFILE;
1392 if (strncmp((char *)data.data, "li", 2) == 0) {
1394 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1396 bool found_offset = false;
1398 DEBUG(10, ("Subkeys in LI list\n"));
1402 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) {
1403 DEBUG(0, ("Error parsing LI list\n"));
1405 return WERR_BADFILE;
1409 SMB_ASSERT(!strncmp(li.header, "li", 2));
1411 for (i = 0; i < li.key_count; i++) {
1413 li.nk_offset[i-1] = li.nk_offset[i];
1415 if (li.nk_offset[i] == key_offset) {
1416 found_offset = true;
1420 if (!found_offset) {
1421 DEBUG(2, ("Subkey not found\n"));
1422 return WERR_BADFILE;
1426 /* If the there are no entries left, free the subkey list */
1427 if (li.key_count == 0) {
1428 hbin_free(regf, list_offset);
1432 /* Store li block */
1433 *ret = hbin_store_tdr_resize(regf,
1434 (tdr_push_fn_t) tdr_push_li_block,
1436 } else if (strncmp((char *)data.data, "lf", 2) == 0) {
1438 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1440 bool found_offset = false;
1442 DEBUG(10, ("Subkeys in LF list\n"));
1446 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) {
1447 DEBUG(0, ("Error parsing LF list\n"));
1449 return WERR_BADFILE;
1453 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1455 for (i = 0; i < lf.key_count; i++) {
1457 lf.hr[i-1] = lf.hr[i];
1460 if (lf.hr[i].nk_offset == key_offset) {
1465 if (!found_offset) {
1466 DEBUG(2, ("Subkey not found\n"));
1467 return WERR_BADFILE;
1471 /* If the there are no entries left, free the subkey list */
1472 if (lf.key_count == 0) {
1473 hbin_free(regf, list_offset);
1478 /* Store lf block */
1479 *ret = hbin_store_tdr_resize(regf,
1480 (tdr_push_fn_t) tdr_push_lf_block,
1482 } else if (strncmp((char *)data.data, "lh", 2) == 0) {
1484 struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1486 bool found_offset = false;
1488 DEBUG(10, ("Subkeys in LH list\n"));
1492 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) {
1493 DEBUG(0, ("Error parsing LF list\n"));
1495 return WERR_BADFILE;
1499 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1501 for (i = 0; i < lh.key_count; i++) {
1503 lh.hr[i-1] = lh.hr[i];
1506 if (lh.hr[i].nk_offset == key_offset) {
1511 if (!found_offset) {
1512 DEBUG(0, ("Subkey not found\n"));
1513 return WERR_BADFILE;
1517 /* If the there are no entries left, free the subkey list */
1518 if (lh.key_count == 0) {
1519 hbin_free(regf, list_offset);
1524 /* Store lh block */
1525 *ret = hbin_store_tdr_resize(regf,
1526 (tdr_push_fn_t) tdr_push_lh_block,
1528 } else if (strncmp((char *)data.data, "ri", 2) == 0) {
1530 DEBUG(0, ("Sorry, deletion from ri block is not supported yet.\n"));
1531 return WERR_NOT_SUPPORTED;
1533 DEBUG (0, ("Unknown header found in subkey list.\n"));
1534 return WERR_BADFILE;
1539 static WERROR regf_del_value (struct hive_key *key, const char *name)
1541 struct regf_key_data *private_data = (struct regf_key_data *)key;
1542 struct regf_data *regf = private_data->hive;
1543 struct nk_block *nk = private_data->nk;
1546 bool found_offset = false;
1550 if (nk->values_offset == -1) {
1551 return WERR_BADFILE;
1554 values = hbin_get(regf, nk->values_offset);
1556 for (i = 0; i < nk->num_values; i++) {
1558 ((uint32_t *)values.data)[i-1] = ((uint32_t *) values.data)[i];
1560 vk_offset = IVAL(values.data, i * 4);
1561 if (!hbin_get_tdr(regf, vk_offset, private_data,
1562 (tdr_pull_fn_t)tdr_pull_vk_block,
1564 DEBUG(0, ("Unable to get VK block at %d\n",
1566 return WERR_BADFILE;
1568 if (strcmp(vk.data_name, name) == 0) {
1569 hbin_free(regf, vk_offset);
1570 found_offset = true;
1574 if (!found_offset) {
1575 return WERR_BADFILE;
1578 values.length = (nk->num_values)*4;
1581 /* Store values list and nk */
1582 if (nk->num_values == 0) {
1583 hbin_free(regf, nk->values_offset);
1584 nk->values_offset = -1;
1586 nk->values_offset = hbin_store_resize(regf,
1590 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
1591 private_data->offset, nk);
1593 return regf_save_hbin(private_data->hive);
1597 static WERROR regf_del_key(const struct hive_key *parent, const char *name)
1599 const struct regf_key_data *private_data =
1600 (const struct regf_key_data *)parent;
1601 struct regf_key_data *key;
1602 struct nk_block *parent_nk;
1605 SMB_ASSERT(private_data);
1607 parent_nk = private_data->nk;
1609 if (parent_nk->subkeys_offset == -1) {
1610 DEBUG(4, ("Subkey list is empty, this key cannot contain subkeys.\n"));
1611 return WERR_BADFILE;
1615 if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name,
1616 (struct hive_key **)&key))) {
1617 DEBUG(2, ("Key '%s' not found\n", name));
1618 return WERR_BADFILE;
1621 if (key->nk->subkeys_offset != -1 ||
1622 key->nk->values_offset != -1) {
1623 DEBUG(0, ("Key '%s' is not empty.\n", name));
1624 return WERR_FILE_EXISTS;
1627 /* Delete it from the subkey list. */
1628 error = regf_sl_del_entry(private_data->hive, parent_nk->subkeys_offset,
1629 key->offset, &parent_nk->subkeys_offset);
1630 if (!W_ERROR_IS_OK(error)) {
1631 DEBUG(0, ("Can't store new subkey list for parent key. Won't delete.\n"));
1635 /* Re-store parent key */
1636 parent_nk->num_subkeys--;
1637 hbin_store_tdr_resize(private_data->hive,
1638 (tdr_push_fn_t) tdr_push_nk_block,
1639 private_data->offset, parent_nk);
1641 if (key->nk->clsname_offset != -1) {
1642 hbin_free(private_data->hive, key->nk->clsname_offset);
1644 hbin_free(private_data->hive, key->offset);
1646 return regf_save_hbin(private_data->hive);
1649 static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent,
1650 const char *name, const char *classname,
1651 struct security_descriptor *sec_desc,
1652 struct hive_key **ret)
1654 const struct regf_key_data *private_data =
1655 (const struct regf_key_data *)parent;
1656 struct nk_block *parent_nk = private_data->nk, nk;
1657 struct nk_block *root;
1658 struct regf_data *regf = private_data->hive;
1663 nk.type = REG_SUB_KEY;
1664 unix_to_nt_time(&nk.last_change, time(NULL));
1666 nk.parent_offset = private_data->offset;
1669 nk.subkeys_offset = -1;
1670 nk.unknown_offset = -1;
1672 nk.values_offset = -1;
1673 memset(nk.unk3, 0, 5);
1674 nk.clsname_offset = -1; /* FIXME: fill in */
1675 nk.clsname_length = 0;
1678 /* Get the security descriptor of the root key */
1679 root = talloc_zero(ctx, struct nk_block);
1680 W_ERROR_HAVE_NO_MEMORY(root);
1682 if (!hbin_get_tdr(regf, regf->header->data_offset, root,
1683 (tdr_pull_fn_t)tdr_pull_nk_block, root)) {
1684 DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
1685 return WERR_GENERAL_FAILURE;
1687 nk.sk_offset = root->sk_offset;
1690 /* Store the new nk key */
1691 offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk);
1693 error = regf_sl_add_entry(regf, parent_nk->subkeys_offset, name, offset,
1694 &parent_nk->subkeys_offset);
1695 if (!W_ERROR_IS_OK(error)) {
1696 hbin_free(regf, offset);
1700 parent_nk->num_subkeys++;
1702 /* Since the subkey offset of the parent can change, store it again */
1703 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
1704 nk.parent_offset, parent_nk);
1706 *ret = (struct hive_key *)regf_get_key(ctx, regf, offset);
1708 return regf_save_hbin(private_data->hive);
1711 static WERROR regf_set_value(struct hive_key *key, const char *name,
1712 uint32_t type, const DATA_BLOB data)
1714 struct regf_key_data *private_data = (struct regf_key_data *)key;
1715 struct regf_data *regf = private_data->hive;
1716 struct nk_block *nk = private_data->nk;
1719 uint32_t tmp_vk_offset, vk_offset, old_vk_offset = -1;
1724 /* find the value offset, if it exists */
1725 if (nk->values_offset != -1) {
1726 values = hbin_get(regf, nk->values_offset);
1728 for (i = 0; i < nk->num_values; i++) {
1729 tmp_vk_offset = IVAL(values.data, i * 4);
1730 if (!hbin_get_tdr(regf, tmp_vk_offset, private_data,
1731 (tdr_pull_fn_t)tdr_pull_vk_block,
1733 DEBUG(0, ("Unable to get VK block at %d\n",
1735 return WERR_GENERAL_FAILURE;
1737 if (strcmp(vk.data_name, name) == 0) {
1738 old_vk_offset = tmp_vk_offset;
1742 /* Free data, if any */
1743 if (!(vk.data_length & 0x80000000)) {
1744 hbin_free(regf, vk.data_offset);
1747 if (old_vk_offset == -1) {
1749 vk.name_length = strlen(name);
1750 if (name != NULL && name[0] != 0) {
1752 vk.data_name = name;
1754 vk.data_name = NULL;
1758 /* Set the type and data */
1759 vk.data_length = data.length;
1760 vk.data_type = type;
1761 if (type == REG_DWORD) {
1762 vk.data_length |= 0x80000000;
1763 vk.data_offset = *(uint32_t *)data.data;
1765 /* Store data somewhere */
1766 vk.data_offset = hbin_store(regf, data);
1768 if (old_vk_offset == -1) {
1770 vk_offset = hbin_store_tdr(regf,
1771 (tdr_push_fn_t) tdr_push_vk_block,
1774 /* Store vk at offset */
1775 vk_offset = hbin_store_tdr_resize(regf,
1776 (tdr_push_fn_t) tdr_push_vk_block,
1777 old_vk_offset ,&vk);
1780 /* Re-allocate the value list */
1781 if (nk->values_offset == -1) {
1782 nk->values_offset = hbin_store_tdr(regf,
1783 (tdr_push_fn_t) tdr_push_uint32,
1788 /* Change if we're changing, otherwise we're adding the value */
1789 if (old_vk_offset != -1) {
1790 /* Find and overwrite the offset. */
1791 for (i = 0; i < nk->num_values; i++) {
1792 if (IVAL(values.data, i * 4) == old_vk_offset) {
1793 SIVAL(values.data, i * 4, vk_offset);
1798 /* Create a new value list */
1799 DATA_BLOB value_list;
1801 value_list.length = (nk->num_values+1)*4;
1802 value_list.data = (uint8_t *)talloc_array(private_data,
1805 W_ERROR_HAVE_NO_MEMORY(value_list.data);
1806 memcpy(value_list.data, values.data, nk->num_values * 4);
1808 SIVAL(value_list.data, nk->num_values * 4, vk_offset);
1810 nk->values_offset = hbin_store_resize(regf,
1816 hbin_store_tdr_resize(regf,
1817 (tdr_push_fn_t) tdr_push_nk_block,
1818 private_data->offset, nk);
1819 return regf_save_hbin(private_data->hive);
1822 static WERROR regf_save_hbin(struct regf_data *regf)
1824 struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience);
1827 W_ERROR_HAVE_NO_MEMORY(push);
1829 if (lseek(regf->fd, 0, SEEK_SET) == -1) {
1830 DEBUG(0, ("Error lseeking in regf file\n"));
1831 return WERR_GENERAL_FAILURE;
1834 /* Recompute checksum */
1835 if (NT_STATUS_IS_ERR(tdr_push_regf_hdr(push, regf->header))) {
1836 DEBUG(0, ("Failed to push regf header\n"));
1837 return WERR_GENERAL_FAILURE;
1839 regf->header->chksum = regf_hdr_checksum(push->data.data);
1842 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience,
1843 (tdr_push_fn_t)tdr_push_regf_hdr,
1845 DEBUG(0, ("Error writing registry file header\n"));
1846 return WERR_GENERAL_FAILURE;
1849 if (lseek(regf->fd, 0x1000, SEEK_SET) == -1) {
1850 DEBUG(0, ("Error lseeking to 0x1000 in regf file\n"));
1851 return WERR_GENERAL_FAILURE;
1854 for (i = 0; regf->hbins[i]; i++) {
1855 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience,
1856 (tdr_push_fn_t)tdr_push_hbin_block,
1858 DEBUG(0, ("Error writing HBIN block\n"));
1859 return WERR_GENERAL_FAILURE;
1866 WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx,
1867 struct smb_iconv_convenience *iconv_convenience,
1868 const char *location,
1869 int minor_version, struct hive_key **key)
1871 struct regf_data *regf;
1872 struct regf_hdr *regf_hdr;
1877 regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
1879 regf->iconv_convenience = iconv_convenience;
1881 W_ERROR_HAVE_NO_MEMORY(regf);
1883 DEBUG(5, ("Attempting to create registry file\n"));
1885 /* Get the header */
1886 regf->fd = creat(location, 0644);
1888 if (regf->fd == -1) {
1889 DEBUG(0,("Could not create file: %s, %s\n", location,
1892 return WERR_GENERAL_FAILURE;
1895 regf_hdr = talloc_zero(regf, struct regf_hdr);
1896 W_ERROR_HAVE_NO_MEMORY(regf_hdr);
1897 regf_hdr->REGF_ID = "regf";
1898 unix_to_nt_time(®f_hdr->modtime, time(NULL));
1899 regf_hdr->version.major = 1;
1900 regf_hdr->version.minor = minor_version;
1901 regf_hdr->last_block = 0x1000; /* Block size */
1902 regf_hdr->description = talloc_strdup(regf_hdr,
1903 "registry created by Samba 4");
1904 W_ERROR_HAVE_NO_MEMORY(regf_hdr->description);
1905 regf_hdr->chksum = 0;
1907 regf->header = regf_hdr;
1910 /* Create all hbin blocks */
1911 regf->hbins = talloc_array(regf, struct hbin_block *, 1);
1912 W_ERROR_HAVE_NO_MEMORY(regf->hbins);
1913 regf->hbins[0] = NULL;
1915 regf_hdr->data_offset = -1; /* FIXME */
1918 nk.type = REG_SUB_KEY;
1919 unix_to_nt_time(&nk.last_change, time(NULL));
1921 nk.parent_offset = -1;
1924 nk.subkeys_offset = -1;
1925 nk.unknown_offset = -1;
1927 nk.values_offset = -1;
1928 memset(nk.unk3, 0, 5);
1929 nk.clsname_offset = -1; /* FIXME: fill in */
1930 nk.clsname_length = 0;
1933 nk.sk_offset = -1; /* FIXME: fill in */
1935 /* Store the new nk key */
1936 regf->header->data_offset = hbin_store_tdr(regf,
1937 (tdr_push_fn_t)tdr_push_nk_block,
1940 *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
1941 regf->header->data_offset);
1943 /* We can drop our own reference now that *key will have created one */
1946 error = regf_save_hbin(regf);
1947 if (!W_ERROR_IS_OK(error)) {
1954 WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location,
1955 struct smb_iconv_convenience *iconv_convenience, struct hive_key **key)
1957 struct regf_data *regf;
1958 struct regf_hdr *regf_hdr;
1959 struct tdr_pull *pull;
1962 regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
1964 regf->iconv_convenience = iconv_convenience;
1966 W_ERROR_HAVE_NO_MEMORY(regf);
1968 DEBUG(5, ("Attempting to load registry file\n"));
1970 /* Get the header */
1971 regf->fd = open(location, O_RDWR);
1973 if (regf->fd == -1) {
1974 DEBUG(0,("Could not load file: %s, %s\n", location,
1977 return WERR_GENERAL_FAILURE;
1980 pull = tdr_pull_init(regf, regf->iconv_convenience);
1982 pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, regf);
1984 if (pull->data.data == NULL) {
1985 DEBUG(0, ("Error reading data\n"));
1987 return WERR_GENERAL_FAILURE;
1990 regf_hdr = talloc(regf, struct regf_hdr);
1991 W_ERROR_HAVE_NO_MEMORY(regf_hdr);
1993 if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr, regf_hdr))) {
1995 return WERR_GENERAL_FAILURE;
1998 regf->header = regf_hdr;
2000 if (strcmp(regf_hdr->REGF_ID, "regf") != 0) {
2001 DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n",
2002 regf_hdr->REGF_ID, location));
2004 return WERR_GENERAL_FAILURE;
2007 /* Validate the header ... */
2008 if (regf_hdr_checksum(pull->data.data) != regf_hdr->chksum) {
2009 DEBUG(0, ("Registry file checksum error: %s: %d,%d\n",
2010 location, regf_hdr->chksum,
2011 regf_hdr_checksum(pull->data.data)));
2013 return WERR_GENERAL_FAILURE;
2016 pull->offset = 0x1000;
2019 /* Read in all hbin blocks */
2020 regf->hbins = talloc_array(regf, struct hbin_block *, 1);
2021 W_ERROR_HAVE_NO_MEMORY(regf->hbins);
2023 regf->hbins[0] = NULL;
2025 while (pull->offset < pull->data.length &&
2026 pull->offset <= regf->header->last_block) {
2027 struct hbin_block *hbin = talloc(regf->hbins,
2030 W_ERROR_HAVE_NO_MEMORY(hbin);
2032 if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(pull, hbin, hbin))) {
2033 DEBUG(0, ("[%d] Error parsing HBIN block\n", i));
2038 if (strcmp(hbin->HBIN_ID, "hbin") != 0) {
2039 DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n",
2045 regf->hbins[i] = hbin;
2047 regf->hbins = talloc_realloc(regf, regf->hbins,
2048 struct hbin_block *, i+2);
2049 regf->hbins[i] = NULL;
2054 DEBUG(1, ("%d HBIN blocks read\n", i));
2056 *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
2057 regf->header->data_offset);
2059 /* We can drop our own reference now that *key will have created one */
2065 static struct hive_operations reg_backend_regf = {
2067 .get_key_info = regf_get_info,
2068 .enum_key = regf_get_subkey_by_index,
2069 .get_key_by_name = regf_get_subkey_by_name,
2070 .get_value_by_name = regf_get_value_by_name,
2071 .enum_value = regf_get_value,
2072 .get_sec_desc = regf_get_sec_desc,
2073 .set_sec_desc = regf_set_sec_desc,
2074 .add_key = regf_add_key,
2075 .set_value = regf_set_value,
2076 .del_key = regf_del_key,
2077 .delete_value = regf_del_value,