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"
28 static struct hive_operations reg_backend_regf;
31 * There are several places on the web where the REGF format is explained;
37 * - Return error codes that make more sense
39 * - do more things in-memory
43 * Read HBIN blocks into memory
48 struct hbin_block **hbins;
49 struct regf_hdr *header;
52 static WERROR regf_save_hbin(struct regf_data *data);
54 struct regf_key_data {
56 struct regf_data *hive;
61 static struct hbin_block *hbin_by_offset(const struct regf_data *data,
62 uint32_t offset, uint32_t *rel_offset)
66 for (i = 0; data->hbins[i]; i++) {
67 if (offset >= data->hbins[i]->offset_from_first &&
68 offset < data->hbins[i]->offset_from_first+
69 data->hbins[i]->offset_to_next) {
70 if (rel_offset != NULL)
71 *rel_offset = offset - data->hbins[i]->offset_from_first - 0x20;
72 return data->hbins[i];
80 * Validate a regf header
81 * For now, do nothing, but we should check the checksum
83 static uint32_t regf_hdr_checksum(const uint8_t *buffer)
85 uint32_t checksum = 0, x;
88 for (i = 0; i < 0x01FB; i+= 4) {
97 * Obtain the contents of a HBIN block
99 static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset)
102 struct hbin_block *hbin;
108 hbin = hbin_by_offset(data, offset, &rel_offset);
111 DEBUG(1, ("Can't find HBIN containing 0x%04x\n", offset));
115 ret.length = IVAL(hbin->data, rel_offset);
116 if (!(ret.length & 0x80000000)) {
117 DEBUG(0, ("Trying to use dirty block at 0x%04x\n", offset));
121 /* remove high bit */
122 ret.length = (ret.length ^ 0xffffffff) + 1;
124 ret.length -= 4; /* 4 bytes for the length... */
125 ret.data = hbin->data +
126 (offset - hbin->offset_from_first - 0x20) + 4;
131 static bool hbin_get_tdr(struct regf_data *regf, uint32_t offset,
132 TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p)
134 struct tdr_pull pull;
138 pull.data = hbin_get(regf, offset);
139 if (!pull.data.data) {
140 DEBUG(1, ("Unable to get data at 0x%04x\n", offset));
144 if (NT_STATUS_IS_ERR(pull_fn(&pull, ctx, p))) {
145 DEBUG(1, ("Error parsing record at 0x%04x using tdr\n",
153 /* Allocate some new data */
154 static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size,
158 uint32_t rel_offset = -1; /* Relative offset ! */
159 struct hbin_block *hbin = NULL;
165 return data_blob(NULL, 0);
167 size += 4; /* Need to include int32 for the length */
169 /* Allocate as a multiple of 8 */
170 size = (size + 7) & ~7;
175 for (i = 0; (hbin = data->hbins[i]); i++) {
178 for (j = 0; j < hbin->offset_to_next-0x20; j+= my_size) {
179 my_size = IVALS(hbin->data, j);
181 if (my_size == 0x0) {
182 DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
186 if (my_size % 8 != 0) {
187 DEBUG(0, ("Encountered non-aligned block!\n"));
190 if (my_size < 0) { /* Used... */
192 } else if (my_size == size) { /* exact match */
194 DEBUG(4, ("Found free block of exact size %d in middle of HBIN\n",
197 } else if (my_size > size) { /* data will remain */
199 /* Split this block and mark the next block as free */
200 SIVAL(hbin->data, rel_offset+size, my_size-size);
201 DEBUG(4, ("Found free block of size %d (needing %d) in middle of HBIN\n",
207 if (rel_offset != -1)
211 /* No space available in previous hbins,
212 * allocate new one */
213 if (data->hbins[i] == NULL) {
214 DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n",
216 data->hbins = talloc_realloc(data, data->hbins,
217 struct hbin_block *, i+2);
218 hbin = talloc(data->hbins, struct hbin_block);
219 SMB_ASSERT(hbin != NULL);
221 data->hbins[i] = hbin;
222 data->hbins[i+1] = NULL;
224 hbin->HBIN_ID = talloc_strdup(hbin, "hbin");
225 hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next);
226 hbin->offset_to_next = 0x1000;
227 hbin->unknown[0] = 0;
228 hbin->unknown[0] = 0;
229 unix_to_nt_time(&hbin->last_change, time(NULL));
230 hbin->block_size = hbin->offset_to_next;
231 hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20);
234 SIVAL(hbin->data, size, hbin->block_size - size - 0x20);
237 /* Set size and mark as used */
238 SIVAL(hbin->data, rel_offset, -size);
240 ret.data = hbin->data + rel_offset + 0x4; /* Skip past length */
241 ret.length = size - 0x4;
243 uint32_t new_rel_offset;
244 *offset = hbin->offset_from_first + rel_offset + 0x20;
245 SMB_ASSERT(hbin_by_offset(data, *offset, &new_rel_offset) == hbin);
246 SMB_ASSERT(new_rel_offset == rel_offset);
252 /* Store a data blob. Return the offset at which it was stored */
253 static uint32_t hbin_store (struct regf_data *data, DATA_BLOB blob)
256 DATA_BLOB dest = hbin_alloc(data, blob.length, &ret);
258 memcpy(dest.data, blob.data, blob.length);
263 static uint32_t hbin_store_tdr(struct regf_data *data,
264 tdr_push_fn_t push_fn, void *p)
266 struct tdr_push *push = talloc_zero(data, struct tdr_push);
269 if (NT_STATUS_IS_ERR(push_fn(push, p))) {
270 DEBUG(0, ("Error during push\n"));
274 ret = hbin_store(data, push->data);
282 /* Free existing data */
283 static void hbin_free (struct regf_data *data, uint32_t offset)
288 struct hbin_block *hbin;
290 SMB_ASSERT (offset > 0);
292 hbin = hbin_by_offset(data, offset, &rel_offset);
297 /* Get original size */
298 size = IVALS(hbin->data, rel_offset);
301 DEBUG(1, ("Trying to free already freed block at 0x%04x\n",
308 /* If the next block is free, merge into big free block */
309 if (rel_offset + size < hbin->offset_to_next) {
310 next_size = IVALS(hbin->data, rel_offset+size);
316 /* Write block size */
317 SIVALS(hbin->data, rel_offset, size);
321 * Store a data blob data was already stored, but has changed in size
322 * Will try to save it at the current location if possible, otherwise
323 * does a free + store */
324 static uint32_t hbin_store_resize(struct regf_data *data,
325 uint32_t orig_offset, DATA_BLOB blob)
328 struct hbin_block *hbin = hbin_by_offset(data, orig_offset,
333 int32_t possible_size;
336 SMB_ASSERT(orig_offset > 0);
339 return hbin_store(data, blob);
341 /* Get original size */
342 orig_size = -IVALS(hbin->data, rel_offset);
344 needed_size = blob.length + 4; /* Add int32 containing length */
345 needed_size = (needed_size + 7) & ~7; /* Align */
347 /* Fits into current allocated block */
348 if (orig_size >= needed_size) {
349 memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length);
350 /* If the difference in size is greater than 0x4, split the block
351 * and free/merge it */
352 if (orig_size - needed_size > 0x4) {
353 SIVALS(hbin->data, rel_offset, -needed_size);
354 SIVALS(hbin->data, rel_offset + needed_size,
355 needed_size-orig_size);
356 hbin_free(data, orig_offset + needed_size);
361 possible_size = orig_size;
363 /* Check if it can be combined with the next few free records */
364 for (i = rel_offset; i < hbin->offset_to_next - 0x20; i += my_size) {
365 if (IVALS(hbin->data, i) < 0) /* Used */
368 my_size = IVALS(hbin->data, i);
370 if (my_size == 0x0) {
371 DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
374 possible_size += my_size;
377 if (possible_size >= blob.length) {
378 SIVAL(hbin->data, rel_offset, -possible_size);
379 memcpy(hbin->data + rel_offset + 0x4,
380 blob.data, blob.length);
385 hbin_free(data, orig_offset);
386 return hbin_store(data, blob);
389 static uint32_t hbin_store_tdr_resize(struct regf_data *regf,
390 tdr_push_fn_t push_fn,
391 uint32_t orig_offset, void *p)
393 struct tdr_push *push = talloc_zero(regf, struct tdr_push);
396 if (NT_STATUS_IS_ERR(push_fn(push, p))) {
397 DEBUG(0, ("Error during push\n"));
401 ret = hbin_store_resize(regf, orig_offset, push->data);
408 static uint32_t regf_create_lh_hash(const char *name)
414 hash_name = strupper_talloc(NULL, name);
415 for (i = 0; *(hash_name + i) != 0; i++) {
417 ret += *(hash_name + i);
419 talloc_free(hash_name);
423 static WERROR regf_get_info(TALLOC_CTX *mem_ctx,
424 const struct hive_key *key,
425 const char **classname,
426 uint32_t *num_subkeys,
427 uint32_t *num_values,
428 NTTIME *last_mod_time)
430 const struct regf_key_data *private_data =
431 (const struct regf_key_data *)key;
433 if (num_subkeys != NULL)
434 *num_subkeys = private_data->nk->num_subkeys;
436 if (num_values != NULL)
437 *num_values = private_data->nk->num_values;
439 if (classname != NULL) {
440 if (private_data->nk->clsname_offset != -1) {
441 DATA_BLOB data = hbin_get(private_data->hive,
442 private_data->nk->clsname_offset);
443 *classname = talloc_strndup(mem_ctx,
445 private_data->nk->clsname_length);
450 /* TODO: Last mod time */
455 static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx,
456 struct regf_data *regf,
460 struct regf_key_data *ret;
462 ret = talloc_zero(ctx, struct regf_key_data);
463 ret->key.ops = ®_backend_regf;
464 ret->hive = talloc_reference(ret, regf);
465 ret->offset = offset;
466 nk = talloc(ret, struct nk_block);
472 if (!hbin_get_tdr(regf, offset, nk,
473 (tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
474 DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
478 if (strcmp(nk->header, "nk") != 0) {
479 DEBUG(0, ("Expected nk record, got %s\n", nk->header));
488 static WERROR regf_get_value(TALLOC_CTX *ctx, const struct hive_key *key,
489 int idx, const char **name,
490 uint32_t *data_type, DATA_BLOB *data)
492 const struct regf_key_data *private_data =
493 (const struct regf_key_data *)key;
495 struct regf_data *regf = private_data->hive;
499 if (idx >= private_data->nk->num_values)
500 return WERR_NO_MORE_ITEMS;
502 tmp = hbin_get(regf, private_data->nk->values_offset);
504 DEBUG(0, ("Unable to find value list\n"));
505 return WERR_GENERAL_FAILURE;
508 if (tmp.length < private_data->nk->num_values * 4) {
509 DEBUG(1, ("Value counts mismatch\n"));
512 vk_offset = IVAL(tmp.data, idx * 4);
514 vk = talloc(NULL, struct vk_block);
515 W_ERROR_HAVE_NO_MEMORY(vk);
517 if (!hbin_get_tdr(regf, vk_offset, vk,
518 (tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
519 DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));
521 return WERR_GENERAL_FAILURE;
524 /* FIXME: name character set ?*/
526 *name = talloc_strndup(ctx, vk->data_name, vk->name_length);
528 if (data_type != NULL)
529 *data_type = vk->data_type;
531 if (vk->data_length & 0x80000000) {
532 vk->data_length &=~0x80000000;
533 data->data = (uint8_t *)&vk->data_offset;
534 data->length = vk->data_length;
536 *data = hbin_get(regf, vk->data_offset);
539 if (data->length < vk->data_length) {
540 DEBUG(1, ("Read data less than indicated data length!\n"));
548 static WERROR regf_get_value_by_name(TALLOC_CTX *mem_ctx,
549 struct hive_key *key, const char *name,
550 uint32_t *type, DATA_BLOB *data)
556 /* FIXME: Do binary search? Is this list sorted at all? */
558 for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i,
559 &vname, type, data));
561 if (!strcmp(vname, name))
565 if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
566 return WERR_NOT_FOUND;
572 static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx,
573 const struct hive_key *key,
574 uint32_t idx, const char **name,
575 const char **classname,
576 NTTIME *last_mod_time)
579 struct regf_key_data *ret;
580 const struct regf_key_data *private_data = (const struct regf_key_data *)key;
581 struct nk_block *nk = private_data->nk;
584 if (idx >= nk->num_subkeys)
585 return WERR_NO_MORE_ITEMS;
587 data = hbin_get(private_data->hive, nk->subkeys_offset);
589 DEBUG(0, ("Unable to find subkey list\n"));
590 return WERR_GENERAL_FAILURE;
593 if (!strncmp((char *)data.data, "li", 2)) {
595 struct tdr_pull pull;
597 DEBUG(10, ("Subkeys in LI list\n"));
601 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) {
602 DEBUG(0, ("Error parsing LI list\n"));
603 return WERR_GENERAL_FAILURE;
605 SMB_ASSERT(!strncmp(li.header, "li", 2));
607 if (li.key_count != nk->num_subkeys) {
608 DEBUG(0, ("Subkey counts don't match\n"));
609 return WERR_GENERAL_FAILURE;
611 key_off = li.nk_offset[idx];
613 } else if (!strncmp((char *)data.data, "lf", 2)) {
615 struct tdr_pull pull;
617 DEBUG(10, ("Subkeys in LF list\n"));
621 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) {
622 DEBUG(0, ("Error parsing LF list\n"));
623 return WERR_GENERAL_FAILURE;
625 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
627 if (lf.key_count != nk->num_subkeys) {
628 DEBUG(0, ("Subkey counts don't match\n"));
629 return WERR_GENERAL_FAILURE;
632 key_off = lf.hr[idx].nk_offset;
633 } else if (!strncmp((char *)data.data, "lh", 2)) {
635 struct tdr_pull pull;
637 DEBUG(10, ("Subkeys in LH list\n"));
641 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) {
642 DEBUG(0, ("Error parsing LH list\n"));
643 return WERR_GENERAL_FAILURE;
645 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
647 if (lh.key_count != nk->num_subkeys) {
648 DEBUG(0, ("Subkey counts don't match\n"));
649 return WERR_GENERAL_FAILURE;
651 key_off = lh.hr[idx].nk_offset;
652 } else if (!strncmp((char *)data.data, "ri", 2)) {
654 struct tdr_pull pull;
656 uint16_t sublist_count = 0;
658 DEBUG(10, ("Subkeys in RI list\n"));
662 if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) {
663 DEBUG(0, ("Error parsing RI list\n"));
664 return WERR_GENERAL_FAILURE;
666 SMB_ASSERT(!strncmp(ri.header, "ri", 2));
668 for (i = 0; i < ri.key_count; i++) {
671 /* Get sublist data blob */
672 list_data = hbin_get(private_data->hive, ri.offset[i]);
673 if (!list_data.data) {
674 DEBUG(0, ("Error getting RI list."));
675 return WERR_GENERAL_FAILURE;
679 pull.data = list_data;
681 if (!strncmp((char *)list_data.data, "li", 2)) {
684 DEBUG(10, ("Subkeys in RI->LI list\n"));
686 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull,
689 DEBUG(0, ("Error parsing LI list from RI\n"));
690 return WERR_GENERAL_FAILURE;
692 SMB_ASSERT(!strncmp(li.header, "li", 2));
694 /* Advance to next sublist if necessary */
695 if (idx >= sublist_count + li.key_count) {
696 sublist_count += li.key_count;
699 key_off = li.nk_offset[idx - sublist_count];
700 sublist_count += li.key_count;
702 } else if (!strncmp((char *)list_data.data, "lh", 2)) {
705 DEBUG(10, ("Subkeys in RI->LH list\n"));
707 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull,
710 DEBUG(0, ("Error parsing LH list from RI\n"));
711 return WERR_GENERAL_FAILURE;
713 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
715 /* Advance to next sublist if necessary */
716 if (idx >= sublist_count + lh.key_count) {
717 sublist_count += lh.key_count;
720 key_off = lh.hr[idx - sublist_count].nk_offset;
721 sublist_count += lh.key_count;
724 DEBUG(0,("Unknown sublist in ri block\n"));
726 return WERR_GENERAL_FAILURE;
731 if (idx > sublist_count) {
732 return WERR_NO_MORE_ITEMS;
736 DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n",
737 nk->subkeys_offset, data.data[0], data.data[1]));
738 return WERR_GENERAL_FAILURE;
741 ret = regf_get_key (ctx, private_data->hive, key_off);
743 if (classname != NULL) {
744 if (ret->nk->clsname_offset != -1) {
745 DATA_BLOB db = hbin_get(ret->hive,
746 ret->nk->clsname_offset);
747 *classname = talloc_strndup(ctx,
749 ret->nk->clsname_length);
754 if (last_mod_time != NULL)
755 *last_mod_time = ret->nk->last_change;
758 *name = talloc_steal(ctx, ret->nk->key_name);
765 static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx,
766 const struct hive_key *key,
768 const char *name, uint32_t *ret)
770 DATA_BLOB subkey_data;
771 struct nk_block subkey;
772 struct tdr_pull pull;
773 const struct regf_key_data *private_data =
774 (const struct regf_key_data *)key;
776 subkey_data = hbin_get(private_data->hive, offset);
777 if (!subkey_data.data) {
778 DEBUG(0, ("Unable to retrieve subkey HBIN\n"));
779 return WERR_GENERAL_FAILURE;
783 pull.data = subkey_data;
785 if (NT_STATUS_IS_ERR(tdr_pull_nk_block(&pull, ctx, &subkey))) {
786 DEBUG(0, ("Error parsing NK structure.\n"));
787 return WERR_GENERAL_FAILURE;
790 if (strncmp(subkey.header, "nk", 2)) {
791 DEBUG(0, ("Not an NK structure.\n"));
792 return WERR_GENERAL_FAILURE;
795 if (!strcasecmp(subkey.key_name, name)) {
803 static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx,
804 const struct hive_key *key,
806 struct hive_key **ret)
809 const struct regf_key_data *private_data =
810 (const struct regf_key_data *)key;
811 struct nk_block *nk = private_data->nk;
812 uint32_t key_off = 0;
814 data = hbin_get(private_data->hive, nk->subkeys_offset);
816 DEBUG(0, ("Unable to find subkey list\n"));
817 return WERR_GENERAL_FAILURE;
820 if (!strncmp((char *)data.data, "li", 2)) {
822 struct tdr_pull pull;
825 DEBUG(10, ("Subkeys in LI list\n"));
829 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, nk, &li))) {
830 DEBUG(0, ("Error parsing LI list\n"));
831 return WERR_GENERAL_FAILURE;
833 SMB_ASSERT(!strncmp(li.header, "li", 2));
835 if (li.key_count != nk->num_subkeys) {
836 DEBUG(0, ("Subkey counts don't match\n"));
837 return WERR_GENERAL_FAILURE;
840 for (i = 0; i < li.key_count; i++) {
841 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
849 return WERR_NOT_FOUND;
850 } else if (!strncmp((char *)data.data, "lf", 2)) {
852 struct tdr_pull pull;
855 DEBUG(10, ("Subkeys in LF list\n"));
859 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, nk, &lf))) {
860 DEBUG(0, ("Error parsing LF list\n"));
861 return WERR_GENERAL_FAILURE;
863 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
865 if (lf.key_count != nk->num_subkeys) {
866 DEBUG(0, ("Subkey counts don't match\n"));
867 return WERR_GENERAL_FAILURE;
870 for (i = 0; i < lf.key_count; i++) {
871 if (strncmp(lf.hr[i].hash, name, 4)) {
874 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
883 return WERR_NOT_FOUND;
884 } else if (!strncmp((char *)data.data, "lh", 2)) {
886 struct tdr_pull pull;
890 DEBUG(10, ("Subkeys in LH list\n"));
894 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, nk, &lh))) {
895 DEBUG(0, ("Error parsing LH list\n"));
896 return WERR_GENERAL_FAILURE;
898 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
900 if (lh.key_count != nk->num_subkeys) {
901 DEBUG(0, ("Subkey counts don't match\n"));
902 return WERR_GENERAL_FAILURE;
905 hash = regf_create_lh_hash(name);
906 for (i = 0; i < lh.key_count; i++) {
907 if (lh.hr[i].base37 != hash) {
910 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
919 return WERR_NOT_FOUND;
920 } else if (!strncmp((char *)data.data, "ri", 2)) {
922 struct tdr_pull pull;
925 DEBUG(10, ("Subkeys in RI list\n"));
929 if (NT_STATUS_IS_ERR(tdr_pull_ri_block(&pull, nk, &ri))) {
930 DEBUG(0, ("Error parsing RI list\n"));
931 return WERR_GENERAL_FAILURE;
933 SMB_ASSERT(!strncmp(ri.header, "ri", 2));
935 for (i = 0; i < ri.key_count; i++) {
938 /* Get sublist data blob */
939 list_data = hbin_get(private_data->hive, ri.offset[i]);
940 if (list_data.data == NULL) {
941 DEBUG(0, ("Error getting RI list."));
942 return WERR_GENERAL_FAILURE;
946 pull.data = list_data;
948 if (!strncmp((char *)list_data.data, "li", 2)) {
951 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull,
954 DEBUG(0, ("Error parsing LI list from RI\n"));
955 return WERR_GENERAL_FAILURE;
957 SMB_ASSERT(!strncmp(li.header, "li", 2));
959 for (j = 0; j < li.key_count; j++) {
960 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
967 } else if (!strncmp((char *)list_data.data, "lh", 2)) {
971 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull,
974 DEBUG(0, ("Error parsing LH list from RI\n"));
975 return WERR_GENERAL_FAILURE;
977 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
979 hash = regf_create_lh_hash(name);
980 for (j = 0; j < lh.key_count; j++) {
981 if (lh.hr[j].base37 != hash) {
984 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
996 return WERR_NOT_FOUND;
998 DEBUG(0, ("Unknown subkey list type.\n"));
999 return WERR_GENERAL_FAILURE;
1002 *ret = (struct hive_key *)regf_get_key(ctx, private_data->hive,
1007 static WERROR regf_set_sec_desc(struct hive_key *key,
1008 const struct security_descriptor *sec_desc)
1010 const struct regf_key_data *private_data =
1011 (const struct regf_key_data *)key;
1012 struct sk_block cur_sk, sk, new_sk;
1013 struct regf_data *regf = private_data->hive;
1014 struct nk_block root;
1016 uint32_t sk_offset, cur_sk_offset;
1017 bool update_cur_sk = false;
1019 /* Get the root nk */
1020 hbin_get_tdr(regf, regf->header->data_offset, regf,
1021 (tdr_pull_fn_t) tdr_pull_nk_block, &root);
1023 /* Push the security descriptor to a blob */
1024 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, sec_desc,
1025 (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
1026 DEBUG(0, ("Unable to push security descriptor\n"));
1027 return WERR_GENERAL_FAILURE;
1030 /* Get the current security descriptor for the key */
1031 if (!hbin_get_tdr(regf, private_data->nk->sk_offset, regf,
1032 (tdr_pull_fn_t) tdr_pull_sk_block, &cur_sk)) {
1033 DEBUG(0, ("Unable to find security descriptor for current key\n"));
1034 return WERR_BADFILE;
1036 /* If there's no change, change nothing. */
1037 if (memcmp(data.data, cur_sk.sec_desc,
1038 MIN(data.length, cur_sk.rec_size)) == 0) {
1042 /* Delete the current sk if only this key is using it */
1043 if (cur_sk.ref_cnt == 1) {
1044 /* Get the previous security descriptor for the key */
1045 if (!hbin_get_tdr(regf, cur_sk.prev_offset, regf,
1046 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1047 DEBUG(0, ("Unable to find prev security descriptor for current key\n"));
1048 return WERR_BADFILE;
1050 /* Change and store the previous security descriptor */
1051 sk.next_offset = cur_sk.next_offset;
1052 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block,
1053 cur_sk.prev_offset, &sk);
1055 /* Get the next security descriptor for the key */
1056 if (!hbin_get_tdr(regf, cur_sk.next_offset, regf,
1057 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1058 DEBUG(0, ("Unable to find next security descriptor for current key\n"));
1059 return WERR_BADFILE;
1061 /* Change and store the next security descriptor */
1062 sk.prev_offset = cur_sk.prev_offset;
1063 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block,
1064 cur_sk.next_offset, &sk);
1066 hbin_free(regf, private_data->nk->sk_offset);
1068 /* This key will no longer be referring to this sk */
1070 update_cur_sk = true;
1073 sk_offset = root.sk_offset;
1076 cur_sk_offset = sk_offset;
1077 if (!hbin_get_tdr(regf, sk_offset, regf,
1078 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1079 DEBUG(0, ("Unable to find security descriptor\n"));
1080 return WERR_BADFILE;
1082 if (memcmp(data.data, sk.sec_desc, MIN(data.length, sk.rec_size)) == 0) {
1083 private_data->nk->sk_offset = sk_offset;
1085 hbin_store_tdr_resize(regf,
1086 (tdr_push_fn_t) tdr_push_sk_block,
1088 hbin_store_tdr_resize(regf,
1089 (tdr_push_fn_t) tdr_push_nk_block,
1090 private_data->offset,
1094 sk_offset = sk.next_offset;
1095 } while (sk_offset != root.sk_offset);
1097 ZERO_STRUCT(new_sk);
1098 new_sk.header = "sk";
1099 new_sk.prev_offset = cur_sk_offset;
1100 new_sk.next_offset = root.sk_offset;
1102 new_sk.rec_size = data.length;
1103 new_sk.sec_desc = data.data;
1105 sk_offset = hbin_store_tdr(regf,
1106 (tdr_push_fn_t) tdr_push_sk_block,
1108 if (sk_offset == -1) {
1109 DEBUG(0, ("Error storing sk block\n"));
1110 return WERR_GENERAL_FAILURE;
1112 private_data->nk->sk_offset = sk_offset;
1114 if (update_cur_sk) {
1115 hbin_store_tdr_resize(regf,
1116 (tdr_push_fn_t) tdr_push_sk_block,
1117 private_data->nk->sk_offset, &cur_sk);
1120 /* Get the previous security descriptor for the key */
1121 if (!hbin_get_tdr(regf, new_sk.prev_offset, regf,
1122 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1123 DEBUG(0, ("Unable to find security descriptor for previous key\n"));
1124 return WERR_BADFILE;
1126 /* Change and store the previous security descriptor */
1127 sk.next_offset = sk_offset;
1128 hbin_store_tdr_resize(regf,
1129 (tdr_push_fn_t) tdr_push_sk_block,
1130 cur_sk.prev_offset, &sk);
1132 /* Get the next security descriptor for the key (always root, as we append) */
1133 if (!hbin_get_tdr(regf, new_sk.next_offset, regf,
1134 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1135 DEBUG(0, ("Unable to find security descriptor for current key\n"));
1136 return WERR_BADFILE;
1138 /* Change and store the next security descriptor (always root, as we append) */
1139 sk.prev_offset = sk_offset;
1140 hbin_store_tdr_resize(regf,
1141 (tdr_push_fn_t) tdr_push_sk_block,
1142 root.sk_offset, &sk);
1146 hbin_store_tdr_resize(regf,
1147 (tdr_push_fn_t) tdr_push_sk_block,
1148 private_data->offset, private_data->nk);
1152 static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key,
1153 struct security_descriptor **sd)
1155 const struct regf_key_data *private_data =
1156 (const struct regf_key_data *)key;
1158 struct regf_data *regf = private_data->hive;
1161 if (!hbin_get_tdr(regf, private_data->nk->sk_offset, ctx,
1162 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1163 DEBUG(0, ("Unable to find security descriptor\n"));
1164 return WERR_GENERAL_FAILURE;
1167 if (strcmp(sk.header, "sk") != 0) {
1168 DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header));
1169 return WERR_GENERAL_FAILURE;
1172 *sd = talloc(ctx, struct security_descriptor);
1173 W_ERROR_HAVE_NO_MEMORY(*sd);
1175 data.data = sk.sec_desc;
1176 data.length = sk.rec_size;
1177 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, *sd,
1178 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) {
1179 DEBUG(0, ("Error parsing security descriptor\n"));
1180 return WERR_GENERAL_FAILURE;
1186 static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset,
1188 uint32_t key_offset, uint32_t *ret)
1192 /* Create a new key if necessary */
1193 if (list_offset == -1) {
1194 if (regf->header->version.major != 1) {
1195 DEBUG(0, ("Can't store keys in unknown registry format\n"));
1196 return WERR_NOT_SUPPORTED;
1198 if (regf->header->version.minor < 3) {
1205 li.nk_offset = talloc_array(regf, uint32_t, 1);
1206 W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1207 li.nk_offset[0] = key_offset;
1209 *ret = hbin_store_tdr(regf,
1210 (tdr_push_fn_t) tdr_push_li_block,
1213 talloc_free(li.nk_offset);
1214 } else if (regf->header->version.minor == 3 ||
1215 regf->header->version.minor == 4) {
1222 lf.hr = talloc_array(regf, struct hash_record, 1);
1223 W_ERROR_HAVE_NO_MEMORY(lf.hr);
1224 lf.hr[0].nk_offset = key_offset;
1225 lf.hr[0].hash = talloc_strndup(lf.hr, name, 4);
1226 W_ERROR_HAVE_NO_MEMORY(lf.hr[0].hash);
1228 *ret = hbin_store_tdr(regf,
1229 (tdr_push_fn_t) tdr_push_lf_block,
1233 } else if (regf->header->version.minor == 5) {
1240 lh.hr = talloc_array(regf, struct lh_hash, 1);
1241 W_ERROR_HAVE_NO_MEMORY(lh.hr);
1242 lh.hr[0].nk_offset = key_offset;
1243 lh.hr[0].base37 = regf_create_lh_hash(name);
1245 *ret = hbin_store_tdr(regf,
1246 (tdr_push_fn_t) tdr_push_lh_block,
1254 data = hbin_get(regf, list_offset);
1256 DEBUG(0, ("Unable to find subkey list\n"));
1257 return WERR_BADFILE;
1260 if (!strncmp((char *)data.data, "li", 2)) {
1261 struct tdr_pull pull;
1267 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, regf, &li))) {
1268 DEBUG(0, ("Error parsing LI list\n"));
1269 return WERR_BADFILE;
1272 if (strncmp(li.header, "li", 2) != 0) {
1274 DEBUG(0, ("LI header corrupt\n"));
1275 return WERR_BADFILE;
1278 li.nk_offset = talloc_realloc(regf, li.nk_offset,
1279 uint32_t, li.key_count+1);
1280 W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1281 li.nk_offset[li.key_count] = key_offset;
1283 *ret = hbin_store_tdr_resize(regf,
1284 (tdr_push_fn_t)tdr_push_li_block,
1287 talloc_free(li.nk_offset);
1288 } else if (!strncmp((char *)data.data, "lf", 2)) {
1289 struct tdr_pull pull;
1295 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, regf, &lf))) {
1296 DEBUG(0, ("Error parsing LF list\n"));
1297 return WERR_BADFILE;
1299 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1301 lf.hr = talloc_realloc(regf, lf.hr, struct hash_record,
1303 W_ERROR_HAVE_NO_MEMORY(lf.hr);
1304 lf.hr[lf.key_count].nk_offset = key_offset;
1305 lf.hr[lf.key_count].hash = talloc_strndup(lf.hr, name, 4);
1306 W_ERROR_HAVE_NO_MEMORY(lf.hr[lf.key_count].hash);
1308 *ret = hbin_store_tdr_resize(regf,
1309 (tdr_push_fn_t)tdr_push_lf_block,
1313 } else if (!strncmp((char *)data.data, "lh", 2)) {
1314 struct tdr_pull pull;
1320 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, regf, &lh))) {
1321 DEBUG(0, ("Error parsing LH list\n"));
1322 return WERR_BADFILE;
1324 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1326 lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash,
1328 W_ERROR_HAVE_NO_MEMORY(lh.hr);
1329 lh.hr[lh.key_count].nk_offset = key_offset;
1330 lh.hr[lh.key_count].base37 = regf_create_lh_hash(name);
1332 *ret = hbin_store_tdr_resize(regf,
1333 (tdr_push_fn_t)tdr_push_lh_block,
1337 } else if (!strncmp((char *)data.data, "ri", 2)) {
1339 DEBUG(0, ("Adding to 'ri' subkey list is not supported yet.\n"));
1340 return WERR_NOT_SUPPORTED;
1342 DEBUG(0, ("Cannot add to unknown subkey list\n"));
1343 return WERR_BADFILE;
1349 static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset,
1350 uint32_t key_offset, uint32_t *ret)
1354 data = hbin_get(regf, list_offset);
1356 DEBUG(0, ("Unable to find subkey list\n"));
1357 return WERR_BADFILE;
1360 if (strncmp((char *)data.data, "li", 2) == 0) {
1362 struct tdr_pull pull;
1364 bool found_offset = false;
1366 DEBUG(10, ("Subkeys in LI list\n"));
1371 if (NT_STATUS_IS_ERR(tdr_pull_li_block(&pull, regf, &li))) {
1372 DEBUG(0, ("Error parsing LI list\n"));
1373 return WERR_BADFILE;
1376 SMB_ASSERT(!strncmp(li.header, "li", 2));
1378 for (i = 0; i < li.key_count; i++) {
1380 li.nk_offset[i-1] = li.nk_offset[i];
1382 if (li.nk_offset[i] == key_offset) {
1383 found_offset = true;
1387 if (!found_offset) {
1388 DEBUG(2, ("Subkey not found\n"));
1389 return WERR_NOT_FOUND;
1393 /* If the there are no entries left, free the subkey list */
1394 if (li.key_count == 0) {
1395 hbin_free(regf, list_offset);
1399 /* Store li block */
1400 *ret = hbin_store_tdr_resize(regf,
1401 (tdr_push_fn_t) tdr_push_li_block,
1403 } else if (strncmp((char *)data.data, "lf", 2) == 0) {
1405 struct tdr_pull pull;
1407 bool found_offset = false;
1409 DEBUG(10, ("Subkeys in LF list\n"));
1414 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(&pull, regf, &lf))) {
1415 DEBUG(0, ("Error parsing LF list\n"));
1416 return WERR_BADFILE;
1419 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1421 for (i = 0; i < lf.key_count; i++) {
1423 lf.hr[i-1] = lf.hr[i];
1426 if (lf.hr[i].nk_offset == key_offset) {
1431 if (!found_offset) {
1432 DEBUG(2, ("Subkey not found\n"));
1433 return WERR_NOT_FOUND;
1437 /* If the there are no entries left, free the subkey list */
1438 if (lf.key_count == 0) {
1439 hbin_free(regf, list_offset);
1444 /* Store lf block */
1445 *ret = hbin_store_tdr_resize(regf,
1446 (tdr_push_fn_t) tdr_push_lf_block,
1448 } else if (strncmp((char *)data.data, "lh", 2) == 0) {
1450 struct tdr_pull pull;
1452 bool found_offset = false;
1454 DEBUG(10, ("Subkeys in LH list\n"));
1459 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(&pull, regf, &lh))) {
1460 DEBUG(0, ("Error parsing LF list\n"));
1461 return WERR_BADFILE;
1464 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1466 for (i = 0; i < lh.key_count; i++) {
1468 lh.hr[i-1] = lh.hr[i];
1471 if (lh.hr[i].nk_offset == key_offset) {
1476 if (!found_offset) {
1477 DEBUG(0, ("Subkey not found\n"));
1478 return WERR_NOT_FOUND;
1482 /* If the there are no entries left, free the subkey list */
1483 if (lh.key_count == 0) {
1484 hbin_free(regf, list_offset);
1489 /* Store lh block */
1490 *ret = hbin_store_tdr_resize(regf,
1491 (tdr_push_fn_t) tdr_push_lh_block,
1493 } else if (strncmp((char *)data.data, "ri", 2) == 0) {
1495 DEBUG(0, ("Sorry, deletion from ri block is not supported yet.\n"));
1496 return WERR_NOT_SUPPORTED;
1498 DEBUG (0, ("Unknown header found in subkey list.\n"));
1499 return WERR_BADFILE;
1504 static WERROR regf_del_value (struct hive_key *key, const char *name)
1506 const struct regf_key_data *private_data =
1507 (const struct regf_key_data *)key;
1508 struct regf_data *regf = private_data->hive;
1509 struct nk_block *nk = private_data->nk;
1512 bool found_offset = false;
1516 if (nk->values_offset == -1) {
1517 return WERR_NOT_FOUND;
1520 values = hbin_get(regf, nk->values_offset);
1522 for (i = 0; i < nk->num_values; i++) {
1524 ((uint32_t *)values.data)[i-1] = ((uint32_t *) values.data)[i];
1526 vk_offset = IVAL(values.data, i * 4);
1527 if (!hbin_get_tdr(regf, vk_offset, private_data,
1528 (tdr_pull_fn_t)tdr_pull_vk_block,
1530 DEBUG(0, ("Unable to get VK block at %d\n",
1532 return WERR_BADFILE;
1534 if (strcmp(vk.data_name, name) == 0) {
1535 hbin_free(regf, vk_offset);
1536 found_offset = true;
1540 if (!found_offset) {
1541 return WERR_NOT_FOUND;
1544 values.length = (nk->num_values)*4;
1547 /* Store values list and nk */
1548 if (nk->num_values == 0) {
1549 hbin_free(regf, nk->values_offset);
1550 nk->values_offset = -1;
1552 nk->values_offset = hbin_store_resize(regf,
1556 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
1557 private_data->offset, nk);
1559 return regf_save_hbin(private_data->hive);
1563 static WERROR regf_del_key(const struct hive_key *parent, const char *name)
1565 const struct regf_key_data *private_data =
1566 (const struct regf_key_data *)parent;
1567 struct regf_key_data *key;
1568 struct nk_block *parent_nk;
1571 SMB_ASSERT(private_data);
1573 parent_nk = private_data->nk;
1575 if (parent_nk->subkeys_offset == -1) {
1576 DEBUG(4, ("Subkey list is empty, this key cannot contain subkeys.\n"));
1577 return WERR_NOT_FOUND;
1581 if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name,
1582 (struct hive_key **)&key))) {
1583 DEBUG(2, ("Key '%s' not found\n", name));
1584 return WERR_NOT_FOUND;
1587 if (key->nk->subkeys_offset != -1 ||
1588 key->nk->values_offset != -1) {
1589 DEBUG(0, ("Key '%s' is not empty.\n", name));
1590 return WERR_FILE_EXISTS;
1593 /* Delete it from the subkey list. */
1594 error = regf_sl_del_entry(private_data->hive, parent_nk->subkeys_offset,
1595 key->offset, &parent_nk->subkeys_offset);
1596 if (!W_ERROR_IS_OK(error)) {
1597 DEBUG(0, ("Can't store new subkey list for parent key. Won't delete.\n"));
1601 /* Re-store parent key */
1602 parent_nk->num_subkeys--;
1603 hbin_store_tdr_resize(private_data->hive,
1604 (tdr_push_fn_t) tdr_push_nk_block,
1605 private_data->offset, parent_nk);
1607 if (key->nk->clsname_offset != -1) {
1608 hbin_free(private_data->hive, key->nk->clsname_offset);
1610 hbin_free(private_data->hive, key->offset);
1612 return regf_save_hbin(private_data->hive);
1615 static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent,
1616 const char *name, const char *classname,
1617 struct security_descriptor *sec_desc,
1618 struct hive_key **ret)
1620 const struct regf_key_data *private_data =
1621 (const struct regf_key_data *)parent;
1622 struct nk_block *parent_nk = private_data->nk, nk;
1623 struct nk_block *root;
1624 struct regf_data *regf = private_data->hive;
1629 nk.type = REG_SUB_KEY;
1630 unix_to_nt_time(&nk.last_change, time(NULL));
1632 nk.parent_offset = private_data->offset;
1635 nk.subkeys_offset = -1;
1636 nk.unknown_offset = -1;
1638 nk.values_offset = -1;
1639 memset(nk.unk3, 0, 5);
1640 nk.clsname_offset = -1; /* FIXME: fill in */
1641 nk.clsname_length = 0;
1644 /* Get the security descriptor of the root key */
1645 root = talloc_zero(ctx, struct nk_block);
1646 W_ERROR_HAVE_NO_MEMORY(root);
1648 if (!hbin_get_tdr(regf, regf->header->data_offset, root,
1649 (tdr_pull_fn_t)tdr_pull_nk_block, root)) {
1650 DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
1651 return WERR_GENERAL_FAILURE;
1653 nk.sk_offset = root->sk_offset;
1656 /* Store the new nk key */
1657 offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk);
1659 error = regf_sl_add_entry(regf, parent_nk->subkeys_offset, name, offset,
1660 &parent_nk->subkeys_offset);
1661 if (!W_ERROR_IS_OK(error)) {
1662 hbin_free(regf, offset);
1666 parent_nk->num_subkeys++;
1668 /* Since the subkey offset of the parent can change, store it again */
1669 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
1670 nk.parent_offset, parent_nk);
1672 *ret = (struct hive_key *)regf_get_key(ctx, regf, offset);
1674 return regf_save_hbin(private_data->hive);
1677 static WERROR regf_set_value(struct hive_key *key, const char *name,
1678 uint32_t type, const DATA_BLOB data)
1680 const struct regf_key_data *private_data =
1681 (const struct regf_key_data *)key;
1682 struct regf_data *regf = private_data->hive;
1683 struct nk_block *nk = private_data->nk;
1686 uint32_t tmp_vk_offset, vk_offset, old_vk_offset = -1;
1691 /* find the value offset, if it exists */
1692 if (nk->values_offset != -1) {
1693 values = hbin_get(regf, nk->values_offset);
1695 for (i = 0; i < nk->num_values; i++) {
1696 tmp_vk_offset = IVAL(values.data, i * 4);
1697 if (!hbin_get_tdr(regf, tmp_vk_offset, private_data,
1698 (tdr_pull_fn_t)tdr_pull_vk_block,
1700 DEBUG(0, ("Unable to get VK block at %d\n",
1702 return WERR_GENERAL_FAILURE;
1704 if (strcmp(vk.data_name, name) == 0) {
1705 old_vk_offset = tmp_vk_offset;
1709 /* Free data, if any */
1710 if (!(vk.data_length & 0x80000000)) {
1711 hbin_free(regf, vk.data_offset);
1714 if (old_vk_offset == -1) {
1716 vk.name_length = strlen(name);
1717 if (name != NULL && name[0] != 0) {
1719 vk.data_name = name;
1721 vk.data_name = NULL;
1725 /* Set the type and data */
1726 vk.data_length = data.length;
1727 vk.data_type = type;
1728 if (type == REG_DWORD) {
1729 vk.data_length |= 0x80000000;
1730 vk.data_offset = *(uint32_t *)data.data;
1732 /* Store data somewhere */
1733 vk.data_offset = hbin_store(regf, data);
1735 if (old_vk_offset == -1) {
1737 vk_offset = hbin_store_tdr(regf,
1738 (tdr_push_fn_t) tdr_push_vk_block,
1741 /* Store vk at offset */
1742 vk_offset = hbin_store_tdr_resize(regf,
1743 (tdr_push_fn_t) tdr_push_vk_block,
1744 old_vk_offset ,&vk);
1747 /* Re-allocate the value list */
1748 if (nk->values_offset == -1) {
1749 nk->values_offset = hbin_store_tdr(regf,
1750 (tdr_push_fn_t) tdr_push_uint32,
1755 /* Change if we're changing, otherwise we're adding the value */
1756 if (old_vk_offset != -1) {
1757 /* Find and overwrite the offset. */
1758 for (i = 0; i < nk->num_values; i++) {
1759 if (IVAL(values.data, i * 4) == old_vk_offset) {
1760 SIVAL(values.data, i * 4, vk_offset);
1765 /* Create a new value list */
1766 DATA_BLOB value_list;
1768 value_list.length = (nk->num_values+1)*4;
1769 value_list.data = (uint8_t *)talloc_array(private_data,
1772 W_ERROR_HAVE_NO_MEMORY(value_list.data);
1773 memcpy(value_list.data, values.data, nk->num_values * 4);
1775 SIVAL(value_list.data, nk->num_values * 4, vk_offset);
1777 nk->values_offset = hbin_store_resize(regf,
1783 hbin_store_tdr_resize(regf,
1784 (tdr_push_fn_t) tdr_push_nk_block,
1785 private_data->offset, nk);
1786 return regf_save_hbin(private_data->hive);
1789 static WERROR regf_save_hbin(struct regf_data *regf)
1791 struct tdr_push *push = talloc_zero(regf, struct tdr_push);
1794 W_ERROR_HAVE_NO_MEMORY(push);
1796 if (lseek(regf->fd, 0, SEEK_SET) == -1) {
1797 DEBUG(0, ("Error lseeking in regf file\n"));
1798 return WERR_GENERAL_FAILURE;
1801 /* Recompute checksum */
1802 if (NT_STATUS_IS_ERR(tdr_push_regf_hdr(push, regf->header))) {
1803 DEBUG(0, ("Failed to push regf header\n"));
1804 return WERR_GENERAL_FAILURE;
1806 regf->header->chksum = regf_hdr_checksum(push->data.data);
1809 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd,
1810 (tdr_push_fn_t)tdr_push_regf_hdr,
1812 DEBUG(0, ("Error writing registry file header\n"));
1813 return WERR_GENERAL_FAILURE;
1816 if (lseek(regf->fd, 0x1000, SEEK_SET) == -1) {
1817 DEBUG(0, ("Error lseeking to 0x1000 in regf file\n"));
1818 return WERR_GENERAL_FAILURE;
1821 for (i = 0; regf->hbins[i]; i++) {
1822 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd,
1823 (tdr_push_fn_t)tdr_push_hbin_block,
1825 DEBUG(0, ("Error writing HBIN block\n"));
1826 return WERR_GENERAL_FAILURE;
1833 WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx, const char *location,
1834 int minor_version, struct hive_key **key)
1836 struct regf_data *regf;
1837 struct regf_hdr *regf_hdr;
1838 struct tdr_pull pull;
1843 regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
1845 W_ERROR_HAVE_NO_MEMORY(regf);
1847 DEBUG(5, ("Attempting to create registry file\n"));
1849 /* Get the header */
1850 regf->fd = creat(location, 0644);
1852 if (regf->fd == -1) {
1853 DEBUG(0,("Could not create file: %s, %s\n", location,
1856 return WERR_GENERAL_FAILURE;
1859 regf_hdr = talloc_zero(regf, struct regf_hdr);
1860 W_ERROR_HAVE_NO_MEMORY(regf_hdr);
1861 regf_hdr->REGF_ID = "regf";
1862 unix_to_nt_time(®f_hdr->modtime, time(NULL));
1863 regf_hdr->version.major = 1;
1864 regf_hdr->version.minor = minor_version;
1865 regf_hdr->last_block = 0x1000; /* Block size */
1866 regf_hdr->description = talloc_strdup(regf_hdr,
1867 "registry created by Samba 4");
1868 W_ERROR_HAVE_NO_MEMORY(regf_hdr->description);
1869 regf_hdr->chksum = 0;
1871 regf->header = regf_hdr;
1873 pull.offset = 0x1000;
1876 /* Create all hbin blocks */
1877 regf->hbins = talloc_array(regf, struct hbin_block *, 1);
1878 W_ERROR_HAVE_NO_MEMORY(regf->hbins);
1879 regf->hbins[0] = NULL;
1881 regf_hdr->data_offset = -1; /* FIXME */
1884 nk.type = REG_SUB_KEY;
1885 unix_to_nt_time(&nk.last_change, time(NULL));
1887 nk.parent_offset = -1;
1890 nk.subkeys_offset = -1;
1891 nk.unknown_offset = -1;
1893 nk.values_offset = -1;
1894 memset(nk.unk3, 0, 5);
1895 nk.clsname_offset = -1; /* FIXME: fill in */
1896 nk.clsname_length = 0;
1899 nk.sk_offset = -1; /* FIXME: fill in */
1901 /* Store the new nk key */
1902 regf->header->data_offset = hbin_store_tdr(regf,
1903 (tdr_push_fn_t)tdr_push_nk_block,
1906 *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
1907 regf->header->data_offset);
1909 /* We can drop our own reference now that *key will have created one */
1912 error = regf_save_hbin(regf);
1913 if (!W_ERROR_IS_OK(error)) {
1920 WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx,
1921 const char *location, struct hive_key **key)
1923 struct regf_data *regf;
1924 struct regf_hdr *regf_hdr;
1925 struct tdr_pull pull;
1928 regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
1930 W_ERROR_HAVE_NO_MEMORY(regf);
1932 DEBUG(5, ("Attempting to load registry file\n"));
1934 /* Get the header */
1935 regf->fd = open(location, O_RDWR);
1937 if (regf->fd == -1) {
1938 DEBUG(0,("Could not load file: %s, %s\n", location,
1941 return WERR_GENERAL_FAILURE;
1945 pull.data.data = (uint8_t*)fd_load(regf->fd, &pull.data.length, regf);
1947 if (pull.data.data == NULL) {
1948 DEBUG(0, ("Error reading data\n"));
1950 return WERR_GENERAL_FAILURE;
1953 regf_hdr = talloc(regf, struct regf_hdr);
1954 W_ERROR_HAVE_NO_MEMORY(regf_hdr);
1956 if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(&pull, regf_hdr, regf_hdr))) {
1958 return WERR_GENERAL_FAILURE;
1961 regf->header = regf_hdr;
1963 if (strcmp(regf_hdr->REGF_ID, "regf") != 0) {
1964 DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n",
1965 regf_hdr->REGF_ID, location));
1967 return WERR_GENERAL_FAILURE;
1970 /* Validate the header ... */
1971 if (regf_hdr_checksum(pull.data.data) != regf_hdr->chksum) {
1972 DEBUG(0, ("Registry file checksum error: %s: %d,%d\n",
1973 location, regf_hdr->chksum,
1974 regf_hdr_checksum(pull.data.data)));
1976 return WERR_GENERAL_FAILURE;
1979 pull.offset = 0x1000;
1982 /* Read in all hbin blocks */
1983 regf->hbins = talloc_array(regf, struct hbin_block *, 1);
1984 W_ERROR_HAVE_NO_MEMORY(regf->hbins);
1986 regf->hbins[0] = NULL;
1988 while (pull.offset < pull.data.length &&
1989 pull.offset <= regf->header->last_block) {
1990 struct hbin_block *hbin = talloc(regf->hbins,
1993 W_ERROR_HAVE_NO_MEMORY(hbin);
1995 if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(&pull, hbin, hbin))) {
1996 DEBUG(0, ("[%d] Error parsing HBIN block\n", i));
2001 if (strcmp(hbin->HBIN_ID, "hbin") != 0) {
2002 DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n",
2008 regf->hbins[i] = hbin;
2010 regf->hbins = talloc_realloc(regf, regf->hbins,
2011 struct hbin_block *, i+2);
2012 regf->hbins[i] = NULL;
2015 DEBUG(1, ("%d HBIN blocks read\n", i));
2017 *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
2018 regf->header->data_offset);
2020 /* We can drop our own reference now that *key will have created one */
2026 static struct hive_operations reg_backend_regf = {
2028 .get_key_info = regf_get_info,
2029 .enum_key = regf_get_subkey_by_index,
2030 .get_key_by_name = regf_get_subkey_by_name,
2031 .get_value_by_name = regf_get_value_by_name,
2032 .enum_value = regf_get_value,
2033 .get_sec_desc = regf_get_sec_desc,
2034 .set_sec_desc = regf_set_sec_desc,
2035 .add_key = regf_add_key,
2036 .set_value = regf_set_value,
2037 .del_key = regf_del_key,
2038 .delete_value = regf_del_value,