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;
52
struct smb_iconv_convenience *iconv_convenience;
55
static WERROR regf_save_hbin(struct regf_data *data);
57
struct regf_key_data {
59
struct regf_data *hive;
64
static struct hbin_block *hbin_by_offset(const struct regf_data *data,
65
uint32_t offset, uint32_t *rel_offset)
69
for (i = 0; data->hbins[i]; i++) {
70
if (offset >= data->hbins[i]->offset_from_first &&
71
offset < data->hbins[i]->offset_from_first+
72
data->hbins[i]->offset_to_next) {
73
if (rel_offset != NULL)
74
*rel_offset = offset - data->hbins[i]->offset_from_first - 0x20;
75
return data->hbins[i];
83
* Validate a regf header
84
* For now, do nothing, but we should check the checksum
86
static uint32_t regf_hdr_checksum(const uint8_t *buffer)
88
uint32_t checksum = 0, x;
91
for (i = 0; i < 0x01FB; i+= 4) {
100
* Obtain the contents of a HBIN block
102
static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset)
105
struct hbin_block *hbin;
111
hbin = hbin_by_offset(data, offset, &rel_offset);
114
DEBUG(1, ("Can't find HBIN containing 0x%04x\n", offset));
118
ret.length = IVAL(hbin->data, rel_offset);
119
if (!(ret.length & 0x80000000)) {
120
DEBUG(0, ("Trying to use dirty block at 0x%04x\n", offset));
124
/* remove high bit */
125
ret.length = (ret.length ^ 0xffffffff) + 1;
127
ret.length -= 4; /* 4 bytes for the length... */
128
ret.data = hbin->data +
129
(offset - hbin->offset_from_first - 0x20) + 4;
134
static bool hbin_get_tdr(struct regf_data *regf, uint32_t offset,
135
TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p)
137
struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
139
pull->data = hbin_get(regf, offset);
140
if (!pull->data.data) {
141
DEBUG(1, ("Unable to get data at 0x%04x\n", offset));
146
if (NT_STATUS_IS_ERR(pull_fn(pull, ctx, p))) {
147
DEBUG(1, ("Error parsing record at 0x%04x using tdr\n",
157
/* Allocate some new data */
158
static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size,
162
uint32_t rel_offset = -1; /* Relative offset ! */
163
struct hbin_block *hbin = NULL;
169
return data_blob(NULL, 0);
171
size += 4; /* Need to include int32 for the length */
173
/* Allocate as a multiple of 8 */
174
size = (size + 7) & ~7;
179
for (i = 0; (hbin = data->hbins[i]); i++) {
182
for (j = 0; j < hbin->offset_to_next-0x20; j+= my_size) {
183
my_size = IVALS(hbin->data, j);
185
if (my_size == 0x0) {
186
DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
190
if (my_size % 8 != 0) {
191
DEBUG(0, ("Encountered non-aligned block!\n"));
194
if (my_size < 0) { /* Used... */
196
} else if (my_size == size) { /* exact match */
198
DEBUG(4, ("Found free block of exact size %d in middle of HBIN\n",
201
} else if (my_size > size) { /* data will remain */
203
/* Split this block and mark the next block as free */
204
SIVAL(hbin->data, rel_offset+size, my_size-size);
205
DEBUG(4, ("Found free block of size %d (needing %d) in middle of HBIN\n",
211
if (rel_offset != -1)
215
/* No space available in previous hbins,
216
* allocate new one */
217
if (data->hbins[i] == NULL) {
218
DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n",
220
data->hbins = talloc_realloc(data, data->hbins,
221
struct hbin_block *, i+2);
222
hbin = talloc(data->hbins, struct hbin_block);
223
SMB_ASSERT(hbin != NULL);
225
data->hbins[i] = hbin;
226
data->hbins[i+1] = NULL;
228
hbin->HBIN_ID = talloc_strdup(hbin, "hbin");
229
hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next);
230
hbin->offset_to_next = 0x1000;
231
hbin->unknown[0] = 0;
232
hbin->unknown[0] = 0;
233
unix_to_nt_time(&hbin->last_change, time(NULL));
234
hbin->block_size = hbin->offset_to_next;
235
hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20);
238
SIVAL(hbin->data, size, hbin->block_size - size - 0x20);
241
/* Set size and mark as used */
242
SIVAL(hbin->data, rel_offset, -size);
244
ret.data = hbin->data + rel_offset + 0x4; /* Skip past length */
245
ret.length = size - 0x4;
247
uint32_t new_rel_offset;
248
*offset = hbin->offset_from_first + rel_offset + 0x20;
249
SMB_ASSERT(hbin_by_offset(data, *offset, &new_rel_offset) == hbin);
250
SMB_ASSERT(new_rel_offset == rel_offset);
256
/* Store a data blob. Return the offset at which it was stored */
257
static uint32_t hbin_store (struct regf_data *data, DATA_BLOB blob)
260
DATA_BLOB dest = hbin_alloc(data, blob.length, &ret);
262
memcpy(dest.data, blob.data, blob.length);
267
static uint32_t hbin_store_tdr(struct regf_data *data,
268
tdr_push_fn_t push_fn, void *p)
270
struct tdr_push *push = tdr_push_init(data, data->iconv_convenience);
273
if (NT_STATUS_IS_ERR(push_fn(push, p))) {
274
DEBUG(0, ("Error during push\n"));
278
ret = hbin_store(data, push->data);
286
/* Free existing data */
287
static void hbin_free (struct regf_data *data, uint32_t offset)
292
struct hbin_block *hbin;
294
SMB_ASSERT (offset > 0);
296
hbin = hbin_by_offset(data, offset, &rel_offset);
301
/* Get original size */
302
size = IVALS(hbin->data, rel_offset);
305
DEBUG(1, ("Trying to free already freed block at 0x%04x\n",
312
/* If the next block is free, merge into big free block */
313
if (rel_offset + size < hbin->offset_to_next) {
314
next_size = IVALS(hbin->data, rel_offset+size);
320
/* Write block size */
321
SIVALS(hbin->data, rel_offset, size);
325
* Store a data blob data was already stored, but has changed in size
326
* Will try to save it at the current location if possible, otherwise
327
* does a free + store */
328
static uint32_t hbin_store_resize(struct regf_data *data,
329
uint32_t orig_offset, DATA_BLOB blob)
332
struct hbin_block *hbin = hbin_by_offset(data, orig_offset,
337
int32_t possible_size;
340
SMB_ASSERT(orig_offset > 0);
343
return hbin_store(data, blob);
345
/* Get original size */
346
orig_size = -IVALS(hbin->data, rel_offset);
348
needed_size = blob.length + 4; /* Add int32 containing length */
349
needed_size = (needed_size + 7) & ~7; /* Align */
351
/* Fits into current allocated block */
352
if (orig_size >= needed_size) {
353
memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length);
354
/* If the difference in size is greater than 0x4, split the block
355
* and free/merge it */
356
if (orig_size - needed_size > 0x4) {
357
SIVALS(hbin->data, rel_offset, -needed_size);
358
SIVALS(hbin->data, rel_offset + needed_size,
359
needed_size-orig_size);
360
hbin_free(data, orig_offset + needed_size);
365
possible_size = orig_size;
367
/* Check if it can be combined with the next few free records */
368
for (i = rel_offset; i < hbin->offset_to_next - 0x20; i += my_size) {
369
if (IVALS(hbin->data, i) < 0) /* Used */
372
my_size = IVALS(hbin->data, i);
374
if (my_size == 0x0) {
375
DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
378
possible_size += my_size;
381
if (possible_size >= blob.length) {
382
SIVAL(hbin->data, rel_offset, -possible_size);
383
memcpy(hbin->data + rel_offset + 0x4,
384
blob.data, blob.length);
389
hbin_free(data, orig_offset);
390
return hbin_store(data, blob);
393
static uint32_t hbin_store_tdr_resize(struct regf_data *regf,
394
tdr_push_fn_t push_fn,
395
uint32_t orig_offset, void *p)
397
struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience);
400
if (NT_STATUS_IS_ERR(push_fn(push, p))) {
401
DEBUG(0, ("Error during push\n"));
405
ret = hbin_store_resize(regf, orig_offset, push->data);
412
static uint32_t regf_create_lh_hash(const char *name)
418
hash_name = strupper_talloc(NULL, name);
419
for (i = 0; *(hash_name + i) != 0; i++) {
421
ret += *(hash_name + i);
423
talloc_free(hash_name);
427
static WERROR regf_get_info(TALLOC_CTX *mem_ctx,
428
const struct hive_key *key,
429
const char **classname,
430
uint32_t *num_subkeys,
431
uint32_t *num_values,
432
NTTIME *last_mod_time,
433
uint32_t *max_subkeynamelen,
434
uint32_t *max_valnamelen,
435
uint32_t *max_valbufsize)
437
const struct regf_key_data *private_data =
438
(const struct regf_key_data *)key;
440
if (num_subkeys != NULL)
441
*num_subkeys = private_data->nk->num_subkeys;
443
if (num_values != NULL)
444
*num_values = private_data->nk->num_values;
446
if (classname != NULL) {
447
if (private_data->nk->clsname_offset != -1) {
448
DATA_BLOB data = hbin_get(private_data->hive,
449
private_data->nk->clsname_offset);
450
*classname = talloc_strndup(mem_ctx,
452
private_data->nk->clsname_length);
457
/* TODO: Last mod time */
459
/* TODO: max valnamelen */
461
/* TODO: max valbufsize */
463
/* TODO: max subkeynamelen */
468
static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx,
469
struct regf_data *regf,
473
struct regf_key_data *ret;
475
ret = talloc_zero(ctx, struct regf_key_data);
476
ret->key.ops = ®_backend_regf;
477
ret->hive = talloc_reference(ret, regf);
478
ret->offset = offset;
479
nk = talloc(ret, struct nk_block);
485
if (!hbin_get_tdr(regf, offset, nk,
486
(tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
487
DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
491
if (strcmp(nk->header, "nk") != 0) {
492
DEBUG(0, ("Expected nk record, got %s\n", nk->header));
501
static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key,
502
int idx, const char **name,
503
uint32_t *data_type, DATA_BLOB *data)
505
const struct regf_key_data *private_data =
506
(const struct regf_key_data *)key;
508
struct regf_data *regf = private_data->hive;
512
if (idx >= private_data->nk->num_values)
513
return WERR_NO_MORE_ITEMS;
515
tmp = hbin_get(regf, private_data->nk->values_offset);
517
DEBUG(0, ("Unable to find value list\n"));
518
return WERR_GENERAL_FAILURE;
521
if (tmp.length < private_data->nk->num_values * 4) {
522
DEBUG(1, ("Value counts mismatch\n"));
525
vk_offset = IVAL(tmp.data, idx * 4);
527
vk = talloc(NULL, struct vk_block);
528
W_ERROR_HAVE_NO_MEMORY(vk);
530
if (!hbin_get_tdr(regf, vk_offset, vk,
531
(tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
532
DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));
534
return WERR_GENERAL_FAILURE;
537
/* FIXME: name character set ?*/
539
*name = talloc_strndup(ctx, vk->data_name, vk->name_length);
541
if (data_type != NULL)
542
*data_type = vk->data_type;
544
if (vk->data_length & 0x80000000) {
545
vk->data_length &=~0x80000000;
546
data->data = (uint8_t *)talloc_memdup(ctx, (uint8_t *)&vk->data_offset, vk->data_length);
547
data->length = vk->data_length;
549
*data = hbin_get(regf, vk->data_offset);
552
if (data->length < vk->data_length) {
553
DEBUG(1, ("Read data less than indicated data length!\n"));
561
static WERROR regf_get_value_by_name(TALLOC_CTX *mem_ctx,
562
struct hive_key *key, const char *name,
563
uint32_t *type, DATA_BLOB *data)
569
/* FIXME: Do binary search? Is this list sorted at all? */
571
for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i,
572
&vname, type, data));
574
if (!strcmp(vname, name))
578
if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
585
static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx,
586
const struct hive_key *key,
587
uint32_t idx, const char **name,
588
const char **classname,
589
NTTIME *last_mod_time)
592
struct regf_key_data *ret;
593
const struct regf_key_data *private_data = (const struct regf_key_data *)key;
594
struct nk_block *nk = private_data->nk;
597
if (idx >= nk->num_subkeys)
598
return WERR_NO_MORE_ITEMS;
600
data = hbin_get(private_data->hive, nk->subkeys_offset);
602
DEBUG(0, ("Unable to find subkey list\n"));
603
return WERR_GENERAL_FAILURE;
606
if (!strncmp((char *)data.data, "li", 2)) {
608
struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
610
DEBUG(10, ("Subkeys in LI list\n"));
613
if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) {
614
DEBUG(0, ("Error parsing LI list\n"));
616
return WERR_GENERAL_FAILURE;
619
SMB_ASSERT(!strncmp(li.header, "li", 2));
621
if (li.key_count != nk->num_subkeys) {
622
DEBUG(0, ("Subkey counts don't match\n"));
623
return WERR_GENERAL_FAILURE;
625
key_off = li.nk_offset[idx];
627
} else if (!strncmp((char *)data.data, "lf", 2)) {
629
struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
631
DEBUG(10, ("Subkeys in LF list\n"));
634
if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) {
635
DEBUG(0, ("Error parsing LF list\n"));
637
return WERR_GENERAL_FAILURE;
640
SMB_ASSERT(!strncmp(lf.header, "lf", 2));
642
if (lf.key_count != nk->num_subkeys) {
643
DEBUG(0, ("Subkey counts don't match\n"));
644
return WERR_GENERAL_FAILURE;
647
key_off = lf.hr[idx].nk_offset;
648
} else if (!strncmp((char *)data.data, "lh", 2)) {
650
struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
652
DEBUG(10, ("Subkeys in LH list\n"));
655
if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) {
656
DEBUG(0, ("Error parsing LH list\n"));
658
return WERR_GENERAL_FAILURE;
661
SMB_ASSERT(!strncmp(lh.header, "lh", 2));
663
if (lh.key_count != nk->num_subkeys) {
664
DEBUG(0, ("Subkey counts don't match\n"));
665
return WERR_GENERAL_FAILURE;
667
key_off = lh.hr[idx].nk_offset;
668
} else if (!strncmp((char *)data.data, "ri", 2)) {
670
struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
672
uint16_t sublist_count = 0;
674
DEBUG(10, ("Subkeys in RI list\n"));
677
if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) {
678
DEBUG(0, ("Error parsing RI list\n"));
680
return WERR_GENERAL_FAILURE;
682
SMB_ASSERT(!strncmp(ri.header, "ri", 2));
684
for (i = 0; i < ri.key_count; i++) {
687
/* Get sublist data blob */
688
list_data = hbin_get(private_data->hive, ri.offset[i]);
689
if (!list_data.data) {
690
DEBUG(0, ("Error getting RI list."));
692
return WERR_GENERAL_FAILURE;
695
pull->data = list_data;
697
if (!strncmp((char *)list_data.data, "li", 2)) {
700
DEBUG(10, ("Subkeys in RI->LI list\n"));
702
if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull,
705
DEBUG(0, ("Error parsing LI list from RI\n"));
707
return WERR_GENERAL_FAILURE;
709
SMB_ASSERT(!strncmp(li.header, "li", 2));
711
/* Advance to next sublist if necessary */
712
if (idx >= sublist_count + li.key_count) {
713
sublist_count += li.key_count;
716
key_off = li.nk_offset[idx - sublist_count];
717
sublist_count += li.key_count;
719
} else if (!strncmp((char *)list_data.data, "lh", 2)) {
722
DEBUG(10, ("Subkeys in RI->LH list\n"));
724
if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull,
727
DEBUG(0, ("Error parsing LH list from RI\n"));
729
return WERR_GENERAL_FAILURE;
731
SMB_ASSERT(!strncmp(lh.header, "lh", 2));
733
/* Advance to next sublist if necessary */
734
if (idx >= sublist_count + lh.key_count) {
735
sublist_count += lh.key_count;
738
key_off = lh.hr[idx - sublist_count].nk_offset;
739
sublist_count += lh.key_count;
742
DEBUG(0,("Unknown sublist in ri block\n"));
745
return WERR_GENERAL_FAILURE;
752
if (idx > sublist_count) {
753
return WERR_NO_MORE_ITEMS;
757
DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n",
758
nk->subkeys_offset, data.data[0], data.data[1]));
759
return WERR_GENERAL_FAILURE;
762
ret = regf_get_key (ctx, private_data->hive, key_off);
764
if (classname != NULL) {
765
if (ret->nk->clsname_offset != -1) {
766
DATA_BLOB db = hbin_get(ret->hive,
767
ret->nk->clsname_offset);
768
*classname = talloc_strndup(ctx,
770
ret->nk->clsname_length);
775
if (last_mod_time != NULL)
776
*last_mod_time = ret->nk->last_change;
779
*name = talloc_steal(ctx, ret->nk->key_name);
786
static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx,
787
const struct hive_key *key,
789
const char *name, uint32_t *ret)
791
DATA_BLOB subkey_data;
792
struct nk_block subkey;
793
struct tdr_pull *pull;
794
const struct regf_key_data *private_data =
795
(const struct regf_key_data *)key;
797
subkey_data = hbin_get(private_data->hive, offset);
798
if (!subkey_data.data) {
799
DEBUG(0, ("Unable to retrieve subkey HBIN\n"));
800
return WERR_GENERAL_FAILURE;
803
pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
805
pull->data = subkey_data;
807
if (NT_STATUS_IS_ERR(tdr_pull_nk_block(pull, ctx, &subkey))) {
808
DEBUG(0, ("Error parsing NK structure.\n"));
810
return WERR_GENERAL_FAILURE;
814
if (strncmp(subkey.header, "nk", 2)) {
815
DEBUG(0, ("Not an NK structure.\n"));
816
return WERR_GENERAL_FAILURE;
819
if (!strcasecmp(subkey.key_name, name)) {
827
static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx,
828
const struct hive_key *key,
830
struct hive_key **ret)
833
const struct regf_key_data *private_data =
834
(const struct regf_key_data *)key;
835
struct nk_block *nk = private_data->nk;
836
uint32_t key_off = 0;
838
data = hbin_get(private_data->hive, nk->subkeys_offset);
840
DEBUG(0, ("Unable to find subkey list\n"));
841
return WERR_GENERAL_FAILURE;
844
if (!strncmp((char *)data.data, "li", 2)) {
846
struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
849
DEBUG(10, ("Subkeys in LI list\n"));
852
if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) {
853
DEBUG(0, ("Error parsing LI list\n"));
855
return WERR_GENERAL_FAILURE;
858
SMB_ASSERT(!strncmp(li.header, "li", 2));
860
if (li.key_count != nk->num_subkeys) {
861
DEBUG(0, ("Subkey counts don't match\n"));
862
return WERR_GENERAL_FAILURE;
865
for (i = 0; i < li.key_count; i++) {
866
W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
875
} else if (!strncmp((char *)data.data, "lf", 2)) {
877
struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
880
DEBUG(10, ("Subkeys in LF list\n"));
883
if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) {
884
DEBUG(0, ("Error parsing LF list\n"));
886
return WERR_GENERAL_FAILURE;
889
SMB_ASSERT(!strncmp(lf.header, "lf", 2));
891
if (lf.key_count != nk->num_subkeys) {
892
DEBUG(0, ("Subkey counts don't match\n"));
893
return WERR_GENERAL_FAILURE;
896
for (i = 0; i < lf.key_count; i++) {
897
if (strncmp(lf.hr[i].hash, name, 4)) {
900
W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
910
} else if (!strncmp((char *)data.data, "lh", 2)) {
912
struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
916
DEBUG(10, ("Subkeys in LH list\n"));
919
if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) {
920
DEBUG(0, ("Error parsing LH list\n"));
922
return WERR_GENERAL_FAILURE;
925
SMB_ASSERT(!strncmp(lh.header, "lh", 2));
927
if (lh.key_count != nk->num_subkeys) {
928
DEBUG(0, ("Subkey counts don't match\n"));
929
return WERR_GENERAL_FAILURE;
932
hash = regf_create_lh_hash(name);
933
for (i = 0; i < lh.key_count; i++) {
934
if (lh.hr[i].base37 != hash) {
937
W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
947
} else if (!strncmp((char *)data.data, "ri", 2)) {
949
struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
952
DEBUG(10, ("Subkeys in RI list\n"));
955
if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) {
956
DEBUG(0, ("Error parsing RI list\n"));
958
return WERR_GENERAL_FAILURE;
960
SMB_ASSERT(!strncmp(ri.header, "ri", 2));
962
for (i = 0; i < ri.key_count; i++) {
965
/* Get sublist data blob */
966
list_data = hbin_get(private_data->hive, ri.offset[i]);
967
if (list_data.data == NULL) {
968
DEBUG(0, ("Error getting RI list."));
970
return WERR_GENERAL_FAILURE;
973
pull->data = list_data;
975
if (!strncmp((char *)list_data.data, "li", 2)) {
978
if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull,
981
DEBUG(0, ("Error parsing LI list from RI\n"));
983
return WERR_GENERAL_FAILURE;
985
SMB_ASSERT(!strncmp(li.header, "li", 2));
987
for (j = 0; j < li.key_count; j++) {
988
W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
995
} else if (!strncmp((char *)list_data.data, "lh", 2)) {
999
if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull,
1002
DEBUG(0, ("Error parsing LH list from RI\n"));
1004
return WERR_GENERAL_FAILURE;
1006
SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1008
hash = regf_create_lh_hash(name);
1009
for (j = 0; j < lh.key_count; j++) {
1010
if (lh.hr[j].base37 != hash) {
1013
W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
1026
return WERR_BADFILE;
1028
DEBUG(0, ("Unknown subkey list type.\n"));
1029
return WERR_GENERAL_FAILURE;
1032
*ret = (struct hive_key *)regf_get_key(ctx, private_data->hive,
1037
static WERROR regf_set_sec_desc(struct hive_key *key,
1038
const struct security_descriptor *sec_desc)
1040
const struct regf_key_data *private_data =
1041
(const struct regf_key_data *)key;
1042
struct sk_block cur_sk, sk, new_sk;
1043
struct regf_data *regf = private_data->hive;
1044
struct nk_block root;
1046
uint32_t sk_offset, cur_sk_offset;
1047
bool update_cur_sk = false;
1049
/* Get the root nk */
1050
hbin_get_tdr(regf, regf->header->data_offset, regf,
1051
(tdr_pull_fn_t) tdr_pull_nk_block, &root);
1053
/* Push the security descriptor to a blob */
1054
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL,
1055
sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
1056
DEBUG(0, ("Unable to push security descriptor\n"));
1057
return WERR_GENERAL_FAILURE;
1060
/* Get the current security descriptor for the key */
1061
if (!hbin_get_tdr(regf, private_data->nk->sk_offset, regf,
1062
(tdr_pull_fn_t) tdr_pull_sk_block, &cur_sk)) {
1063
DEBUG(0, ("Unable to find security descriptor for current key\n"));
1064
return WERR_BADFILE;
1066
/* If there's no change, change nothing. */
1067
if (memcmp(data.data, cur_sk.sec_desc,
1068
MIN(data.length, cur_sk.rec_size)) == 0) {
1072
/* Delete the current sk if only this key is using it */
1073
if (cur_sk.ref_cnt == 1) {
1074
/* Get the previous security descriptor for the key */
1075
if (!hbin_get_tdr(regf, cur_sk.prev_offset, regf,
1076
(tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1077
DEBUG(0, ("Unable to find prev security descriptor for current key\n"));
1078
return WERR_BADFILE;
1080
/* Change and store the previous security descriptor */
1081
sk.next_offset = cur_sk.next_offset;
1082
hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block,
1083
cur_sk.prev_offset, &sk);
1085
/* Get the next security descriptor for the key */
1086
if (!hbin_get_tdr(regf, cur_sk.next_offset, regf,
1087
(tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1088
DEBUG(0, ("Unable to find next security descriptor for current key\n"));
1089
return WERR_BADFILE;
1091
/* Change and store the next security descriptor */
1092
sk.prev_offset = cur_sk.prev_offset;
1093
hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block,
1094
cur_sk.next_offset, &sk);
1096
hbin_free(regf, private_data->nk->sk_offset);
1098
/* This key will no longer be referring to this sk */
1100
update_cur_sk = true;
1103
sk_offset = root.sk_offset;
1106
cur_sk_offset = sk_offset;
1107
if (!hbin_get_tdr(regf, sk_offset, regf,
1108
(tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1109
DEBUG(0, ("Unable to find security descriptor\n"));
1110
return WERR_BADFILE;
1112
if (memcmp(data.data, sk.sec_desc, MIN(data.length, sk.rec_size)) == 0) {
1113
private_data->nk->sk_offset = sk_offset;
1115
hbin_store_tdr_resize(regf,
1116
(tdr_push_fn_t) tdr_push_sk_block,
1118
hbin_store_tdr_resize(regf,
1119
(tdr_push_fn_t) tdr_push_nk_block,
1120
private_data->offset,
1124
sk_offset = sk.next_offset;
1125
} while (sk_offset != root.sk_offset);
1127
ZERO_STRUCT(new_sk);
1128
new_sk.header = "sk";
1129
new_sk.prev_offset = cur_sk_offset;
1130
new_sk.next_offset = root.sk_offset;
1132
new_sk.rec_size = data.length;
1133
new_sk.sec_desc = data.data;
1135
sk_offset = hbin_store_tdr(regf,
1136
(tdr_push_fn_t) tdr_push_sk_block,
1138
if (sk_offset == -1) {
1139
DEBUG(0, ("Error storing sk block\n"));
1140
return WERR_GENERAL_FAILURE;
1142
private_data->nk->sk_offset = sk_offset;
1144
if (update_cur_sk) {
1145
hbin_store_tdr_resize(regf,
1146
(tdr_push_fn_t) tdr_push_sk_block,
1147
private_data->nk->sk_offset, &cur_sk);
1150
/* Get the previous security descriptor for the key */
1151
if (!hbin_get_tdr(regf, new_sk.prev_offset, regf,
1152
(tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1153
DEBUG(0, ("Unable to find security descriptor for previous key\n"));
1154
return WERR_BADFILE;
1156
/* Change and store the previous security descriptor */
1157
sk.next_offset = sk_offset;
1158
hbin_store_tdr_resize(regf,
1159
(tdr_push_fn_t) tdr_push_sk_block,
1160
cur_sk.prev_offset, &sk);
1162
/* Get the next security descriptor for the key (always root, as we append) */
1163
if (!hbin_get_tdr(regf, new_sk.next_offset, regf,
1164
(tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1165
DEBUG(0, ("Unable to find security descriptor for current key\n"));
1166
return WERR_BADFILE;
1168
/* Change and store the next security descriptor (always root, as we append) */
1169
sk.prev_offset = sk_offset;
1170
hbin_store_tdr_resize(regf,
1171
(tdr_push_fn_t) tdr_push_sk_block,
1172
root.sk_offset, &sk);
1176
hbin_store_tdr_resize(regf,
1177
(tdr_push_fn_t) tdr_push_sk_block,
1178
private_data->offset, private_data->nk);
1182
static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key,
1183
struct security_descriptor **sd)
1185
const struct regf_key_data *private_data =
1186
(const struct regf_key_data *)key;
1188
struct regf_data *regf = private_data->hive;
1191
if (!hbin_get_tdr(regf, private_data->nk->sk_offset, ctx,
1192
(tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1193
DEBUG(0, ("Unable to find security descriptor\n"));
1194
return WERR_GENERAL_FAILURE;
1197
if (strcmp(sk.header, "sk") != 0) {
1198
DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header));
1199
return WERR_GENERAL_FAILURE;
1202
*sd = talloc(ctx, struct security_descriptor);
1203
W_ERROR_HAVE_NO_MEMORY(*sd);
1205
data.data = sk.sec_desc;
1206
data.length = sk.rec_size;
1207
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, NULL, *sd,
1208
(ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) {
1209
DEBUG(0, ("Error parsing security descriptor\n"));
1210
return WERR_GENERAL_FAILURE;
1216
static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset,
1218
uint32_t key_offset, uint32_t *ret)
1222
/* Create a new key if necessary */
1223
if (list_offset == -1) {
1224
if (regf->header->version.major != 1) {
1225
DEBUG(0, ("Can't store keys in unknown registry format\n"));
1226
return WERR_NOT_SUPPORTED;
1228
if (regf->header->version.minor < 3) {
1235
li.nk_offset = talloc_array(regf, uint32_t, 1);
1236
W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1237
li.nk_offset[0] = key_offset;
1239
*ret = hbin_store_tdr(regf,
1240
(tdr_push_fn_t) tdr_push_li_block,
1243
talloc_free(li.nk_offset);
1244
} else if (regf->header->version.minor == 3 ||
1245
regf->header->version.minor == 4) {
1252
lf.hr = talloc_array(regf, struct hash_record, 1);
1253
W_ERROR_HAVE_NO_MEMORY(lf.hr);
1254
lf.hr[0].nk_offset = key_offset;
1255
lf.hr[0].hash = talloc_strndup(lf.hr, name, 4);
1256
W_ERROR_HAVE_NO_MEMORY(lf.hr[0].hash);
1258
*ret = hbin_store_tdr(regf,
1259
(tdr_push_fn_t) tdr_push_lf_block,
1263
} else if (regf->header->version.minor == 5) {
1270
lh.hr = talloc_array(regf, struct lh_hash, 1);
1271
W_ERROR_HAVE_NO_MEMORY(lh.hr);
1272
lh.hr[0].nk_offset = key_offset;
1273
lh.hr[0].base37 = regf_create_lh_hash(name);
1275
*ret = hbin_store_tdr(regf,
1276
(tdr_push_fn_t) tdr_push_lh_block,
1284
data = hbin_get(regf, list_offset);
1286
DEBUG(0, ("Unable to find subkey list\n"));
1287
return WERR_BADFILE;
1290
if (!strncmp((char *)data.data, "li", 2)) {
1291
struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1296
if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) {
1297
DEBUG(0, ("Error parsing LI list\n"));
1299
return WERR_BADFILE;
1303
if (strncmp(li.header, "li", 2) != 0) {
1305
DEBUG(0, ("LI header corrupt\n"));
1306
return WERR_BADFILE;
1309
li.nk_offset = talloc_realloc(regf, li.nk_offset,
1310
uint32_t, li.key_count+1);
1311
W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1312
li.nk_offset[li.key_count] = key_offset;
1314
*ret = hbin_store_tdr_resize(regf,
1315
(tdr_push_fn_t)tdr_push_li_block,
1318
talloc_free(li.nk_offset);
1319
} else if (!strncmp((char *)data.data, "lf", 2)) {
1320
struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1325
if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) {
1326
DEBUG(0, ("Error parsing LF list\n"));
1328
return WERR_BADFILE;
1331
SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1333
lf.hr = talloc_realloc(regf, lf.hr, struct hash_record,
1335
W_ERROR_HAVE_NO_MEMORY(lf.hr);
1336
lf.hr[lf.key_count].nk_offset = key_offset;
1337
lf.hr[lf.key_count].hash = talloc_strndup(lf.hr, name, 4);
1338
W_ERROR_HAVE_NO_MEMORY(lf.hr[lf.key_count].hash);
1340
*ret = hbin_store_tdr_resize(regf,
1341
(tdr_push_fn_t)tdr_push_lf_block,
1345
} else if (!strncmp((char *)data.data, "lh", 2)) {
1346
struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1351
if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) {
1352
DEBUG(0, ("Error parsing LH list\n"));
1354
return WERR_BADFILE;
1357
SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1359
lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash,
1361
W_ERROR_HAVE_NO_MEMORY(lh.hr);
1362
lh.hr[lh.key_count].nk_offset = key_offset;
1363
lh.hr[lh.key_count].base37 = regf_create_lh_hash(name);
1365
*ret = hbin_store_tdr_resize(regf,
1366
(tdr_push_fn_t)tdr_push_lh_block,
1370
} else if (!strncmp((char *)data.data, "ri", 2)) {
1372
DEBUG(0, ("Adding to 'ri' subkey list is not supported yet.\n"));
1373
return WERR_NOT_SUPPORTED;
1375
DEBUG(0, ("Cannot add to unknown subkey list\n"));
1376
return WERR_BADFILE;
1382
static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset,
1383
uint32_t key_offset, uint32_t *ret)
1387
data = hbin_get(regf, list_offset);
1389
DEBUG(0, ("Unable to find subkey list\n"));
1390
return WERR_BADFILE;
1393
if (strncmp((char *)data.data, "li", 2) == 0) {
1395
struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1397
bool found_offset = false;
1399
DEBUG(10, ("Subkeys in LI list\n"));
1403
if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) {
1404
DEBUG(0, ("Error parsing LI list\n"));
1406
return WERR_BADFILE;
1410
SMB_ASSERT(!strncmp(li.header, "li", 2));
1412
for (i = 0; i < li.key_count; i++) {
1414
li.nk_offset[i-1] = li.nk_offset[i];
1416
if (li.nk_offset[i] == key_offset) {
1417
found_offset = true;
1421
if (!found_offset) {
1422
DEBUG(2, ("Subkey not found\n"));
1423
return WERR_BADFILE;
1427
/* If the there are no entries left, free the subkey list */
1428
if (li.key_count == 0) {
1429
hbin_free(regf, list_offset);
1433
/* Store li block */
1434
*ret = hbin_store_tdr_resize(regf,
1435
(tdr_push_fn_t) tdr_push_li_block,
1437
} else if (strncmp((char *)data.data, "lf", 2) == 0) {
1439
struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1441
bool found_offset = false;
1443
DEBUG(10, ("Subkeys in LF list\n"));
1447
if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) {
1448
DEBUG(0, ("Error parsing LF list\n"));
1450
return WERR_BADFILE;
1454
SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1456
for (i = 0; i < lf.key_count; i++) {
1458
lf.hr[i-1] = lf.hr[i];
1461
if (lf.hr[i].nk_offset == key_offset) {
1466
if (!found_offset) {
1467
DEBUG(2, ("Subkey not found\n"));
1468
return WERR_BADFILE;
1472
/* If the there are no entries left, free the subkey list */
1473
if (lf.key_count == 0) {
1474
hbin_free(regf, list_offset);
1479
/* Store lf block */
1480
*ret = hbin_store_tdr_resize(regf,
1481
(tdr_push_fn_t) tdr_push_lf_block,
1483
} else if (strncmp((char *)data.data, "lh", 2) == 0) {
1485
struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
1487
bool found_offset = false;
1489
DEBUG(10, ("Subkeys in LH list\n"));
1493
if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) {
1494
DEBUG(0, ("Error parsing LF list\n"));
1496
return WERR_BADFILE;
1500
SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1502
for (i = 0; i < lh.key_count; i++) {
1504
lh.hr[i-1] = lh.hr[i];
1507
if (lh.hr[i].nk_offset == key_offset) {
1512
if (!found_offset) {
1513
DEBUG(0, ("Subkey not found\n"));
1514
return WERR_BADFILE;
1518
/* If the there are no entries left, free the subkey list */
1519
if (lh.key_count == 0) {
1520
hbin_free(regf, list_offset);
1525
/* Store lh block */
1526
*ret = hbin_store_tdr_resize(regf,
1527
(tdr_push_fn_t) tdr_push_lh_block,
1529
} else if (strncmp((char *)data.data, "ri", 2) == 0) {
1531
DEBUG(0, ("Sorry, deletion from ri block is not supported yet.\n"));
1532
return WERR_NOT_SUPPORTED;
1534
DEBUG (0, ("Unknown header found in subkey list.\n"));
1535
return WERR_BADFILE;
1540
static WERROR regf_del_value (struct hive_key *key, const char *name)
1542
struct regf_key_data *private_data = (struct regf_key_data *)key;
1543
struct regf_data *regf = private_data->hive;
1544
struct nk_block *nk = private_data->nk;
1547
bool found_offset = false;
1551
if (nk->values_offset == -1) {
1552
return WERR_BADFILE;
1555
values = hbin_get(regf, nk->values_offset);
1557
for (i = 0; i < nk->num_values; i++) {
1559
((uint32_t *)values.data)[i-1] = ((uint32_t *) values.data)[i];
1561
vk_offset = IVAL(values.data, i * 4);
1562
if (!hbin_get_tdr(regf, vk_offset, private_data,
1563
(tdr_pull_fn_t)tdr_pull_vk_block,
1565
DEBUG(0, ("Unable to get VK block at %d\n",
1567
return WERR_BADFILE;
1569
if (strcmp(vk.data_name, name) == 0) {
1570
hbin_free(regf, vk_offset);
1571
found_offset = true;
1575
if (!found_offset) {
1576
return WERR_BADFILE;
1579
values.length = (nk->num_values)*4;
1582
/* Store values list and nk */
1583
if (nk->num_values == 0) {
1584
hbin_free(regf, nk->values_offset);
1585
nk->values_offset = -1;
1587
nk->values_offset = hbin_store_resize(regf,
1591
hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
1592
private_data->offset, nk);
1594
return regf_save_hbin(private_data->hive);
1598
static WERROR regf_del_key(const struct hive_key *parent, const char *name)
1600
const struct regf_key_data *private_data =
1601
(const struct regf_key_data *)parent;
1602
struct regf_key_data *key;
1603
struct nk_block *parent_nk;
1606
SMB_ASSERT(private_data);
1608
parent_nk = private_data->nk;
1610
if (parent_nk->subkeys_offset == -1) {
1611
DEBUG(4, ("Subkey list is empty, this key cannot contain subkeys.\n"));
1612
return WERR_BADFILE;
1616
if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name,
1617
(struct hive_key **)&key))) {
1618
DEBUG(2, ("Key '%s' not found\n", name));
1619
return WERR_BADFILE;
1622
if (key->nk->subkeys_offset != -1) {
1624
struct hive_key *sk = (struct hive_key *)key;
1625
int i = key->nk->num_subkeys;
1627
/* Get subkey information. */
1628
error = regf_get_subkey_by_index(parent_nk, sk, 0,
1629
(const char **)&sk_name,
1631
if (!W_ERROR_IS_OK(error)) {
1632
DEBUG(0, ("Can't retrieve subkey by index.\n"));
1636
/* Delete subkey. */
1637
error = regf_del_key(sk, sk_name);
1638
if (!W_ERROR_IS_OK(error)) {
1639
DEBUG(0, ("Can't delete key '%s'.\n", sk_name));
1643
talloc_free(sk_name);
1647
if (key->nk->values_offset != -1) {
1649
struct hive_key *sk = (struct hive_key *)key;
1651
int i = key->nk->num_values;
1653
/* Get value information. */
1654
error = regf_get_value(parent_nk, sk, 0,
1655
(const char **)&val_name,
1657
if (!W_ERROR_IS_OK(error)) {
1658
DEBUG(0, ("Can't retrieve value by index.\n"));
1663
error = regf_del_value(sk, val_name);
1664
if (!W_ERROR_IS_OK(error)) {
1665
DEBUG(0, ("Can't delete value '%s'.\n", val_name));
1669
talloc_free(val_name);
1673
/* Delete it from the subkey list. */
1674
error = regf_sl_del_entry(private_data->hive, parent_nk->subkeys_offset,
1675
key->offset, &parent_nk->subkeys_offset);
1676
if (!W_ERROR_IS_OK(error)) {
1677
DEBUG(0, ("Can't store new subkey list for parent key. Won't delete.\n"));
1681
/* Re-store parent key */
1682
parent_nk->num_subkeys--;
1683
hbin_store_tdr_resize(private_data->hive,
1684
(tdr_push_fn_t) tdr_push_nk_block,
1685
private_data->offset, parent_nk);
1687
if (key->nk->clsname_offset != -1) {
1688
hbin_free(private_data->hive, key->nk->clsname_offset);
1690
hbin_free(private_data->hive, key->offset);
1692
return regf_save_hbin(private_data->hive);
1695
static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent,
1696
const char *name, const char *classname,
1697
struct security_descriptor *sec_desc,
1698
struct hive_key **ret)
1700
const struct regf_key_data *private_data =
1701
(const struct regf_key_data *)parent;
1702
struct nk_block *parent_nk = private_data->nk, nk;
1703
struct nk_block *root;
1704
struct regf_data *regf = private_data->hive;
1709
nk.type = REG_SUB_KEY;
1710
unix_to_nt_time(&nk.last_change, time(NULL));
1712
nk.parent_offset = private_data->offset;
1715
nk.subkeys_offset = -1;
1716
nk.unknown_offset = -1;
1718
nk.values_offset = -1;
1719
memset(nk.unk3, 0, 5);
1720
nk.clsname_offset = -1; /* FIXME: fill in */
1721
nk.clsname_length = 0;
1724
/* Get the security descriptor of the root key */
1725
root = talloc_zero(ctx, struct nk_block);
1726
W_ERROR_HAVE_NO_MEMORY(root);
1728
if (!hbin_get_tdr(regf, regf->header->data_offset, root,
1729
(tdr_pull_fn_t)tdr_pull_nk_block, root)) {
1730
DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
1731
return WERR_GENERAL_FAILURE;
1733
nk.sk_offset = root->sk_offset;
1736
/* Store the new nk key */
1737
offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk);
1739
error = regf_sl_add_entry(regf, parent_nk->subkeys_offset, name, offset,
1740
&parent_nk->subkeys_offset);
1741
if (!W_ERROR_IS_OK(error)) {
1742
hbin_free(regf, offset);
1746
parent_nk->num_subkeys++;
1748
/* Since the subkey offset of the parent can change, store it again */
1749
hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
1750
nk.parent_offset, parent_nk);
1752
*ret = (struct hive_key *)regf_get_key(ctx, regf, offset);
1754
return regf_save_hbin(private_data->hive);
1757
static WERROR regf_set_value(struct hive_key *key, const char *name,
1758
uint32_t type, const DATA_BLOB data)
1760
struct regf_key_data *private_data = (struct regf_key_data *)key;
1761
struct regf_data *regf = private_data->hive;
1762
struct nk_block *nk = private_data->nk;
1765
uint32_t tmp_vk_offset, vk_offset, old_vk_offset = -1;
1770
/* find the value offset, if it exists */
1771
if (nk->values_offset != -1) {
1772
values = hbin_get(regf, nk->values_offset);
1774
for (i = 0; i < nk->num_values; i++) {
1775
tmp_vk_offset = IVAL(values.data, i * 4);
1776
if (!hbin_get_tdr(regf, tmp_vk_offset, private_data,
1777
(tdr_pull_fn_t)tdr_pull_vk_block,
1779
DEBUG(0, ("Unable to get VK block at %d\n",
1781
return WERR_GENERAL_FAILURE;
1783
if (strcmp(vk.data_name, name) == 0) {
1784
old_vk_offset = tmp_vk_offset;
1788
/* Free data, if any */
1789
if (!(vk.data_length & 0x80000000)) {
1790
hbin_free(regf, vk.data_offset);
1793
if (old_vk_offset == -1) {
1795
vk.name_length = strlen(name);
1796
if (name != NULL && name[0] != 0) {
1798
vk.data_name = name;
1800
vk.data_name = NULL;
1804
/* Set the type and data */
1805
vk.data_length = data.length;
1806
vk.data_type = type;
1807
if (type == REG_DWORD) {
1808
vk.data_length |= 0x80000000;
1809
vk.data_offset = *(uint32_t *)data.data;
1811
/* Store data somewhere */
1812
vk.data_offset = hbin_store(regf, data);
1814
if (old_vk_offset == -1) {
1816
vk_offset = hbin_store_tdr(regf,
1817
(tdr_push_fn_t) tdr_push_vk_block,
1820
/* Store vk at offset */
1821
vk_offset = hbin_store_tdr_resize(regf,
1822
(tdr_push_fn_t) tdr_push_vk_block,
1823
old_vk_offset ,&vk);
1826
/* Re-allocate the value list */
1827
if (nk->values_offset == -1) {
1828
nk->values_offset = hbin_store_tdr(regf,
1829
(tdr_push_fn_t) tdr_push_uint32,
1834
/* Change if we're changing, otherwise we're adding the value */
1835
if (old_vk_offset != -1) {
1836
/* Find and overwrite the offset. */
1837
for (i = 0; i < nk->num_values; i++) {
1838
if (IVAL(values.data, i * 4) == old_vk_offset) {
1839
SIVAL(values.data, i * 4, vk_offset);
1844
/* Create a new value list */
1845
DATA_BLOB value_list;
1847
value_list.length = (nk->num_values+1)*4;
1848
value_list.data = (uint8_t *)talloc_array(private_data,
1851
W_ERROR_HAVE_NO_MEMORY(value_list.data);
1852
memcpy(value_list.data, values.data, nk->num_values * 4);
1854
SIVAL(value_list.data, nk->num_values * 4, vk_offset);
1856
nk->values_offset = hbin_store_resize(regf,
1862
hbin_store_tdr_resize(regf,
1863
(tdr_push_fn_t) tdr_push_nk_block,
1864
private_data->offset, nk);
1865
return regf_save_hbin(private_data->hive);
1868
static WERROR regf_save_hbin(struct regf_data *regf)
1870
struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience);
1873
W_ERROR_HAVE_NO_MEMORY(push);
1875
if (lseek(regf->fd, 0, SEEK_SET) == -1) {
1876
DEBUG(0, ("Error lseeking in regf file\n"));
1877
return WERR_GENERAL_FAILURE;
1880
/* Recompute checksum */
1881
if (NT_STATUS_IS_ERR(tdr_push_regf_hdr(push, regf->header))) {
1882
DEBUG(0, ("Failed to push regf header\n"));
1883
return WERR_GENERAL_FAILURE;
1885
regf->header->chksum = regf_hdr_checksum(push->data.data);
1888
if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience,
1889
(tdr_push_fn_t)tdr_push_regf_hdr,
1891
DEBUG(0, ("Error writing registry file header\n"));
1892
return WERR_GENERAL_FAILURE;
1895
if (lseek(regf->fd, 0x1000, SEEK_SET) == -1) {
1896
DEBUG(0, ("Error lseeking to 0x1000 in regf file\n"));
1897
return WERR_GENERAL_FAILURE;
1900
for (i = 0; regf->hbins[i]; i++) {
1901
if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience,
1902
(tdr_push_fn_t)tdr_push_hbin_block,
1904
DEBUG(0, ("Error writing HBIN block\n"));
1905
return WERR_GENERAL_FAILURE;
1912
WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx,
1913
struct smb_iconv_convenience *iconv_convenience,
1914
const char *location,
1915
int minor_version, struct hive_key **key)
1917
struct regf_data *regf;
1918
struct regf_hdr *regf_hdr;
1923
struct security_descriptor *sd;
1926
regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
1928
regf->iconv_convenience = iconv_convenience;
1930
W_ERROR_HAVE_NO_MEMORY(regf);
1932
DEBUG(5, ("Attempting to create registry file\n"));
1934
/* Get the header */
1935
regf->fd = creat(location, 0644);
1937
if (regf->fd == -1) {
1938
DEBUG(0,("Could not create file: %s, %s\n", location,
1941
return WERR_GENERAL_FAILURE;
1944
regf_hdr = talloc_zero(regf, struct regf_hdr);
1945
W_ERROR_HAVE_NO_MEMORY(regf_hdr);
1946
regf_hdr->REGF_ID = "regf";
1947
unix_to_nt_time(®f_hdr->modtime, time(NULL));
1948
regf_hdr->version.major = 1;
1949
regf_hdr->version.minor = minor_version;
1950
regf_hdr->last_block = 0x1000; /* Block size */
1951
regf_hdr->description = talloc_strdup(regf_hdr,
1952
"Registry created by Samba 4");
1953
W_ERROR_HAVE_NO_MEMORY(regf_hdr->description);
1954
regf_hdr->chksum = 0;
1956
regf->header = regf_hdr;
1958
/* Create all hbin blocks */
1959
regf->hbins = talloc_array(regf, struct hbin_block *, 1);
1960
W_ERROR_HAVE_NO_MEMORY(regf->hbins);
1961
regf->hbins[0] = NULL;
1964
nk.type = REG_SUB_KEY;
1965
unix_to_nt_time(&nk.last_change, time(NULL));
1967
nk.parent_offset = -1;
1970
nk.subkeys_offset = -1;
1971
nk.unknown_offset = -1;
1973
nk.values_offset = -1;
1974
memset(nk.unk3, 0, 5);
1975
nk.clsname_offset = -1;
1976
nk.clsname_length = 0;
1977
nk.sk_offset = 0x80;
1978
nk.key_name = "SambaRootKey";
1981
* It should be noted that changing the key_name to something shorter
1982
* creates a shorter nk block, which makes the position of the sk block
1983
* change. All Windows registries I've seen have the sk at 0x80.
1984
* I therefore recommend that our regf files share that offset -- Wilco
1987
/* Create a security descriptor. */
1988
sd = security_descriptor_dacl_create(regf,
1991
SID_NT_AUTHENTICATED_USERS,
1992
SEC_ACE_TYPE_ACCESS_ALLOWED,
1994
SEC_ACE_FLAG_OBJECT_INHERIT,
1997
/* Push the security descriptor to a blob */
1998
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf, NULL,
1999
sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
2000
DEBUG(0, ("Unable to push security descriptor\n"));
2001
return WERR_GENERAL_FAILURE;
2006
sk.prev_offset = 0x80;
2007
sk.next_offset = 0x80;
2009
sk.rec_size = data.length;
2010
sk.sec_desc = data.data;
2012
/* Store the new nk key */
2013
regf->header->data_offset = hbin_store_tdr(regf,
2014
(tdr_push_fn_t)tdr_push_nk_block,
2016
/* Store the sk block */
2017
sk_offset = hbin_store_tdr(regf,
2018
(tdr_push_fn_t) tdr_push_sk_block,
2020
if (sk_offset != 0x80) {
2021
DEBUG(0, ("Error storing sk block, should be at 0x80, stored at 0x%x\n", nk.sk_offset));
2022
return WERR_GENERAL_FAILURE;
2026
*key = (struct hive_key *)regf_get_key(parent_ctx, regf,
2027
regf->header->data_offset);
2029
error = regf_save_hbin(regf);
2030
if (!W_ERROR_IS_OK(error)) {
2034
/* We can drop our own reference now that *key will have created one */
2040
WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location,
2041
struct smb_iconv_convenience *iconv_convenience, struct hive_key **key)
2043
struct regf_data *regf;
2044
struct regf_hdr *regf_hdr;
2045
struct tdr_pull *pull;
2048
regf = (struct regf_data *)talloc_zero(parent_ctx, struct regf_data);
2050
regf->iconv_convenience = iconv_convenience;
2052
W_ERROR_HAVE_NO_MEMORY(regf);
2054
DEBUG(5, ("Attempting to load registry file\n"));
2056
/* Get the header */
2057
regf->fd = open(location, O_RDWR);
2059
if (regf->fd == -1) {
2060
DEBUG(0,("Could not load file: %s, %s\n", location,
2063
return WERR_GENERAL_FAILURE;
2066
pull = tdr_pull_init(regf, regf->iconv_convenience);
2068
pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, 0, regf);
2070
if (pull->data.data == NULL) {
2071
DEBUG(0, ("Error reading data\n"));
2073
return WERR_GENERAL_FAILURE;
2076
regf_hdr = talloc(regf, struct regf_hdr);
2077
W_ERROR_HAVE_NO_MEMORY(regf_hdr);
2079
if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr, regf_hdr))) {
2081
return WERR_GENERAL_FAILURE;
2084
regf->header = regf_hdr;
2086
if (strcmp(regf_hdr->REGF_ID, "regf") != 0) {
2087
DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n",
2088
regf_hdr->REGF_ID, location));
2090
return WERR_GENERAL_FAILURE;
2093
/* Validate the header ... */
2094
if (regf_hdr_checksum(pull->data.data) != regf_hdr->chksum) {
2095
DEBUG(0, ("Registry file checksum error: %s: %d,%d\n",
2096
location, regf_hdr->chksum,
2097
regf_hdr_checksum(pull->data.data)));
2099
return WERR_GENERAL_FAILURE;
2102
pull->offset = 0x1000;
2105
/* Read in all hbin blocks */
2106
regf->hbins = talloc_array(regf, struct hbin_block *, 1);
2107
W_ERROR_HAVE_NO_MEMORY(regf->hbins);
2109
regf->hbins[0] = NULL;
2111
while (pull->offset < pull->data.length &&
2112
pull->offset <= regf->header->last_block) {
2113
struct hbin_block *hbin = talloc(regf->hbins,
2116
W_ERROR_HAVE_NO_MEMORY(hbin);
2118
if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(pull, hbin, hbin))) {
2119
DEBUG(0, ("[%d] Error parsing HBIN block\n", i));
2124
if (strcmp(hbin->HBIN_ID, "hbin") != 0) {
2125
DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n",
2131
regf->hbins[i] = hbin;
2133
regf->hbins = talloc_realloc(regf, regf->hbins,
2134
struct hbin_block *, i+2);
2135
regf->hbins[i] = NULL;
2140
DEBUG(1, ("%d HBIN blocks read\n", i));
2142
*key = (struct hive_key *)regf_get_key(parent_ctx, regf,
2143
regf->header->data_offset);
2145
/* We can drop our own reference now that *key will have created one */
2151
static struct hive_operations reg_backend_regf = {
2153
.get_key_info = regf_get_info,
2154
.enum_key = regf_get_subkey_by_index,
2155
.get_key_by_name = regf_get_subkey_by_name,
2156
.get_value_by_name = regf_get_value_by_name,
2157
.enum_value = regf_get_value,
2158
.get_sec_desc = regf_get_sec_desc,
2159
.set_sec_desc = regf_set_sec_desc,
2160
.add_key = regf_add_key,
2161
.set_value = regf_set_value,
2162
.del_key = regf_del_key,
2163
.delete_value = regf_del_value,