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 "system/filesys.h"
22 #include "system/time.h"
23 #include "lib/registry/tdr_regf.h"
24 #include "librpc/gen_ndr/ndr_security.h"
25 #include "librpc/gen_ndr/winreg.h"
26 #include "lib/registry/registry.h"
27 #include "libcli/security/security.h"
30 static struct hive_operations reg_backend_regf;
33 * There are several places on the web where the REGF format is explained;
39 * - Return error codes that make more sense
41 * - do more things in-memory
45 * Read HBIN blocks into memory
50 struct hbin_block **hbins;
51 struct regf_hdr *header;
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);
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);
263 /* Make sure that we have no tailing garbage in the block */
264 if (dest.length > blob.length) {
265 memset(dest.data + blob.length, 0, dest.length - blob.length);
271 static uint32_t hbin_store_tdr(struct regf_data *data,
272 tdr_push_fn_t push_fn, void *p)
274 struct tdr_push *push = tdr_push_init(data);
277 if (NT_STATUS_IS_ERR(push_fn(push, p))) {
278 DEBUG(0, ("Error during push\n"));
282 ret = hbin_store(data, push->data);
290 /* Free existing data */
291 static void hbin_free (struct regf_data *data, uint32_t offset)
296 struct hbin_block *hbin;
298 SMB_ASSERT (offset > 0);
300 hbin = hbin_by_offset(data, offset, &rel_offset);
305 /* Get original size */
306 size = IVALS(hbin->data, rel_offset);
309 DEBUG(1, ("Trying to free already freed block at 0x%04x\n",
316 /* If the next block is free, merge into big free block */
317 if (rel_offset + size < hbin->offset_to_next) {
318 next_size = IVALS(hbin->data, rel_offset+size);
324 /* Write block size */
325 SIVALS(hbin->data, rel_offset, size);
329 * Store a data blob data was already stored, but has changed in size
330 * Will try to save it at the current location if possible, otherwise
331 * does a free + store */
332 static uint32_t hbin_store_resize(struct regf_data *data,
333 uint32_t orig_offset, DATA_BLOB blob)
336 struct hbin_block *hbin = hbin_by_offset(data, orig_offset,
341 int32_t possible_size;
344 SMB_ASSERT(orig_offset > 0);
347 return hbin_store(data, blob);
349 /* Get original size */
350 orig_size = -IVALS(hbin->data, rel_offset);
352 needed_size = blob.length + 4; /* Add int32 containing length */
353 needed_size = (needed_size + 7) & ~7; /* Align */
355 /* Fits into current allocated block */
356 if (orig_size >= needed_size) {
357 memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length);
358 /* If the difference in size is greater than 0x4, split the block
359 * and free/merge it */
360 if (orig_size - needed_size > 0x4) {
361 SIVALS(hbin->data, rel_offset, -needed_size);
362 SIVALS(hbin->data, rel_offset + needed_size,
363 needed_size-orig_size);
364 hbin_free(data, orig_offset + needed_size);
369 possible_size = orig_size;
371 /* Check if it can be combined with the next few free records */
372 for (i = rel_offset; i < hbin->offset_to_next - 0x20; i += my_size) {
373 if (IVALS(hbin->data, i) < 0) /* Used */
376 my_size = IVALS(hbin->data, i);
378 if (my_size == 0x0) {
379 DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
382 possible_size += my_size;
385 if (possible_size >= blob.length) {
386 SIVAL(hbin->data, rel_offset, -possible_size);
387 memcpy(hbin->data + rel_offset + 0x4,
388 blob.data, blob.length);
393 hbin_free(data, orig_offset);
394 return hbin_store(data, blob);
397 static uint32_t hbin_store_tdr_resize(struct regf_data *regf,
398 tdr_push_fn_t push_fn,
399 uint32_t orig_offset, void *p)
401 struct tdr_push *push = tdr_push_init(regf);
404 if (NT_STATUS_IS_ERR(push_fn(push, p))) {
405 DEBUG(0, ("Error during push\n"));
409 ret = hbin_store_resize(regf, orig_offset, push->data);
416 static uint32_t regf_create_lh_hash(const char *name)
422 hash_name = strupper_talloc(NULL, name);
423 for (i = 0; *(hash_name + i) != 0; i++) {
425 ret += *(hash_name + i);
427 talloc_free(hash_name);
431 static WERROR regf_get_info(TALLOC_CTX *mem_ctx,
432 const struct hive_key *key,
433 const char **classname,
434 uint32_t *num_subkeys,
435 uint32_t *num_values,
436 NTTIME *last_mod_time,
437 uint32_t *max_subkeynamelen,
438 uint32_t *max_valnamelen,
439 uint32_t *max_valbufsize)
441 const struct regf_key_data *private_data =
442 (const struct regf_key_data *)key;
444 if (num_subkeys != NULL)
445 *num_subkeys = private_data->nk->num_subkeys;
447 if (num_values != NULL)
448 *num_values = private_data->nk->num_values;
450 if (classname != NULL) {
451 if (private_data->nk->clsname_offset != -1) {
452 DATA_BLOB data = hbin_get(private_data->hive,
453 private_data->nk->clsname_offset);
454 *classname = talloc_strndup(mem_ctx,
456 private_data->nk->clsname_length);
457 W_ERROR_HAVE_NO_MEMORY(*classname);
462 /* TODO: Last mod time */
464 /* TODO: max valnamelen */
466 /* TODO: max valbufsize */
468 /* TODO: max subkeynamelen */
473 static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx,
474 struct regf_data *regf,
478 struct regf_key_data *ret;
480 ret = talloc_zero(ctx, struct regf_key_data);
481 ret->key.ops = ®_backend_regf;
482 ret->hive = talloc_reference(ret, regf);
483 ret->offset = offset;
484 nk = talloc(ret, struct nk_block);
490 if (!hbin_get_tdr(regf, offset, nk,
491 (tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
492 DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
496 if (strcmp(nk->header, "nk") != 0) {
497 DEBUG(0, ("Expected nk record, got %s\n", nk->header));
506 static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key,
507 uint32_t idx, const char **name,
508 uint32_t *data_type, DATA_BLOB *data)
510 const struct regf_key_data *private_data =
511 (const struct regf_key_data *)key;
513 struct regf_data *regf = private_data->hive;
517 if (idx >= private_data->nk->num_values)
518 return WERR_NO_MORE_ITEMS;
520 tmp = hbin_get(regf, private_data->nk->values_offset);
522 DEBUG(0, ("Unable to find value list\n"));
523 return WERR_GENERAL_FAILURE;
526 if (tmp.length < private_data->nk->num_values * 4) {
527 DEBUG(1, ("Value counts mismatch\n"));
530 vk_offset = IVAL(tmp.data, idx * 4);
532 vk = talloc(NULL, struct vk_block);
533 W_ERROR_HAVE_NO_MEMORY(vk);
535 if (!hbin_get_tdr(regf, vk_offset, vk,
536 (tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
537 DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));
539 return WERR_GENERAL_FAILURE;
542 /* FIXME: name character set ?*/
544 *name = talloc_strndup(ctx, vk->data_name, vk->name_length);
545 W_ERROR_HAVE_NO_MEMORY(*name);
548 if (data_type != NULL)
549 *data_type = vk->data_type;
551 if (vk->data_length & 0x80000000) {
552 /* this is data of type "REG_DWORD" or "REG_DWORD_BIG_ENDIAN" */
553 data->data = talloc_size(ctx, sizeof(uint32_t));
554 W_ERROR_HAVE_NO_MEMORY(data->data);
555 SIVAL(data->data, 0, vk->data_offset);
556 data->length = sizeof(uint32_t);
558 *data = hbin_get(regf, vk->data_offset);
561 if (data->length < vk->data_length) {
562 DEBUG(1, ("Read data less than indicated data length!\n"));
570 static WERROR regf_get_value_by_name(TALLOC_CTX *mem_ctx,
571 struct hive_key *key, const char *name,
572 uint32_t *type, DATA_BLOB *data)
578 /* FIXME: Do binary search? Is this list sorted at all? */
580 for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i,
581 &vname, type, data));
583 if (!strcmp(vname, name))
587 if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
594 static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx,
595 const struct hive_key *key,
596 uint32_t idx, const char **name,
597 const char **classname,
598 NTTIME *last_mod_time)
601 struct regf_key_data *ret;
602 const struct regf_key_data *private_data = (const struct regf_key_data *)key;
603 struct nk_block *nk = private_data->nk;
606 if (idx >= nk->num_subkeys)
607 return WERR_NO_MORE_ITEMS;
609 data = hbin_get(private_data->hive, nk->subkeys_offset);
611 DEBUG(0, ("Unable to find subkey list\n"));
612 return WERR_GENERAL_FAILURE;
615 if (!strncmp((char *)data.data, "li", 2)) {
617 struct tdr_pull *pull = tdr_pull_init(private_data->hive);
619 DEBUG(10, ("Subkeys in LI list\n"));
622 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) {
623 DEBUG(0, ("Error parsing LI list\n"));
625 return WERR_GENERAL_FAILURE;
628 SMB_ASSERT(!strncmp(li.header, "li", 2));
630 if (li.key_count != nk->num_subkeys) {
631 DEBUG(0, ("Subkey counts don't match\n"));
632 return WERR_GENERAL_FAILURE;
634 key_off = li.nk_offset[idx];
636 } else if (!strncmp((char *)data.data, "lf", 2)) {
638 struct tdr_pull *pull = tdr_pull_init(private_data->hive);
640 DEBUG(10, ("Subkeys in LF list\n"));
643 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) {
644 DEBUG(0, ("Error parsing LF list\n"));
646 return WERR_GENERAL_FAILURE;
649 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
651 if (lf.key_count != nk->num_subkeys) {
652 DEBUG(0, ("Subkey counts don't match\n"));
653 return WERR_GENERAL_FAILURE;
656 key_off = lf.hr[idx].nk_offset;
657 } else if (!strncmp((char *)data.data, "lh", 2)) {
659 struct tdr_pull *pull = tdr_pull_init(private_data->hive);
661 DEBUG(10, ("Subkeys in LH list\n"));
664 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) {
665 DEBUG(0, ("Error parsing LH list\n"));
667 return WERR_GENERAL_FAILURE;
670 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
672 if (lh.key_count != nk->num_subkeys) {
673 DEBUG(0, ("Subkey counts don't match\n"));
674 return WERR_GENERAL_FAILURE;
676 key_off = lh.hr[idx].nk_offset;
677 } else if (!strncmp((char *)data.data, "ri", 2)) {
679 struct tdr_pull *pull = tdr_pull_init(ctx);
681 uint16_t sublist_count = 0;
683 DEBUG(10, ("Subkeys in RI list\n"));
686 if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) {
687 DEBUG(0, ("Error parsing RI list\n"));
689 return WERR_GENERAL_FAILURE;
691 SMB_ASSERT(!strncmp(ri.header, "ri", 2));
693 for (i = 0; i < ri.key_count; i++) {
696 /* Get sublist data blob */
697 list_data = hbin_get(private_data->hive, ri.offset[i]);
698 if (!list_data.data) {
699 DEBUG(0, ("Error getting RI list."));
701 return WERR_GENERAL_FAILURE;
704 pull->data = list_data;
706 if (!strncmp((char *)list_data.data, "li", 2)) {
709 DEBUG(10, ("Subkeys in RI->LI list\n"));
711 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull,
714 DEBUG(0, ("Error parsing LI list from RI\n"));
716 return WERR_GENERAL_FAILURE;
718 SMB_ASSERT(!strncmp(li.header, "li", 2));
720 /* Advance to next sublist if necessary */
721 if (idx >= sublist_count + li.key_count) {
722 sublist_count += li.key_count;
725 key_off = li.nk_offset[idx - sublist_count];
726 sublist_count += li.key_count;
728 } else if (!strncmp((char *)list_data.data, "lh", 2)) {
731 DEBUG(10, ("Subkeys in RI->LH list\n"));
733 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull,
736 DEBUG(0, ("Error parsing LH list from RI\n"));
738 return WERR_GENERAL_FAILURE;
740 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
742 /* Advance to next sublist if necessary */
743 if (idx >= sublist_count + lh.key_count) {
744 sublist_count += lh.key_count;
747 key_off = lh.hr[idx - sublist_count].nk_offset;
748 sublist_count += lh.key_count;
751 DEBUG(0,("Unknown sublist in ri block\n"));
754 return WERR_GENERAL_FAILURE;
761 if (idx > sublist_count) {
762 return WERR_NO_MORE_ITEMS;
766 DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n",
767 nk->subkeys_offset, data.data[0], data.data[1]));
768 return WERR_GENERAL_FAILURE;
771 ret = regf_get_key (ctx, private_data->hive, key_off);
773 if (classname != NULL) {
774 if (ret->nk->clsname_offset != -1) {
775 DATA_BLOB db = hbin_get(ret->hive,
776 ret->nk->clsname_offset);
777 *classname = talloc_strndup(ctx,
779 ret->nk->clsname_length);
780 W_ERROR_HAVE_NO_MEMORY(*classname);
785 if (last_mod_time != NULL)
786 *last_mod_time = ret->nk->last_change;
789 *name = talloc_steal(ctx, ret->nk->key_name);
796 static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx,
797 const struct hive_key *key,
799 const char *name, uint32_t *ret)
801 DATA_BLOB subkey_data;
802 struct nk_block subkey;
803 struct tdr_pull *pull;
804 const struct regf_key_data *private_data =
805 (const struct regf_key_data *)key;
807 subkey_data = hbin_get(private_data->hive, offset);
808 if (!subkey_data.data) {
809 DEBUG(0, ("Unable to retrieve subkey HBIN\n"));
810 return WERR_GENERAL_FAILURE;
813 pull = tdr_pull_init(ctx);
815 pull->data = subkey_data;
817 if (NT_STATUS_IS_ERR(tdr_pull_nk_block(pull, ctx, &subkey))) {
818 DEBUG(0, ("Error parsing NK structure.\n"));
820 return WERR_GENERAL_FAILURE;
824 if (strncmp(subkey.header, "nk", 2)) {
825 DEBUG(0, ("Not an NK structure.\n"));
826 return WERR_GENERAL_FAILURE;
829 if (!strcasecmp(subkey.key_name, name)) {
837 static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx,
838 const struct hive_key *key,
840 struct hive_key **ret)
843 const struct regf_key_data *private_data =
844 (const struct regf_key_data *)key;
845 struct nk_block *nk = private_data->nk;
846 uint32_t key_off = 0;
848 data = hbin_get(private_data->hive, nk->subkeys_offset);
850 DEBUG(0, ("Unable to find subkey list\n"));
851 return WERR_GENERAL_FAILURE;
854 if (!strncmp((char *)data.data, "li", 2)) {
856 struct tdr_pull *pull = tdr_pull_init(ctx);
859 DEBUG(10, ("Subkeys in LI list\n"));
862 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) {
863 DEBUG(0, ("Error parsing LI list\n"));
865 return WERR_GENERAL_FAILURE;
868 SMB_ASSERT(!strncmp(li.header, "li", 2));
870 if (li.key_count != nk->num_subkeys) {
871 DEBUG(0, ("Subkey counts don't match\n"));
872 return WERR_GENERAL_FAILURE;
875 for (i = 0; i < li.key_count; i++) {
876 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
885 } else if (!strncmp((char *)data.data, "lf", 2)) {
887 struct tdr_pull *pull = tdr_pull_init(ctx);
890 DEBUG(10, ("Subkeys in LF list\n"));
893 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) {
894 DEBUG(0, ("Error parsing LF list\n"));
896 return WERR_GENERAL_FAILURE;
899 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
901 if (lf.key_count != nk->num_subkeys) {
902 DEBUG(0, ("Subkey counts don't match\n"));
903 return WERR_GENERAL_FAILURE;
906 for (i = 0; i < lf.key_count; i++) {
907 if (strncmp(lf.hr[i].hash, name, 4)) {
910 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
920 } else if (!strncmp((char *)data.data, "lh", 2)) {
922 struct tdr_pull *pull = tdr_pull_init(ctx);
926 DEBUG(10, ("Subkeys in LH list\n"));
929 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) {
930 DEBUG(0, ("Error parsing LH list\n"));
932 return WERR_GENERAL_FAILURE;
935 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
937 if (lh.key_count != nk->num_subkeys) {
938 DEBUG(0, ("Subkey counts don't match\n"));
939 return WERR_GENERAL_FAILURE;
942 hash = regf_create_lh_hash(name);
943 for (i = 0; i < lh.key_count; i++) {
944 if (lh.hr[i].base37 != hash) {
947 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
957 } else if (!strncmp((char *)data.data, "ri", 2)) {
959 struct tdr_pull *pull = tdr_pull_init(ctx);
962 DEBUG(10, ("Subkeys in RI list\n"));
965 if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) {
966 DEBUG(0, ("Error parsing RI list\n"));
968 return WERR_GENERAL_FAILURE;
970 SMB_ASSERT(!strncmp(ri.header, "ri", 2));
972 for (i = 0; i < ri.key_count; i++) {
975 /* Get sublist data blob */
976 list_data = hbin_get(private_data->hive, ri.offset[i]);
977 if (list_data.data == NULL) {
978 DEBUG(0, ("Error getting RI list."));
980 return WERR_GENERAL_FAILURE;
983 pull->data = list_data;
985 if (!strncmp((char *)list_data.data, "li", 2)) {
988 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull,
991 DEBUG(0, ("Error parsing LI list from RI\n"));
993 return WERR_GENERAL_FAILURE;
995 SMB_ASSERT(!strncmp(li.header, "li", 2));
997 for (j = 0; j < li.key_count; j++) {
998 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
1005 } else if (!strncmp((char *)list_data.data, "lh", 2)) {
1009 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull,
1012 DEBUG(0, ("Error parsing LH list from RI\n"));
1014 return WERR_GENERAL_FAILURE;
1016 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1018 hash = regf_create_lh_hash(name);
1019 for (j = 0; j < lh.key_count; j++) {
1020 if (lh.hr[j].base37 != hash) {
1023 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
1036 return WERR_BADFILE;
1038 DEBUG(0, ("Unknown subkey list type.\n"));
1039 return WERR_GENERAL_FAILURE;
1042 *ret = (struct hive_key *)regf_get_key(ctx, private_data->hive,
1047 static WERROR regf_set_sec_desc(struct hive_key *key,
1048 const struct security_descriptor *sec_desc)
1050 const struct regf_key_data *private_data =
1051 (const struct regf_key_data *)key;
1052 struct sk_block cur_sk, sk, new_sk;
1053 struct regf_data *regf = private_data->hive;
1054 struct nk_block root;
1056 uint32_t sk_offset, cur_sk_offset;
1057 bool update_cur_sk = false;
1059 /* Get the root nk */
1060 hbin_get_tdr(regf, regf->header->data_offset, regf,
1061 (tdr_pull_fn_t) tdr_pull_nk_block, &root);
1063 /* Push the security descriptor to a blob */
1064 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf,
1065 sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
1066 DEBUG(0, ("Unable to push security descriptor\n"));
1067 return WERR_GENERAL_FAILURE;
1070 /* Get the current security descriptor for the key */
1071 if (!hbin_get_tdr(regf, private_data->nk->sk_offset, regf,
1072 (tdr_pull_fn_t) tdr_pull_sk_block, &cur_sk)) {
1073 DEBUG(0, ("Unable to find security descriptor for current key\n"));
1074 return WERR_BADFILE;
1076 /* If there's no change, change nothing. */
1077 if (memcmp(data.data, cur_sk.sec_desc,
1078 MIN(data.length, cur_sk.rec_size)) == 0) {
1082 /* Delete the current sk if only this key is using it */
1083 if (cur_sk.ref_cnt == 1) {
1084 /* Get the previous security descriptor for the key */
1085 if (!hbin_get_tdr(regf, cur_sk.prev_offset, regf,
1086 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1087 DEBUG(0, ("Unable to find prev security descriptor for current key\n"));
1088 return WERR_BADFILE;
1090 /* Change and store the previous security descriptor */
1091 sk.next_offset = cur_sk.next_offset;
1092 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block,
1093 cur_sk.prev_offset, &sk);
1095 /* Get the next security descriptor for the key */
1096 if (!hbin_get_tdr(regf, cur_sk.next_offset, regf,
1097 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1098 DEBUG(0, ("Unable to find next security descriptor for current key\n"));
1099 return WERR_BADFILE;
1101 /* Change and store the next security descriptor */
1102 sk.prev_offset = cur_sk.prev_offset;
1103 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block,
1104 cur_sk.next_offset, &sk);
1106 hbin_free(regf, private_data->nk->sk_offset);
1108 /* This key will no longer be referring to this sk */
1110 update_cur_sk = true;
1113 sk_offset = root.sk_offset;
1116 cur_sk_offset = sk_offset;
1117 if (!hbin_get_tdr(regf, sk_offset, regf,
1118 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1119 DEBUG(0, ("Unable to find security descriptor\n"));
1120 return WERR_BADFILE;
1122 if (memcmp(data.data, sk.sec_desc, MIN(data.length, sk.rec_size)) == 0) {
1123 private_data->nk->sk_offset = sk_offset;
1125 hbin_store_tdr_resize(regf,
1126 (tdr_push_fn_t) tdr_push_sk_block,
1128 hbin_store_tdr_resize(regf,
1129 (tdr_push_fn_t) tdr_push_nk_block,
1130 private_data->offset,
1134 sk_offset = sk.next_offset;
1135 } while (sk_offset != root.sk_offset);
1137 ZERO_STRUCT(new_sk);
1138 new_sk.header = "sk";
1139 new_sk.prev_offset = cur_sk_offset;
1140 new_sk.next_offset = root.sk_offset;
1142 new_sk.rec_size = data.length;
1143 new_sk.sec_desc = data.data;
1145 sk_offset = hbin_store_tdr(regf,
1146 (tdr_push_fn_t) tdr_push_sk_block,
1148 if (sk_offset == -1) {
1149 DEBUG(0, ("Error storing sk block\n"));
1150 return WERR_GENERAL_FAILURE;
1152 private_data->nk->sk_offset = sk_offset;
1154 if (update_cur_sk) {
1155 hbin_store_tdr_resize(regf,
1156 (tdr_push_fn_t) tdr_push_sk_block,
1157 private_data->nk->sk_offset, &cur_sk);
1160 /* Get the previous security descriptor for the key */
1161 if (!hbin_get_tdr(regf, new_sk.prev_offset, regf,
1162 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1163 DEBUG(0, ("Unable to find security descriptor for previous key\n"));
1164 return WERR_BADFILE;
1166 /* Change and store the previous security descriptor */
1167 sk.next_offset = sk_offset;
1168 hbin_store_tdr_resize(regf,
1169 (tdr_push_fn_t) tdr_push_sk_block,
1170 cur_sk.prev_offset, &sk);
1172 /* Get the next security descriptor for the key (always root, as we append) */
1173 if (!hbin_get_tdr(regf, new_sk.next_offset, regf,
1174 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1175 DEBUG(0, ("Unable to find security descriptor for current key\n"));
1176 return WERR_BADFILE;
1178 /* Change and store the next security descriptor (always root, as we append) */
1179 sk.prev_offset = sk_offset;
1180 hbin_store_tdr_resize(regf,
1181 (tdr_push_fn_t) tdr_push_sk_block,
1182 root.sk_offset, &sk);
1186 hbin_store_tdr_resize(regf,
1187 (tdr_push_fn_t) tdr_push_sk_block,
1188 private_data->offset, private_data->nk);
1192 static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key,
1193 struct security_descriptor **sd)
1195 const struct regf_key_data *private_data =
1196 (const struct regf_key_data *)key;
1198 struct regf_data *regf = private_data->hive;
1201 if (!hbin_get_tdr(regf, private_data->nk->sk_offset, ctx,
1202 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1203 DEBUG(0, ("Unable to find security descriptor\n"));
1204 return WERR_GENERAL_FAILURE;
1207 if (strcmp(sk.header, "sk") != 0) {
1208 DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header));
1209 return WERR_GENERAL_FAILURE;
1212 *sd = talloc(ctx, struct security_descriptor);
1213 W_ERROR_HAVE_NO_MEMORY(*sd);
1215 data.data = sk.sec_desc;
1216 data.length = sk.rec_size;
1217 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, *sd,
1218 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) {
1219 DEBUG(0, ("Error parsing security descriptor\n"));
1220 return WERR_GENERAL_FAILURE;
1226 static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset,
1228 uint32_t key_offset, uint32_t *ret)
1232 /* Create a new key if necessary */
1233 if (list_offset == -1) {
1234 if (regf->header->version.major != 1) {
1235 DEBUG(0, ("Can't store keys in unknown registry format\n"));
1236 return WERR_NOT_SUPPORTED;
1238 if (regf->header->version.minor < 3) {
1245 li.nk_offset = talloc_array(regf, uint32_t, 1);
1246 W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1247 li.nk_offset[0] = key_offset;
1249 *ret = hbin_store_tdr(regf,
1250 (tdr_push_fn_t) tdr_push_li_block,
1253 talloc_free(li.nk_offset);
1254 } else if (regf->header->version.minor == 3 ||
1255 regf->header->version.minor == 4) {
1262 lf.hr = talloc_array(regf, struct hash_record, 1);
1263 W_ERROR_HAVE_NO_MEMORY(lf.hr);
1264 lf.hr[0].nk_offset = key_offset;
1265 lf.hr[0].hash = talloc_strndup(lf.hr, name, 4);
1266 W_ERROR_HAVE_NO_MEMORY(lf.hr[0].hash);
1268 *ret = hbin_store_tdr(regf,
1269 (tdr_push_fn_t) tdr_push_lf_block,
1273 } else if (regf->header->version.minor == 5) {
1280 lh.hr = talloc_array(regf, struct lh_hash, 1);
1281 W_ERROR_HAVE_NO_MEMORY(lh.hr);
1282 lh.hr[0].nk_offset = key_offset;
1283 lh.hr[0].base37 = regf_create_lh_hash(name);
1285 *ret = hbin_store_tdr(regf,
1286 (tdr_push_fn_t) tdr_push_lh_block,
1294 data = hbin_get(regf, list_offset);
1296 DEBUG(0, ("Unable to find subkey list\n"));
1297 return WERR_BADFILE;
1300 if (!strncmp((char *)data.data, "li", 2)) {
1301 struct tdr_pull *pull = tdr_pull_init(regf);
1306 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) {
1307 DEBUG(0, ("Error parsing LI list\n"));
1309 return WERR_BADFILE;
1313 if (strncmp(li.header, "li", 2) != 0) {
1315 DEBUG(0, ("LI header corrupt\n"));
1316 return WERR_BADFILE;
1319 li.nk_offset = talloc_realloc(regf, li.nk_offset,
1320 uint32_t, li.key_count+1);
1321 W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1322 li.nk_offset[li.key_count] = key_offset;
1324 *ret = hbin_store_tdr_resize(regf,
1325 (tdr_push_fn_t)tdr_push_li_block,
1328 talloc_free(li.nk_offset);
1329 } else if (!strncmp((char *)data.data, "lf", 2)) {
1330 struct tdr_pull *pull = tdr_pull_init(regf);
1335 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) {
1336 DEBUG(0, ("Error parsing LF list\n"));
1338 return WERR_BADFILE;
1341 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1343 lf.hr = talloc_realloc(regf, lf.hr, struct hash_record,
1345 W_ERROR_HAVE_NO_MEMORY(lf.hr);
1346 lf.hr[lf.key_count].nk_offset = key_offset;
1347 lf.hr[lf.key_count].hash = talloc_strndup(lf.hr, name, 4);
1348 W_ERROR_HAVE_NO_MEMORY(lf.hr[lf.key_count].hash);
1350 *ret = hbin_store_tdr_resize(regf,
1351 (tdr_push_fn_t)tdr_push_lf_block,
1355 } else if (!strncmp((char *)data.data, "lh", 2)) {
1356 struct tdr_pull *pull = tdr_pull_init(regf);
1361 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) {
1362 DEBUG(0, ("Error parsing LH list\n"));
1364 return WERR_BADFILE;
1367 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1369 lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash,
1371 W_ERROR_HAVE_NO_MEMORY(lh.hr);
1372 lh.hr[lh.key_count].nk_offset = key_offset;
1373 lh.hr[lh.key_count].base37 = regf_create_lh_hash(name);
1375 *ret = hbin_store_tdr_resize(regf,
1376 (tdr_push_fn_t)tdr_push_lh_block,
1380 } else if (!strncmp((char *)data.data, "ri", 2)) {
1382 DEBUG(0, ("Adding to 'ri' subkey list is not supported yet.\n"));
1383 return WERR_NOT_SUPPORTED;
1385 DEBUG(0, ("Cannot add to unknown subkey list\n"));
1386 return WERR_BADFILE;
1392 static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset,
1393 uint32_t key_offset, uint32_t *ret)
1397 data = hbin_get(regf, list_offset);
1399 DEBUG(0, ("Unable to find subkey list\n"));
1400 return WERR_BADFILE;
1403 if (strncmp((char *)data.data, "li", 2) == 0) {
1405 struct tdr_pull *pull = tdr_pull_init(regf);
1407 bool found_offset = false;
1409 DEBUG(10, ("Subkeys in LI list\n"));
1413 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) {
1414 DEBUG(0, ("Error parsing LI list\n"));
1416 return WERR_BADFILE;
1420 SMB_ASSERT(!strncmp(li.header, "li", 2));
1422 for (i = 0; i < li.key_count; i++) {
1424 li.nk_offset[i-1] = li.nk_offset[i];
1426 if (li.nk_offset[i] == key_offset) {
1427 found_offset = true;
1431 if (!found_offset) {
1432 DEBUG(2, ("Subkey not found\n"));
1433 return WERR_BADFILE;
1437 /* If the there are no entries left, free the subkey list */
1438 if (li.key_count == 0) {
1439 hbin_free(regf, list_offset);
1443 /* Store li block */
1444 *ret = hbin_store_tdr_resize(regf,
1445 (tdr_push_fn_t) tdr_push_li_block,
1447 } else if (strncmp((char *)data.data, "lf", 2) == 0) {
1449 struct tdr_pull *pull = tdr_pull_init(regf);
1451 bool found_offset = false;
1453 DEBUG(10, ("Subkeys in LF list\n"));
1457 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) {
1458 DEBUG(0, ("Error parsing LF list\n"));
1460 return WERR_BADFILE;
1464 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1466 for (i = 0; i < lf.key_count; i++) {
1468 lf.hr[i-1] = lf.hr[i];
1471 if (lf.hr[i].nk_offset == key_offset) {
1476 if (!found_offset) {
1477 DEBUG(2, ("Subkey not found\n"));
1478 return WERR_BADFILE;
1482 /* If the there are no entries left, free the subkey list */
1483 if (lf.key_count == 0) {
1484 hbin_free(regf, list_offset);
1489 /* Store lf block */
1490 *ret = hbin_store_tdr_resize(regf,
1491 (tdr_push_fn_t) tdr_push_lf_block,
1493 } else if (strncmp((char *)data.data, "lh", 2) == 0) {
1495 struct tdr_pull *pull = tdr_pull_init(regf);
1497 bool found_offset = false;
1499 DEBUG(10, ("Subkeys in LH list\n"));
1503 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) {
1504 DEBUG(0, ("Error parsing LF list\n"));
1506 return WERR_BADFILE;
1510 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1512 for (i = 0; i < lh.key_count; i++) {
1514 lh.hr[i-1] = lh.hr[i];
1517 if (lh.hr[i].nk_offset == key_offset) {
1522 if (!found_offset) {
1523 DEBUG(0, ("Subkey not found\n"));
1524 return WERR_BADFILE;
1528 /* If the there are no entries left, free the subkey list */
1529 if (lh.key_count == 0) {
1530 hbin_free(regf, list_offset);
1535 /* Store lh block */
1536 *ret = hbin_store_tdr_resize(regf,
1537 (tdr_push_fn_t) tdr_push_lh_block,
1539 } else if (strncmp((char *)data.data, "ri", 2) == 0) {
1541 DEBUG(0, ("Sorry, deletion from ri block is not supported yet.\n"));
1542 return WERR_NOT_SUPPORTED;
1544 DEBUG (0, ("Unknown header found in subkey list.\n"));
1545 return WERR_BADFILE;
1550 static WERROR regf_del_value(TALLOC_CTX *mem_ctx, struct hive_key *key,
1553 struct regf_key_data *private_data = (struct regf_key_data *)key;
1554 struct regf_data *regf = private_data->hive;
1555 struct nk_block *nk = private_data->nk;
1558 bool found_offset = false;
1562 if (nk->values_offset == -1) {
1563 return WERR_BADFILE;
1566 values = hbin_get(regf, nk->values_offset);
1568 for (i = 0; i < nk->num_values; i++) {
1570 ((uint32_t *)values.data)[i-1] = ((uint32_t *) values.data)[i];
1572 vk_offset = IVAL(values.data, i * 4);
1573 if (!hbin_get_tdr(regf, vk_offset, private_data,
1574 (tdr_pull_fn_t)tdr_pull_vk_block,
1576 DEBUG(0, ("Unable to get VK block at %d\n",
1578 return WERR_BADFILE;
1580 if (strcmp(vk.data_name, name) == 0) {
1581 hbin_free(regf, vk_offset);
1582 found_offset = true;
1586 if (!found_offset) {
1587 return WERR_BADFILE;
1590 values.length = (nk->num_values)*4;
1593 /* Store values list and nk */
1594 if (nk->num_values == 0) {
1595 hbin_free(regf, nk->values_offset);
1596 nk->values_offset = -1;
1598 nk->values_offset = hbin_store_resize(regf,
1602 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
1603 private_data->offset, nk);
1605 return regf_save_hbin(private_data->hive);
1609 static WERROR regf_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *parent,
1612 const struct regf_key_data *private_data =
1613 (const struct regf_key_data *)parent;
1614 struct regf_key_data *key;
1615 struct nk_block *parent_nk;
1618 SMB_ASSERT(private_data);
1620 parent_nk = private_data->nk;
1622 if (parent_nk->subkeys_offset == -1) {
1623 DEBUG(4, ("Subkey list is empty, this key cannot contain subkeys.\n"));
1624 return WERR_BADFILE;
1628 if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name,
1629 (struct hive_key **)&key))) {
1630 DEBUG(2, ("Key '%s' not found\n", name));
1631 return WERR_BADFILE;
1634 if (key->nk->subkeys_offset != -1) {
1636 struct hive_key *sk = (struct hive_key *)key;
1637 unsigned int i = key->nk->num_subkeys;
1639 /* Get subkey information. */
1640 error = regf_get_subkey_by_index(parent_nk, sk, 0,
1641 (const char **)&sk_name,
1643 if (!W_ERROR_IS_OK(error)) {
1644 DEBUG(0, ("Can't retrieve subkey by index.\n"));
1648 /* Delete subkey. */
1649 error = regf_del_key(NULL, sk, sk_name);
1650 if (!W_ERROR_IS_OK(error)) {
1651 DEBUG(0, ("Can't delete key '%s'.\n", sk_name));
1655 talloc_free(sk_name);
1659 if (key->nk->values_offset != -1) {
1661 struct hive_key *sk = (struct hive_key *)key;
1663 unsigned int i = key->nk->num_values;
1665 /* Get value information. */
1666 error = regf_get_value(parent_nk, sk, 0,
1667 (const char **)&val_name,
1669 if (!W_ERROR_IS_OK(error)) {
1670 DEBUG(0, ("Can't retrieve value by index.\n"));
1675 error = regf_del_value(NULL, sk, val_name);
1676 if (!W_ERROR_IS_OK(error)) {
1677 DEBUG(0, ("Can't delete value '%s'.\n", val_name));
1681 talloc_free(val_name);
1685 /* Delete it from the subkey list. */
1686 error = regf_sl_del_entry(private_data->hive, parent_nk->subkeys_offset,
1687 key->offset, &parent_nk->subkeys_offset);
1688 if (!W_ERROR_IS_OK(error)) {
1689 DEBUG(0, ("Can't store new subkey list for parent key. Won't delete.\n"));
1693 /* Re-store parent key */
1694 parent_nk->num_subkeys--;
1695 hbin_store_tdr_resize(private_data->hive,
1696 (tdr_push_fn_t) tdr_push_nk_block,
1697 private_data->offset, parent_nk);
1699 if (key->nk->clsname_offset != -1) {
1700 hbin_free(private_data->hive, key->nk->clsname_offset);
1702 hbin_free(private_data->hive, key->offset);
1704 return regf_save_hbin(private_data->hive);
1707 static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent,
1708 const char *name, const char *classname,
1709 struct security_descriptor *sec_desc,
1710 struct hive_key **ret)
1712 const struct regf_key_data *private_data =
1713 (const struct regf_key_data *)parent;
1714 struct nk_block *parent_nk = private_data->nk, nk;
1715 struct nk_block *root;
1716 struct regf_data *regf = private_data->hive;
1721 nk.type = REG_SUB_KEY;
1722 unix_to_nt_time(&nk.last_change, time(NULL));
1724 nk.parent_offset = private_data->offset;
1727 nk.subkeys_offset = -1;
1728 nk.unknown_offset = -1;
1730 nk.values_offset = -1;
1731 memset(nk.unk3, 0, 5);
1732 nk.clsname_offset = -1; /* FIXME: fill in */
1733 nk.clsname_length = 0;
1736 /* Get the security descriptor of the root key */
1737 root = talloc_zero(ctx, struct nk_block);
1738 W_ERROR_HAVE_NO_MEMORY(root);
1740 if (!hbin_get_tdr(regf, regf->header->data_offset, root,
1741 (tdr_pull_fn_t)tdr_pull_nk_block, root)) {
1742 DEBUG(0, ("Unable to find HBIN data for offset %d\n",
1743 regf->header->data_offset));
1744 return WERR_GENERAL_FAILURE;
1746 nk.sk_offset = root->sk_offset;
1749 /* Store the new nk key */
1750 offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk);
1752 error = regf_sl_add_entry(regf, parent_nk->subkeys_offset, name, offset,
1753 &parent_nk->subkeys_offset);
1754 if (!W_ERROR_IS_OK(error)) {
1755 hbin_free(regf, offset);
1759 parent_nk->num_subkeys++;
1761 /* Since the subkey offset of the parent can change, store it again */
1762 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
1763 nk.parent_offset, parent_nk);
1765 *ret = (struct hive_key *)regf_get_key(ctx, regf, offset);
1767 return regf_save_hbin(private_data->hive);
1770 static WERROR regf_set_value(struct hive_key *key, const char *name,
1771 uint32_t type, const DATA_BLOB data)
1773 struct regf_key_data *private_data = (struct regf_key_data *)key;
1774 struct regf_data *regf = private_data->hive;
1775 struct nk_block *nk = private_data->nk;
1778 uint32_t tmp_vk_offset, vk_offset, old_vk_offset = -1;
1783 /* find the value offset, if it exists */
1784 if (nk->values_offset != -1) {
1785 values = hbin_get(regf, nk->values_offset);
1787 for (i = 0; i < nk->num_values; i++) {
1788 tmp_vk_offset = IVAL(values.data, i * 4);
1789 if (!hbin_get_tdr(regf, tmp_vk_offset, private_data,
1790 (tdr_pull_fn_t)tdr_pull_vk_block,
1792 DEBUG(0, ("Unable to get VK block at %d\n",
1794 return WERR_GENERAL_FAILURE;
1796 if (strcmp(vk.data_name, name) == 0) {
1797 old_vk_offset = tmp_vk_offset;
1803 /* If it's new, create the vk struct, if it's old, free the old data. */
1804 if (old_vk_offset == -1) {
1806 vk.name_length = strlen(name);
1807 if (name != NULL && name[0] != 0) {
1809 vk.data_name = name;
1811 vk.data_name = NULL;
1815 /* Free data, if any */
1816 if (!(vk.data_length & 0x80000000)) {
1817 hbin_free(regf, vk.data_offset);
1821 /* Set the type and data */
1822 vk.data_length = data.length;
1823 vk.data_type = type;
1824 if ((type == REG_DWORD) || (type == REG_DWORD_BIG_ENDIAN)) {
1825 if (vk.data_length != sizeof(uint32_t)) {
1826 DEBUG(0, ("DWORD or DWORD_BIG_ENDIAN value with size other than 4 byte!\n"));
1827 return WERR_NOT_SUPPORTED;
1829 vk.data_length |= 0x80000000;
1830 vk.data_offset = IVAL(data.data, 0);
1832 /* Store data somewhere */
1833 vk.data_offset = hbin_store(regf, data);
1835 if (old_vk_offset == -1) {
1837 vk_offset = hbin_store_tdr(regf,
1838 (tdr_push_fn_t) tdr_push_vk_block,
1841 /* Store vk at offset */
1842 vk_offset = hbin_store_tdr_resize(regf,
1843 (tdr_push_fn_t) tdr_push_vk_block,
1844 old_vk_offset ,&vk);
1847 /* Re-allocate the value list */
1848 if (nk->values_offset == -1) {
1849 nk->values_offset = hbin_store_tdr(regf,
1850 (tdr_push_fn_t) tdr_push_uint32,
1855 /* Change if we're changing, otherwise we're adding the value */
1856 if (old_vk_offset != -1) {
1857 /* Find and overwrite the offset. */
1858 for (i = 0; i < nk->num_values; i++) {
1859 if (IVAL(values.data, i * 4) == old_vk_offset) {
1860 SIVAL(values.data, i * 4, vk_offset);
1865 /* Create a new value list */
1866 DATA_BLOB value_list;
1868 value_list.length = (nk->num_values+1)*4;
1869 value_list.data = (uint8_t *)talloc_array(private_data,
1872 W_ERROR_HAVE_NO_MEMORY(value_list.data);
1873 memcpy(value_list.data, values.data, nk->num_values * 4);
1875 SIVAL(value_list.data, nk->num_values * 4, vk_offset);
1877 nk->values_offset = hbin_store_resize(regf,
1883 hbin_store_tdr_resize(regf,
1884 (tdr_push_fn_t) tdr_push_nk_block,
1885 private_data->offset, nk);
1886 return regf_save_hbin(private_data->hive);
1889 static WERROR regf_save_hbin(struct regf_data *regf)
1891 struct tdr_push *push = tdr_push_init(regf);
1894 W_ERROR_HAVE_NO_MEMORY(push);
1896 if (lseek(regf->fd, 0, SEEK_SET) == -1) {
1897 DEBUG(0, ("Error lseeking in regf file\n"));
1898 return WERR_GENERAL_FAILURE;
1901 /* Recompute checksum */
1902 if (NT_STATUS_IS_ERR(tdr_push_regf_hdr(push, regf->header))) {
1903 DEBUG(0, ("Failed to push regf header\n"));
1904 return WERR_GENERAL_FAILURE;
1906 regf->header->chksum = regf_hdr_checksum(push->data.data);
1909 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd,
1910 (tdr_push_fn_t)tdr_push_regf_hdr,
1912 DEBUG(0, ("Error writing registry file header\n"));
1913 return WERR_GENERAL_FAILURE;
1916 if (lseek(regf->fd, 0x1000, SEEK_SET) == -1) {
1917 DEBUG(0, ("Error lseeking to 0x1000 in regf file\n"));
1918 return WERR_GENERAL_FAILURE;
1921 for (i = 0; regf->hbins[i]; i++) {
1922 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd,
1923 (tdr_push_fn_t)tdr_push_hbin_block,
1925 DEBUG(0, ("Error writing HBIN block\n"));
1926 return WERR_GENERAL_FAILURE;
1933 WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx,
1934 const char *location,
1935 int minor_version, struct hive_key **key)
1937 struct regf_data *regf;
1938 struct regf_hdr *regf_hdr;
1943 struct security_descriptor *sd;
1946 regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
1948 W_ERROR_HAVE_NO_MEMORY(regf);
1950 DEBUG(5, ("Attempting to create registry file\n"));
1952 /* Get the header */
1953 regf->fd = creat(location, 0644);
1955 if (regf->fd == -1) {
1956 DEBUG(0,("Could not create file: %s, %s\n", location,
1959 return WERR_GENERAL_FAILURE;
1962 regf_hdr = talloc_zero(regf, struct regf_hdr);
1963 W_ERROR_HAVE_NO_MEMORY(regf_hdr);
1964 regf_hdr->REGF_ID = "regf";
1965 unix_to_nt_time(®f_hdr->modtime, time(NULL));
1966 regf_hdr->version.major = 1;
1967 regf_hdr->version.minor = minor_version;
1968 regf_hdr->last_block = 0x1000; /* Block size */
1969 regf_hdr->description = talloc_strdup(regf_hdr,
1970 "Registry created by Samba 4");
1971 W_ERROR_HAVE_NO_MEMORY(regf_hdr->description);
1972 regf_hdr->chksum = 0;
1974 regf->header = regf_hdr;
1976 /* Create all hbin blocks */
1977 regf->hbins = talloc_array(regf, struct hbin_block *, 1);
1978 W_ERROR_HAVE_NO_MEMORY(regf->hbins);
1979 regf->hbins[0] = NULL;
1982 nk.type = REG_SUB_KEY;
1983 unix_to_nt_time(&nk.last_change, time(NULL));
1985 nk.parent_offset = -1;
1988 nk.subkeys_offset = -1;
1989 nk.unknown_offset = -1;
1991 nk.values_offset = -1;
1992 memset(nk.unk3, 0, 5);
1993 nk.clsname_offset = -1;
1994 nk.clsname_length = 0;
1995 nk.sk_offset = 0x80;
1996 nk.key_name = "SambaRootKey";
1999 * It should be noted that changing the key_name to something shorter
2000 * creates a shorter nk block, which makes the position of the sk block
2001 * change. All Windows registries I've seen have the sk at 0x80.
2002 * I therefore recommend that our regf files share that offset -- Wilco
2005 /* Create a security descriptor. */
2006 sd = security_descriptor_dacl_create(regf,
2009 SID_NT_AUTHENTICATED_USERS,
2010 SEC_ACE_TYPE_ACCESS_ALLOWED,
2012 SEC_ACE_FLAG_OBJECT_INHERIT,
2015 /* Push the security descriptor to a blob */
2016 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf,
2017 sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
2018 DEBUG(0, ("Unable to push security descriptor\n"));
2019 return WERR_GENERAL_FAILURE;
2024 sk.prev_offset = 0x80;
2025 sk.next_offset = 0x80;
2027 sk.rec_size = data.length;
2028 sk.sec_desc = data.data;
2030 /* Store the new nk key */
2031 regf->header->data_offset = hbin_store_tdr(regf,
2032 (tdr_push_fn_t)tdr_push_nk_block,
2034 /* Store the sk block */
2035 sk_offset = hbin_store_tdr(regf,
2036 (tdr_push_fn_t) tdr_push_sk_block,
2038 if (sk_offset != 0x80) {
2039 DEBUG(0, ("Error storing sk block, should be at 0x80, stored at 0x%x\n", nk.sk_offset));
2040 return WERR_GENERAL_FAILURE;
2044 *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
2045 regf->header->data_offset);
2047 error = regf_save_hbin(regf);
2048 if (!W_ERROR_IS_OK(error)) {
2052 /* We can drop our own reference now that *key will have created one */
2053 talloc_unlink(NULL, regf);
2058 WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location,
2059 struct hive_key **key)
2061 struct regf_data *regf;
2062 struct regf_hdr *regf_hdr;
2063 struct tdr_pull *pull;
2066 regf = (struct regf_data *)talloc_zero(parent_ctx, struct regf_data);
2068 W_ERROR_HAVE_NO_MEMORY(regf);
2070 DEBUG(5, ("Attempting to load registry file\n"));
2072 /* Get the header */
2073 regf->fd = open(location, O_RDWR);
2075 if (regf->fd == -1) {
2076 DEBUG(0,("Could not load file: %s, %s\n", location,
2079 return WERR_GENERAL_FAILURE;
2082 pull = tdr_pull_init(regf);
2084 pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, 0, regf);
2086 if (pull->data.data == NULL) {
2087 DEBUG(0, ("Error reading data\n"));
2089 return WERR_GENERAL_FAILURE;
2092 regf_hdr = talloc(regf, struct regf_hdr);
2093 W_ERROR_HAVE_NO_MEMORY(regf_hdr);
2095 if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr, regf_hdr))) {
2097 return WERR_GENERAL_FAILURE;
2100 regf->header = regf_hdr;
2102 if (strcmp(regf_hdr->REGF_ID, "regf") != 0) {
2103 DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n",
2104 regf_hdr->REGF_ID, location));
2106 return WERR_GENERAL_FAILURE;
2109 /* Validate the header ... */
2110 if (regf_hdr_checksum(pull->data.data) != regf_hdr->chksum) {
2111 DEBUG(0, ("Registry file checksum error: %s: %d,%d\n",
2112 location, regf_hdr->chksum,
2113 regf_hdr_checksum(pull->data.data)));
2115 return WERR_GENERAL_FAILURE;
2118 pull->offset = 0x1000;
2121 /* Read in all hbin blocks */
2122 regf->hbins = talloc_array(regf, struct hbin_block *, 1);
2123 W_ERROR_HAVE_NO_MEMORY(regf->hbins);
2125 regf->hbins[0] = NULL;
2127 while (pull->offset < pull->data.length &&
2128 pull->offset <= regf->header->last_block) {
2129 struct hbin_block *hbin = talloc(regf->hbins,
2132 W_ERROR_HAVE_NO_MEMORY(hbin);
2134 if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(pull, hbin, hbin))) {
2135 DEBUG(0, ("[%d] Error parsing HBIN block\n", i));
2140 if (strcmp(hbin->HBIN_ID, "hbin") != 0) {
2141 DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n",
2147 regf->hbins[i] = hbin;
2149 regf->hbins = talloc_realloc(regf, regf->hbins,
2150 struct hbin_block *, i+2);
2151 regf->hbins[i] = NULL;
2156 DEBUG(1, ("%d HBIN blocks read\n", i));
2158 *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
2159 regf->header->data_offset);
2161 /* We can drop our own reference now that *key will have created one */
2162 talloc_unlink(parent_ctx, regf);
2167 static struct hive_operations reg_backend_regf = {
2169 .get_key_info = regf_get_info,
2170 .enum_key = regf_get_subkey_by_index,
2171 .get_key_by_name = regf_get_subkey_by_name,
2172 .get_value_by_name = regf_get_value_by_name,
2173 .enum_value = regf_get_value,
2174 .get_sec_desc = regf_get_sec_desc,
2175 .set_sec_desc = regf_set_sec_desc,
2176 .add_key = regf_add_key,
2177 .set_value = regf_set_value,
2178 .del_key = regf_del_key,
2179 .delete_value = regf_del_value,