source: vendor/current/source4/lib/registry/regf.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 58.5 KB
Line 
1/*
2 Samba CIFS implementation
3 Registry backend for REGF files
4 Copyright (C) 2005-2007 Jelmer Vernooij, jelmer@samba.org
5 Copyright (C) 2006-2010 Wilco Baan Hofman, wilco@baanhofman.nl
6
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.
11
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.
16
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/>. */
19
20#include "includes.h"
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"
28
29
30static struct hive_operations reg_backend_regf;
31
32/**
33 * There are several places on the web where the REGF format is explained;
34 *
35 * TODO: Links
36 */
37
38/* TODO:
39 * - Return error codes that make more sense
40 * - Locking
41 * - do more things in-memory
42 */
43
44/*
45 * Read HBIN blocks into memory
46 */
47
48struct regf_data {
49 int fd;
50 struct hbin_block **hbins;
51 struct regf_hdr *header;
52 time_t last_write;
53};
54
55static WERROR regf_save_hbin(struct regf_data *data, bool flush);
56
57struct regf_key_data {
58 struct hive_key key;
59 struct regf_data *hive;
60 uint32_t offset;
61 struct nk_block *nk;
62};
63
64static struct hbin_block *hbin_by_offset(const struct regf_data *data,
65 uint32_t offset, uint32_t *rel_offset)
66{
67 unsigned int i;
68
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];
76 }
77 }
78
79 return NULL;
80}
81
82/**
83 * Validate a regf header
84 * For now, do nothing, but we should check the checksum
85 */
86static uint32_t regf_hdr_checksum(const uint8_t *buffer)
87{
88 uint32_t checksum = 0, x;
89 unsigned int i;
90
91 for (i = 0; i < 0x01FB; i+= 4) {
92 x = IVAL(buffer, i);
93 checksum ^= x;
94 }
95
96 return checksum;
97}
98
99/**
100 * Obtain the contents of a HBIN block
101 */
102static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset)
103{
104 DATA_BLOB ret;
105 struct hbin_block *hbin;
106 uint32_t rel_offset;
107
108 ret.data = NULL;
109 ret.length = 0;
110
111 hbin = hbin_by_offset(data, offset, &rel_offset);
112
113 if (hbin == NULL) {
114 DEBUG(1, ("Can't find HBIN at 0x%04x\n", offset));
115 return ret;
116 }
117
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));
121 return ret;
122 }
123
124 /* remove high bit */
125 ret.length = (ret.length ^ 0xffffffff) + 1;
126
127 ret.length -= 4; /* 4 bytes for the length... */
128 ret.data = hbin->data +
129 (offset - hbin->offset_from_first - 0x20) + 4;
130
131 return ret;
132}
133
134static bool hbin_get_tdr(struct regf_data *regf, uint32_t offset,
135 TALLOC_CTX *ctx, tdr_pull_fn_t pull_fn, void *p)
136{
137 struct tdr_pull *pull = tdr_pull_init(regf);
138
139 pull->data = hbin_get(regf, offset);
140 if (!pull->data.data) {
141 DEBUG(1, ("Unable to get data at 0x%04x\n", offset));
142 talloc_free(pull);
143 return false;
144 }
145
146 if (NT_STATUS_IS_ERR(pull_fn(pull, ctx, p))) {
147 DEBUG(1, ("Error parsing record at 0x%04x using tdr\n",
148 offset));
149 talloc_free(pull);
150 return false;
151 }
152 talloc_free(pull);
153
154 return true;
155}
156
157/* Allocate some new data */
158static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size,
159 uint32_t *offset)
160{
161 DATA_BLOB ret;
162 uint32_t rel_offset = (uint32_t) -1; /* Relative offset ! */
163 struct hbin_block *hbin = NULL;
164 unsigned int i;
165
166 if (offset != NULL) {
167 *offset = 0;
168 }
169
170 if (size == 0)
171 return data_blob(NULL, 0);
172
173 size += 4; /* Need to include int32 for the length */
174
175 /* Allocate as a multiple of 8 */
176 size = (size + 7) & ~7;
177
178 ret.data = NULL;
179 ret.length = 0;
180
181 for (i = 0; (hbin = data->hbins[i]); i++) {
182 int j;
183 int32_t my_size;
184 for (j = 0; j < hbin->offset_to_next-0x20; j+= my_size) {
185 my_size = IVALS(hbin->data, j);
186
187 if (my_size == 0x0) {
188 DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
189 return ret;
190 }
191
192 if (my_size % 8 != 0) {
193 DEBUG(0, ("Encountered non-aligned block!\n"));
194 }
195
196 if (my_size < 0) { /* Used... */
197 my_size = -my_size;
198 } else if (my_size == size) { /* exact match */
199 rel_offset = j;
200 DEBUG(4, ("Found free block of exact size %d in middle of HBIN\n",
201 size));
202 break;
203 } else if (my_size > size) { /* data will remain */
204 rel_offset = j;
205 /* Split this block and mark the next block as free */
206 SIVAL(hbin->data, rel_offset+size, my_size-size);
207 DEBUG(4, ("Found free block of size %d (needing %d) in middle of HBIN\n",
208 my_size, size));
209 break;
210 }
211 }
212
213 if (rel_offset != -1)
214 break;
215 }
216
217 /* No space available in previous hbins,
218 * allocate new one */
219 if (data->hbins[i] == NULL) {
220 DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n",
221 size));
222
223 /* Add extra hbin block */
224 data->hbins = talloc_realloc(data, data->hbins,
225 struct hbin_block *, i+2);
226 hbin = talloc(data->hbins, struct hbin_block);
227 SMB_ASSERT(hbin != NULL);
228
229 data->hbins[i] = hbin;
230 data->hbins[i+1] = NULL;
231
232 /* Set hbin data */
233 hbin->HBIN_ID = talloc_strdup(hbin, "hbin");
234 hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next);
235 hbin->offset_to_next = 0x1000;
236 hbin->unknown[0] = 0;
237 hbin->unknown[1] = 0;
238 unix_to_nt_time(&hbin->last_change, time(NULL));
239 hbin->block_size = hbin->offset_to_next;
240 hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20);
241 /* Update the regf header */
242 data->header->last_block += hbin->offset_to_next;
243
244 /* Set the next block to it's proper size and set the
245 * rel_offset for this block */
246 SIVAL(hbin->data, size, hbin->block_size - size - 0x20);
247 rel_offset = 0x0;
248 }
249
250 /* Set size and mark as used */
251 SIVAL(hbin->data, rel_offset, -size);
252
253 ret.data = hbin->data + rel_offset + 0x4; /* Skip past length */
254 ret.length = size - 0x4;
255 if (offset) {
256 uint32_t new_rel_offset = 0;
257 *offset = hbin->offset_from_first + rel_offset + 0x20;
258 SMB_ASSERT(hbin_by_offset(data, *offset, &new_rel_offset) == hbin);
259 SMB_ASSERT(new_rel_offset == rel_offset);
260 }
261
262 return ret;
263}
264
265/* Store a data blob. Return the offset at which it was stored */
266static uint32_t hbin_store (struct regf_data *data, DATA_BLOB blob)
267{
268 uint32_t ret;
269 DATA_BLOB dest = hbin_alloc(data, blob.length, &ret);
270
271 memcpy(dest.data, blob.data, blob.length);
272
273 /* Make sure that we have no tailing garbage in the block */
274 if (dest.length > blob.length) {
275 memset(dest.data + blob.length, 0, dest.length - blob.length);
276 }
277
278 return ret;
279}
280
281static uint32_t hbin_store_tdr(struct regf_data *data,
282 tdr_push_fn_t push_fn, void *p)
283{
284 struct tdr_push *push = tdr_push_init(data);
285 uint32_t ret;
286
287 if (NT_STATUS_IS_ERR(push_fn(push, p))) {
288 DEBUG(0, ("Error during push\n"));
289 return -1;
290 }
291
292 ret = hbin_store(data, push->data);
293
294 talloc_free(push);
295
296 return ret;
297}
298
299
300/* Free existing data */
301static void hbin_free (struct regf_data *data, uint32_t offset)
302{
303 int32_t size;
304 uint32_t rel_offset;
305 int32_t next_size;
306 struct hbin_block *hbin;
307
308 SMB_ASSERT (offset > 0);
309
310 hbin = hbin_by_offset(data, offset, &rel_offset);
311
312 if (hbin == NULL)
313 return;
314
315 /* Get original size */
316 size = IVALS(hbin->data, rel_offset);
317
318 if (size > 0) {
319 DEBUG(1, ("Trying to free already freed block at 0x%04x\n",
320 offset));
321 return;
322 }
323 /* Mark as unused */
324 size = -size;
325
326 /* If the next block is free, merge into big free block */
327 if (rel_offset + size < hbin->offset_to_next - 0x20) {
328 next_size = IVALS(hbin->data, rel_offset+size);
329 if (next_size > 0) {
330 size += next_size;
331 }
332 }
333
334 /* Write block size */
335 SIVALS(hbin->data, rel_offset, size);
336}
337
338/**
339 * Store a data blob data was already stored, but has changed in size
340 * Will try to save it at the current location if possible, otherwise
341 * does a free + store */
342static uint32_t hbin_store_resize(struct regf_data *data,
343 uint32_t orig_offset, DATA_BLOB blob)
344{
345 uint32_t rel_offset;
346 struct hbin_block *hbin = hbin_by_offset(data, orig_offset,
347 &rel_offset);
348 int32_t my_size;
349 int32_t orig_size;
350 int32_t needed_size;
351 int32_t possible_size;
352 unsigned int i;
353
354 SMB_ASSERT(orig_offset > 0);
355
356 if (!hbin)
357 return hbin_store(data, blob);
358
359 /* Get original size */
360 orig_size = -IVALS(hbin->data, rel_offset);
361
362 needed_size = blob.length + 4; /* Add int32 containing length */
363 needed_size = (needed_size + 7) & ~7; /* Align */
364
365 /* Fits into current allocated block */
366 if (orig_size >= needed_size) {
367 memcpy(hbin->data + rel_offset + 0x4, blob.data, blob.length);
368 /* If the difference in size is greater than 0x4, split the block
369 * and free/merge it */
370 if (orig_size - needed_size > 0x4) {
371 SIVALS(hbin->data, rel_offset, -needed_size);
372 SIVALS(hbin->data, rel_offset + needed_size,
373 needed_size-orig_size);
374 hbin_free(data, orig_offset + needed_size);
375 }
376 return orig_offset;
377 }
378
379 possible_size = orig_size;
380
381 /* Check if it can be combined with the next few free records */
382 for (i = rel_offset; i < hbin->offset_to_next - 0x20; i += my_size) {
383 if (IVALS(hbin->data, i) < 0) /* Used */
384 break;
385
386 my_size = IVALS(hbin->data, i);
387
388 if (my_size == 0x0) {
389 DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
390 break;
391 } else {
392 possible_size += my_size;
393 }
394
395 if (possible_size >= blob.length) {
396 SIVAL(hbin->data, rel_offset, -possible_size);
397 memcpy(hbin->data + rel_offset + 0x4,
398 blob.data, blob.length);
399 return orig_offset;
400 }
401 }
402
403 hbin_free(data, orig_offset);
404 return hbin_store(data, blob);
405}
406
407static uint32_t hbin_store_tdr_resize(struct regf_data *regf,
408 tdr_push_fn_t push_fn,
409 uint32_t orig_offset, void *p)
410{
411 struct tdr_push *push = tdr_push_init(regf);
412 uint32_t ret;
413
414 if (NT_STATUS_IS_ERR(push_fn(push, p))) {
415 DEBUG(0, ("Error during push\n"));
416 return -1;
417 }
418
419 ret = hbin_store_resize(regf, orig_offset, push->data);
420
421 talloc_free(push);
422
423 return ret;
424}
425
426static uint32_t regf_create_lh_hash(const char *name)
427{
428 char *hash_name;
429 uint32_t ret = 0;
430 uint16_t i;
431
432 hash_name = strupper_talloc(NULL, name);
433 for (i = 0; *(hash_name + i) != 0; i++) {
434 ret *= 37;
435 ret += *(hash_name + i);
436 }
437 talloc_free(hash_name);
438 return ret;
439}
440
441static WERROR regf_get_info(TALLOC_CTX *mem_ctx,
442 const struct hive_key *key,
443 const char **classname,
444 uint32_t *num_subkeys,
445 uint32_t *num_values,
446 NTTIME *last_mod_time,
447 uint32_t *max_subkeynamelen,
448 uint32_t *max_valnamelen,
449 uint32_t *max_valbufsize)
450{
451 const struct regf_key_data *private_data =
452 (const struct regf_key_data *)key;
453
454 if (num_subkeys != NULL)
455 *num_subkeys = private_data->nk->num_subkeys;
456
457 if (num_values != NULL)
458 *num_values = private_data->nk->num_values;
459
460 if (classname != NULL) {
461 if (private_data->nk->clsname_offset != -1) {
462 DATA_BLOB data = hbin_get(private_data->hive,
463 private_data->nk->clsname_offset);
464 *classname = talloc_strndup(mem_ctx,
465 (char*)data.data,
466 private_data->nk->clsname_length);
467 W_ERROR_HAVE_NO_MEMORY(*classname);
468 } else
469 *classname = NULL;
470 }
471
472 /* TODO: Last mod time */
473
474 /* TODO: max valnamelen */
475
476 /* TODO: max valbufsize */
477
478 /* TODO: max subkeynamelen */
479
480 return WERR_OK;
481}
482
483static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx,
484 struct regf_data *regf,
485 uint32_t offset)
486{
487 struct nk_block *nk;
488 struct regf_key_data *ret;
489
490 ret = talloc_zero(ctx, struct regf_key_data);
491 ret->key.ops = &reg_backend_regf;
492 ret->hive = talloc_reference(ret, regf);
493 ret->offset = offset;
494 nk = talloc(ret, struct nk_block);
495 if (nk == NULL)
496 return NULL;
497
498 ret->nk = nk;
499
500 if (!hbin_get_tdr(regf, offset, nk,
501 (tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
502 DEBUG(0, ("Unable to find HBIN data for offset 0x%x\n", offset));
503 return NULL;
504 }
505
506 if (strcmp(nk->header, "nk") != 0) {
507 DEBUG(0, ("Expected nk record, got %s\n", nk->header));
508 talloc_free(ret);
509 return NULL;
510 }
511
512 return ret;
513}
514
515
516static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key,
517 uint32_t idx, const char **name,
518 uint32_t *data_type, DATA_BLOB *data)
519{
520 const struct regf_key_data *private_data =
521 (const struct regf_key_data *)key;
522 struct vk_block *vk;
523 struct regf_data *regf = private_data->hive;
524 uint32_t vk_offset;
525 DATA_BLOB tmp;
526
527 if (idx >= private_data->nk->num_values)
528 return WERR_NO_MORE_ITEMS;
529
530 tmp = hbin_get(regf, private_data->nk->values_offset);
531 if (!tmp.data) {
532 DEBUG(0, ("Unable to find value list at 0x%x\n",
533 private_data->nk->values_offset));
534 return WERR_GENERAL_FAILURE;
535 }
536
537 if (tmp.length < private_data->nk->num_values * 4) {
538 DEBUG(1, ("Value counts mismatch\n"));
539 }
540
541 vk_offset = IVAL(tmp.data, idx * 4);
542
543 vk = talloc(NULL, struct vk_block);
544 W_ERROR_HAVE_NO_MEMORY(vk);
545
546 if (!hbin_get_tdr(regf, vk_offset, vk,
547 (tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
548 DEBUG(0, ("Unable to get VK block at 0x%x\n", vk_offset));
549 talloc_free(vk);
550 return WERR_GENERAL_FAILURE;
551 }
552
553 /* FIXME: name character set ?*/
554 if (name != NULL) {
555 *name = talloc_strndup(ctx, vk->data_name, vk->name_length);
556 W_ERROR_HAVE_NO_MEMORY(*name);
557 }
558
559 if (data_type != NULL)
560 *data_type = vk->data_type;
561
562 if (vk->data_length & 0x80000000) {
563 /* this is data of type "REG_DWORD" or "REG_DWORD_BIG_ENDIAN" */
564 data->data = talloc_size(ctx, sizeof(uint32_t));
565 W_ERROR_HAVE_NO_MEMORY(data->data);
566 SIVAL(data->data, 0, vk->data_offset);
567 data->length = sizeof(uint32_t);
568 } else {
569 *data = hbin_get(regf, vk->data_offset);
570 }
571
572 if (data->length < vk->data_length) {
573 DEBUG(1, ("Read data less than indicated data length!\n"));
574 }
575
576 talloc_free(vk);
577
578 return WERR_OK;
579}
580
581static WERROR regf_get_value_by_name(TALLOC_CTX *mem_ctx,
582 struct hive_key *key, const char *name,
583 uint32_t *type, DATA_BLOB *data)
584{
585 unsigned int i;
586 const char *vname;
587 WERROR error;
588
589 /* FIXME: Do binary search? Is this list sorted at all? */
590
591 for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i,
592 &vname, type, data));
593 i++) {
594 if (!strcmp(vname, name))
595 return WERR_OK;
596 }
597
598 if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
599 return WERR_BADFILE;
600
601 return error;
602}
603
604
605static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx,
606 const struct hive_key *key,
607 uint32_t idx, const char **name,
608 const char **classname,
609 NTTIME *last_mod_time)
610{
611 DATA_BLOB data;
612 struct regf_key_data *ret;
613 const struct regf_key_data *private_data = (const struct regf_key_data *)key;
614 struct nk_block *nk = private_data->nk;
615 uint32_t key_off=0;
616
617 if (idx >= nk->num_subkeys)
618 return WERR_NO_MORE_ITEMS;
619
620 /* Make sure that we don't crash if the key is empty */
621 if (nk->subkeys_offset == -1) {
622 return WERR_NO_MORE_ITEMS;
623 }
624
625 data = hbin_get(private_data->hive, nk->subkeys_offset);
626 if (!data.data) {
627 DEBUG(0, ("Unable to find subkey list at 0x%x\n",
628 nk->subkeys_offset));
629 return WERR_GENERAL_FAILURE;
630 }
631
632 if (!strncmp((char *)data.data, "li", 2)) {
633 struct li_block li;
634 struct tdr_pull *pull = tdr_pull_init(private_data->hive);
635
636 DEBUG(10, ("Subkeys in LI list\n"));
637 pull->data = data;
638
639 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) {
640 DEBUG(0, ("Error parsing LI list\n"));
641 talloc_free(pull);
642 return WERR_GENERAL_FAILURE;
643 }
644 talloc_free(pull);
645 SMB_ASSERT(!strncmp(li.header, "li", 2));
646
647 if (li.key_count != nk->num_subkeys) {
648 DEBUG(0, ("Subkey counts don't match\n"));
649 return WERR_GENERAL_FAILURE;
650 }
651 key_off = li.nk_offset[idx];
652
653 } else if (!strncmp((char *)data.data, "lf", 2)) {
654 struct lf_block lf;
655 struct tdr_pull *pull = tdr_pull_init(private_data->hive);
656
657 DEBUG(10, ("Subkeys in LF list\n"));
658 pull->data = data;
659
660 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) {
661 DEBUG(0, ("Error parsing LF list\n"));
662 talloc_free(pull);
663 return WERR_GENERAL_FAILURE;
664 }
665 talloc_free(pull);
666 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
667
668 if (lf.key_count != nk->num_subkeys) {
669 DEBUG(0, ("Subkey counts don't match\n"));
670 return WERR_GENERAL_FAILURE;
671 }
672
673 key_off = lf.hr[idx].nk_offset;
674 } else if (!strncmp((char *)data.data, "lh", 2)) {
675 struct lh_block lh;
676 struct tdr_pull *pull = tdr_pull_init(private_data->hive);
677
678 DEBUG(10, ("Subkeys in LH list\n"));
679 pull->data = data;
680
681 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) {
682 DEBUG(0, ("Error parsing LH list\n"));
683 talloc_free(pull);
684 return WERR_GENERAL_FAILURE;
685 }
686 talloc_free(pull);
687 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
688
689 if (lh.key_count != nk->num_subkeys) {
690 DEBUG(0, ("Subkey counts don't match\n"));
691 return WERR_GENERAL_FAILURE;
692 }
693 key_off = lh.hr[idx].nk_offset;
694 } else if (!strncmp((char *)data.data, "ri", 2)) {
695 struct ri_block ri;
696 struct tdr_pull *pull = tdr_pull_init(ctx);
697 uint16_t i;
698 uint16_t sublist_count = 0;
699
700 DEBUG(10, ("Subkeys in RI list\n"));
701 pull->data = data;
702
703 if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) {
704 DEBUG(0, ("Error parsing RI list\n"));
705 talloc_free(pull);
706 return WERR_GENERAL_FAILURE;
707 }
708 SMB_ASSERT(!strncmp(ri.header, "ri", 2));
709
710 for (i = 0; i < ri.key_count; i++) {
711 DATA_BLOB list_data;
712
713 /* Get sublist data blob */
714 list_data = hbin_get(private_data->hive, ri.offset[i]);
715 if (!list_data.data) {
716 DEBUG(0, ("Error getting RI list."));
717 talloc_free(pull);
718 return WERR_GENERAL_FAILURE;
719 }
720
721 pull->data = list_data;
722
723 if (!strncmp((char *)list_data.data, "li", 2)) {
724 struct li_block li;
725
726 DEBUG(10, ("Subkeys in RI->LI list\n"));
727
728 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull,
729 nk,
730 &li))) {
731 DEBUG(0, ("Error parsing LI list from RI\n"));
732 talloc_free(pull);
733 return WERR_GENERAL_FAILURE;
734 }
735 SMB_ASSERT(!strncmp(li.header, "li", 2));
736
737 /* Advance to next sublist if necessary */
738 if (idx >= sublist_count + li.key_count) {
739 sublist_count += li.key_count;
740 continue;
741 }
742 key_off = li.nk_offset[idx - sublist_count];
743 sublist_count += li.key_count;
744 break;
745 } else if (!strncmp((char *)list_data.data, "lh", 2)) {
746 struct lh_block lh;
747
748 DEBUG(10, ("Subkeys in RI->LH list\n"));
749
750 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull,
751 nk,
752 &lh))) {
753 DEBUG(0, ("Error parsing LH list from RI\n"));
754 talloc_free(pull);
755 return WERR_GENERAL_FAILURE;
756 }
757 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
758
759 /* Advance to next sublist if necessary */
760 if (idx >= sublist_count + lh.key_count) {
761 sublist_count += lh.key_count;
762 continue;
763 }
764 key_off = lh.hr[idx - sublist_count].nk_offset;
765 sublist_count += lh.key_count;
766 break;
767 } else {
768 DEBUG(0,("Unknown sublist in ri block\n"));
769 talloc_free(pull);
770
771 return WERR_GENERAL_FAILURE;
772 }
773
774 }
775 talloc_free(pull);
776
777
778 if (idx > sublist_count) {
779 return WERR_NO_MORE_ITEMS;
780 }
781
782 } else {
783 DEBUG(0, ("Unknown type for subkey list (0x%04x): %c%c\n",
784 nk->subkeys_offset, data.data[0], data.data[1]));
785 return WERR_GENERAL_FAILURE;
786 }
787
788 ret = regf_get_key (ctx, private_data->hive, key_off);
789
790 if (classname != NULL) {
791 if (ret->nk->clsname_offset != -1) {
792 DATA_BLOB db = hbin_get(ret->hive,
793 ret->nk->clsname_offset);
794 *classname = talloc_strndup(ctx,
795 (char*)db.data,
796 ret->nk->clsname_length);
797 W_ERROR_HAVE_NO_MEMORY(*classname);
798 } else
799 *classname = NULL;
800 }
801
802 if (last_mod_time != NULL)
803 *last_mod_time = ret->nk->last_change;
804
805 if (name != NULL)
806 *name = talloc_steal(ctx, ret->nk->key_name);
807
808 talloc_free(ret);
809
810 return WERR_OK;
811}
812
813static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx,
814 const struct hive_key *key,
815 uint32_t offset,
816 const char *name, uint32_t *ret)
817{
818 DATA_BLOB subkey_data;
819 struct nk_block subkey;
820 struct tdr_pull *pull;
821 const struct regf_key_data *private_data =
822 (const struct regf_key_data *)key;
823
824 subkey_data = hbin_get(private_data->hive, offset);
825 if (!subkey_data.data) {
826 DEBUG(0, ("Unable to retrieve subkey HBIN\n"));
827 return WERR_GENERAL_FAILURE;
828 }
829
830 pull = tdr_pull_init(ctx);
831
832 pull->data = subkey_data;
833
834 if (NT_STATUS_IS_ERR(tdr_pull_nk_block(pull, ctx, &subkey))) {
835 DEBUG(0, ("Error parsing NK structure.\n"));
836 talloc_free(pull);
837 return WERR_GENERAL_FAILURE;
838 }
839 talloc_free(pull);
840
841 if (strncmp(subkey.header, "nk", 2)) {
842 DEBUG(0, ("Not an NK structure.\n"));
843 return WERR_GENERAL_FAILURE;
844 }
845
846 if (!strcasecmp(subkey.key_name, name)) {
847 *ret = offset;
848 } else {
849 *ret = 0;
850 }
851 return WERR_OK;
852}
853
854static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx,
855 const struct hive_key *key,
856 const char *name,
857 struct hive_key **ret)
858{
859 DATA_BLOB data;
860 const struct regf_key_data *private_data =
861 (const struct regf_key_data *)key;
862 struct nk_block *nk = private_data->nk;
863 uint32_t key_off = 0;
864
865 /* Make sure that we don't crash if the key is empty */
866 if (nk->subkeys_offset == -1) {
867 return WERR_BADFILE;
868 }
869
870 data = hbin_get(private_data->hive, nk->subkeys_offset);
871 if (!data.data) {
872 DEBUG(0, ("Unable to find subkey list\n"));
873 return WERR_GENERAL_FAILURE;
874 }
875
876 if (!strncmp((char *)data.data, "li", 2)) {
877 struct li_block li;
878 struct tdr_pull *pull = tdr_pull_init(ctx);
879 uint16_t i;
880
881 DEBUG(10, ("Subkeys in LI list\n"));
882 pull->data = data;
883
884 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) {
885 DEBUG(0, ("Error parsing LI list\n"));
886 talloc_free(pull);
887 return WERR_GENERAL_FAILURE;
888 }
889 talloc_free(pull);
890 SMB_ASSERT(!strncmp(li.header, "li", 2));
891
892 if (li.key_count != nk->num_subkeys) {
893 DEBUG(0, ("Subkey counts don't match\n"));
894 return WERR_GENERAL_FAILURE;
895 }
896
897 for (i = 0; i < li.key_count; i++) {
898 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
899 li.nk_offset[i],
900 name,
901 &key_off));
902 if (key_off != 0)
903 break;
904 }
905 if (key_off == 0)
906 return WERR_BADFILE;
907 } else if (!strncmp((char *)data.data, "lf", 2)) {
908 struct lf_block lf;
909 struct tdr_pull *pull = tdr_pull_init(ctx);
910 uint16_t i;
911
912 DEBUG(10, ("Subkeys in LF list\n"));
913 pull->data = data;
914
915 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) {
916 DEBUG(0, ("Error parsing LF list\n"));
917 talloc_free(pull);
918 return WERR_GENERAL_FAILURE;
919 }
920 talloc_free(pull);
921 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
922
923 if (lf.key_count != nk->num_subkeys) {
924 DEBUG(0, ("Subkey counts don't match\n"));
925 return WERR_GENERAL_FAILURE;
926 }
927
928 for (i = 0; i < lf.key_count; i++) {
929 if (strncmp(lf.hr[i].hash, name, 4)) {
930 continue;
931 }
932 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
933 key,
934 lf.hr[i].nk_offset,
935 name,
936 &key_off));
937 if (key_off != 0)
938 break;
939 }
940 if (key_off == 0)
941 return WERR_BADFILE;
942 } else if (!strncmp((char *)data.data, "lh", 2)) {
943 struct lh_block lh;
944 struct tdr_pull *pull = tdr_pull_init(ctx);
945 uint16_t i;
946 uint32_t hash;
947
948 DEBUG(10, ("Subkeys in LH list\n"));
949 pull->data = data;
950
951 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) {
952 DEBUG(0, ("Error parsing LH list\n"));
953 talloc_free(pull);
954 return WERR_GENERAL_FAILURE;
955 }
956 talloc_free(pull);
957 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
958
959 if (lh.key_count != nk->num_subkeys) {
960 DEBUG(0, ("Subkey counts don't match\n"));
961 return WERR_GENERAL_FAILURE;
962 }
963
964 hash = regf_create_lh_hash(name);
965 for (i = 0; i < lh.key_count; i++) {
966 if (lh.hr[i].base37 != hash) {
967 continue;
968 }
969 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
970 key,
971 lh.hr[i].nk_offset,
972 name,
973 &key_off));
974 if (key_off != 0)
975 break;
976 }
977 if (key_off == 0)
978 return WERR_BADFILE;
979 } else if (!strncmp((char *)data.data, "ri", 2)) {
980 struct ri_block ri;
981 struct tdr_pull *pull = tdr_pull_init(ctx);
982 uint16_t i, j;
983
984 DEBUG(10, ("Subkeys in RI list\n"));
985 pull->data = data;
986
987 if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) {
988 DEBUG(0, ("Error parsing RI list\n"));
989 talloc_free(pull);
990 return WERR_GENERAL_FAILURE;
991 }
992 SMB_ASSERT(!strncmp(ri.header, "ri", 2));
993
994 for (i = 0; i < ri.key_count; i++) {
995 DATA_BLOB list_data;
996
997 /* Get sublist data blob */
998 list_data = hbin_get(private_data->hive, ri.offset[i]);
999 if (list_data.data == NULL) {
1000 DEBUG(0, ("Error getting RI list."));
1001 talloc_free(pull);
1002 return WERR_GENERAL_FAILURE;
1003 }
1004
1005 pull->data = list_data;
1006
1007 if (!strncmp((char *)list_data.data, "li", 2)) {
1008 struct li_block li;
1009
1010 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull,
1011 nk,
1012 &li))) {
1013 DEBUG(0, ("Error parsing LI list from RI\n"));
1014 talloc_free(pull);
1015 return WERR_GENERAL_FAILURE;
1016 }
1017 SMB_ASSERT(!strncmp(li.header, "li", 2));
1018
1019 for (j = 0; j < li.key_count; j++) {
1020 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
1021 li.nk_offset[j],
1022 name,
1023 &key_off));
1024 if (key_off)
1025 break;
1026 }
1027 } else if (!strncmp((char *)list_data.data, "lh", 2)) {
1028 struct lh_block lh;
1029 uint32_t hash;
1030
1031 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull,
1032 nk,
1033 &lh))) {
1034 DEBUG(0, ("Error parsing LH list from RI\n"));
1035 talloc_free(pull);
1036 return WERR_GENERAL_FAILURE;
1037 }
1038 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1039
1040 hash = regf_create_lh_hash(name);
1041 for (j = 0; j < lh.key_count; j++) {
1042 if (lh.hr[j].base37 != hash) {
1043 continue;
1044 }
1045 W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
1046 lh.hr[j].nk_offset,
1047 name,
1048 &key_off));
1049 if (key_off)
1050 break;
1051 }
1052 }
1053 if (key_off)
1054 break;
1055 }
1056 talloc_free(pull);
1057 if (!key_off)
1058 return WERR_BADFILE;
1059 } else {
1060 DEBUG(0, ("Unknown subkey list type.\n"));
1061 return WERR_GENERAL_FAILURE;
1062 }
1063
1064 *ret = (struct hive_key *)regf_get_key(ctx, private_data->hive,
1065 key_off);
1066 return WERR_OK;
1067}
1068
1069static WERROR regf_set_sec_desc(struct hive_key *key,
1070 const struct security_descriptor *sec_desc)
1071{
1072 const struct regf_key_data *private_data =
1073 (const struct regf_key_data *)key;
1074 struct sk_block cur_sk, sk, new_sk;
1075 struct regf_data *regf = private_data->hive;
1076 struct nk_block root;
1077 DATA_BLOB data;
1078 uint32_t sk_offset, cur_sk_offset;
1079 bool update_cur_sk = false;
1080
1081 /* Get the root nk */
1082 hbin_get_tdr(regf, regf->header->data_offset, regf,
1083 (tdr_pull_fn_t) tdr_pull_nk_block, &root);
1084
1085 /* Push the security descriptor to a blob */
1086 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf,
1087 sec_desc, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
1088 DEBUG(0, ("Unable to push security descriptor\n"));
1089 return WERR_GENERAL_FAILURE;
1090 }
1091
1092 /* Get the current security descriptor for the key */
1093 if (!hbin_get_tdr(regf, private_data->nk->sk_offset, regf,
1094 (tdr_pull_fn_t) tdr_pull_sk_block, &cur_sk)) {
1095 DEBUG(0, ("Unable to find security descriptor for current key\n"));
1096 return WERR_BADFILE;
1097 }
1098 /* If there's no change, change nothing. */
1099 if (memcmp(data.data, cur_sk.sec_desc,
1100 MIN(data.length, cur_sk.rec_size)) == 0) {
1101 return WERR_OK;
1102 }
1103
1104 /* Delete the current sk if only this key is using it */
1105 if (cur_sk.ref_cnt == 1) {
1106 /* Get the previous security descriptor for the key */
1107 if (!hbin_get_tdr(regf, cur_sk.prev_offset, regf,
1108 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1109 DEBUG(0, ("Unable to find prev security descriptor for current key\n"));
1110 return WERR_BADFILE;
1111 }
1112 /* Change and store the previous security descriptor */
1113 sk.next_offset = cur_sk.next_offset;
1114 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block,
1115 cur_sk.prev_offset, &sk);
1116
1117 /* Get the next security descriptor for the key */
1118 if (!hbin_get_tdr(regf, cur_sk.next_offset, regf,
1119 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1120 DEBUG(0, ("Unable to find next security descriptor for current key\n"));
1121 return WERR_BADFILE;
1122 }
1123 /* Change and store the next security descriptor */
1124 sk.prev_offset = cur_sk.prev_offset;
1125 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_sk_block,
1126 cur_sk.next_offset, &sk);
1127
1128 hbin_free(regf, private_data->nk->sk_offset);
1129 } else {
1130 /* This key will no longer be referring to this sk */
1131 cur_sk.ref_cnt--;
1132 update_cur_sk = true;
1133 }
1134
1135 sk_offset = root.sk_offset;
1136
1137 do {
1138 cur_sk_offset = sk_offset;
1139 if (!hbin_get_tdr(regf, sk_offset, regf,
1140 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1141 DEBUG(0, ("Unable to find security descriptor\n"));
1142 return WERR_BADFILE;
1143 }
1144 if (memcmp(data.data, sk.sec_desc, MIN(data.length, sk.rec_size)) == 0) {
1145 private_data->nk->sk_offset = sk_offset;
1146 sk.ref_cnt++;
1147 hbin_store_tdr_resize(regf,
1148 (tdr_push_fn_t) tdr_push_sk_block,
1149 sk_offset, &sk);
1150 hbin_store_tdr_resize(regf,
1151 (tdr_push_fn_t) tdr_push_nk_block,
1152 private_data->offset,
1153 private_data->nk);
1154 return WERR_OK;
1155 }
1156 sk_offset = sk.next_offset;
1157 } while (sk_offset != root.sk_offset);
1158
1159 ZERO_STRUCT(new_sk);
1160 new_sk.header = "sk";
1161 new_sk.prev_offset = cur_sk_offset;
1162 new_sk.next_offset = root.sk_offset;
1163 new_sk.ref_cnt = 1;
1164 new_sk.rec_size = data.length;
1165 new_sk.sec_desc = data.data;
1166
1167 sk_offset = hbin_store_tdr(regf,
1168 (tdr_push_fn_t) tdr_push_sk_block,
1169 &new_sk);
1170 if (sk_offset == -1) {
1171 DEBUG(0, ("Error storing sk block\n"));
1172 return WERR_GENERAL_FAILURE;
1173 }
1174 private_data->nk->sk_offset = sk_offset;
1175
1176 if (update_cur_sk) {
1177 hbin_store_tdr_resize(regf,
1178 (tdr_push_fn_t) tdr_push_sk_block,
1179 private_data->nk->sk_offset, &cur_sk);
1180 }
1181
1182 /* Get the previous security descriptor for the key */
1183 if (!hbin_get_tdr(regf, new_sk.prev_offset, regf,
1184 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1185 DEBUG(0, ("Unable to find security descriptor for previous key\n"));
1186 return WERR_BADFILE;
1187 }
1188 /* Change and store the previous security descriptor */
1189 sk.next_offset = sk_offset;
1190 hbin_store_tdr_resize(regf,
1191 (tdr_push_fn_t) tdr_push_sk_block,
1192 cur_sk.prev_offset, &sk);
1193
1194 /* Get the next security descriptor for the key (always root, as we append) */
1195 if (!hbin_get_tdr(regf, new_sk.next_offset, regf,
1196 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1197 DEBUG(0, ("Unable to find security descriptor for current key\n"));
1198 return WERR_BADFILE;
1199 }
1200 /* Change and store the next security descriptor (always root, as we append) */
1201 sk.prev_offset = sk_offset;
1202 hbin_store_tdr_resize(regf,
1203 (tdr_push_fn_t) tdr_push_sk_block,
1204 root.sk_offset, &sk);
1205
1206
1207 /* Store the nk. */
1208 hbin_store_tdr_resize(regf,
1209 (tdr_push_fn_t) tdr_push_sk_block,
1210 private_data->offset, private_data->nk);
1211 return WERR_OK;
1212}
1213
1214static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key,
1215 struct security_descriptor **sd)
1216{
1217 const struct regf_key_data *private_data =
1218 (const struct regf_key_data *)key;
1219 struct sk_block sk;
1220 struct regf_data *regf = private_data->hive;
1221 DATA_BLOB data;
1222
1223 if (!hbin_get_tdr(regf, private_data->nk->sk_offset, ctx,
1224 (tdr_pull_fn_t) tdr_pull_sk_block, &sk)) {
1225 DEBUG(0, ("Unable to find security descriptor\n"));
1226 return WERR_GENERAL_FAILURE;
1227 }
1228
1229 if (strcmp(sk.header, "sk") != 0) {
1230 DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header));
1231 return WERR_GENERAL_FAILURE;
1232 }
1233
1234 *sd = talloc(ctx, struct security_descriptor);
1235 W_ERROR_HAVE_NO_MEMORY(*sd);
1236
1237 data.data = sk.sec_desc;
1238 data.length = sk.rec_size;
1239 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_pull_struct_blob(&data, ctx, *sd,
1240 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor))) {
1241 DEBUG(0, ("Error parsing security descriptor\n"));
1242 return WERR_GENERAL_FAILURE;
1243 }
1244
1245 return WERR_OK;
1246}
1247
1248static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset,
1249 const char *name,
1250 uint32_t key_offset, uint32_t *ret)
1251{
1252 DATA_BLOB data;
1253
1254 /* Create a new key if necessary */
1255 if (list_offset == -1) {
1256 if (regf->header->version.major != 1) {
1257 DEBUG(0, ("Can't store keys in unknown registry format\n"));
1258 return WERR_NOT_SUPPORTED;
1259 }
1260 if (regf->header->version.minor < 3) {
1261 /* Store LI */
1262 struct li_block li;
1263 ZERO_STRUCT(li);
1264 li.header = "li";
1265 li.key_count = 1;
1266
1267 li.nk_offset = talloc_array(regf, uint32_t, 1);
1268 W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1269 li.nk_offset[0] = key_offset;
1270
1271 *ret = hbin_store_tdr(regf,
1272 (tdr_push_fn_t) tdr_push_li_block,
1273 &li);
1274
1275 talloc_free(li.nk_offset);
1276 } else if (regf->header->version.minor == 3 ||
1277 regf->header->version.minor == 4) {
1278 /* Store LF */
1279 struct lf_block lf;
1280 ZERO_STRUCT(lf);
1281 lf.header = "lf";
1282 lf.key_count = 1;
1283
1284 lf.hr = talloc_array(regf, struct hash_record, 1);
1285 W_ERROR_HAVE_NO_MEMORY(lf.hr);
1286 lf.hr[0].nk_offset = key_offset;
1287 lf.hr[0].hash = talloc_strndup(lf.hr, name, 4);
1288 W_ERROR_HAVE_NO_MEMORY(lf.hr[0].hash);
1289
1290 *ret = hbin_store_tdr(regf,
1291 (tdr_push_fn_t) tdr_push_lf_block,
1292 &lf);
1293
1294 talloc_free(lf.hr);
1295 } else if (regf->header->version.minor == 5) {
1296 /* Store LH */
1297 struct lh_block lh;
1298 ZERO_STRUCT(lh);
1299 lh.header = "lh";
1300 lh.key_count = 1;
1301
1302 lh.hr = talloc_array(regf, struct lh_hash, 1);
1303 W_ERROR_HAVE_NO_MEMORY(lh.hr);
1304 lh.hr[0].nk_offset = key_offset;
1305 lh.hr[0].base37 = regf_create_lh_hash(name);
1306
1307 *ret = hbin_store_tdr(regf,
1308 (tdr_push_fn_t) tdr_push_lh_block,
1309 &lh);
1310
1311 talloc_free(lh.hr);
1312 }
1313 return WERR_OK;
1314 }
1315
1316 data = hbin_get(regf, list_offset);
1317 if (!data.data) {
1318 DEBUG(0, ("Unable to find subkey list\n"));
1319 return WERR_BADFILE;
1320 }
1321
1322 if (!strncmp((char *)data.data, "li", 2)) {
1323 struct tdr_pull *pull = tdr_pull_init(regf);
1324 struct li_block li;
1325 struct nk_block sub_nk;
1326 int32_t i, j;
1327
1328 pull->data = data;
1329
1330 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) {
1331 DEBUG(0, ("Error parsing LI list\n"));
1332 talloc_free(pull);
1333 return WERR_BADFILE;
1334 }
1335 talloc_free(pull);
1336
1337 if (strncmp(li.header, "li", 2) != 0) {
1338 abort();
1339 DEBUG(0, ("LI header corrupt\n"));
1340 return WERR_BADFILE;
1341 }
1342
1343 /*
1344 * Find the position to store the pointer
1345 * Extensive testing reveils that at least on windows 7 subkeys
1346 * *MUST* be stored in alphabetical order
1347 */
1348 for (i = 0; i < li.key_count; i++) {
1349 /* Get the nk */
1350 hbin_get_tdr(regf, li.nk_offset[i], regf,
1351 (tdr_pull_fn_t) tdr_pull_nk_block, &sub_nk);
1352 if (strcasecmp(name, sub_nk.key_name) < 0) {
1353 break;
1354 }
1355 }
1356
1357 li.nk_offset = talloc_realloc(regf, li.nk_offset,
1358 uint32_t, li.key_count+1);
1359 W_ERROR_HAVE_NO_MEMORY(li.nk_offset);
1360
1361 /* Move everything behind this offset */
1362 for (j = li.key_count - 1; j >= i; j--) {
1363 li.nk_offset[j+1] = li.nk_offset[j];
1364 }
1365
1366 li.nk_offset[i] = key_offset;
1367 li.key_count++;
1368 *ret = hbin_store_tdr_resize(regf,
1369 (tdr_push_fn_t)tdr_push_li_block,
1370 list_offset, &li);
1371
1372 talloc_free(li.nk_offset);
1373 } else if (!strncmp((char *)data.data, "lf", 2)) {
1374 struct tdr_pull *pull = tdr_pull_init(regf);
1375 struct lf_block lf;
1376 struct nk_block sub_nk;
1377 int32_t i, j;
1378
1379 pull->data = data;
1380
1381 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) {
1382 DEBUG(0, ("Error parsing LF list\n"));
1383 talloc_free(pull);
1384 return WERR_BADFILE;
1385 }
1386 talloc_free(pull);
1387 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1388
1389 /*
1390 * Find the position to store the hash record
1391 * Extensive testing reveils that at least on windows 7 subkeys
1392 * *MUST* be stored in alphabetical order
1393 */
1394 for (i = 0; i < lf.key_count; i++) {
1395 /* Get the nk */
1396 hbin_get_tdr(regf, lf.hr[i].nk_offset, regf,
1397 (tdr_pull_fn_t) tdr_pull_nk_block, &sub_nk);
1398 if (strcasecmp(name, sub_nk.key_name) < 0) {
1399 break;
1400 }
1401 }
1402
1403 lf.hr = talloc_realloc(regf, lf.hr, struct hash_record,
1404 lf.key_count+1);
1405 W_ERROR_HAVE_NO_MEMORY(lf.hr);
1406
1407 /* Move everything behind this hash record */
1408 for (j = lf.key_count - 1; j >= i; j--) {
1409 lf.hr[j+1] = lf.hr[j];
1410 }
1411
1412 lf.hr[i].nk_offset = key_offset;
1413 lf.hr[i].hash = talloc_strndup(lf.hr, name, 4);
1414 W_ERROR_HAVE_NO_MEMORY(lf.hr[lf.key_count].hash);
1415 lf.key_count++;
1416 *ret = hbin_store_tdr_resize(regf,
1417 (tdr_push_fn_t)tdr_push_lf_block,
1418 list_offset, &lf);
1419
1420 talloc_free(lf.hr);
1421 } else if (!strncmp((char *)data.data, "lh", 2)) {
1422 struct tdr_pull *pull = tdr_pull_init(regf);
1423 struct lh_block lh;
1424 struct nk_block sub_nk;
1425 int32_t i, j;
1426
1427 pull->data = data;
1428
1429 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) {
1430 DEBUG(0, ("Error parsing LH list\n"));
1431 talloc_free(pull);
1432 return WERR_BADFILE;
1433 }
1434 talloc_free(pull);
1435 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1436
1437 /*
1438 * Find the position to store the hash record
1439 * Extensive testing reveils that at least on windows 7 subkeys
1440 * *MUST* be stored in alphabetical order
1441 */
1442 for (i = 0; i < lh.key_count; i++) {
1443 /* Get the nk */
1444 hbin_get_tdr(regf, lh.hr[i].nk_offset, regf,
1445 (tdr_pull_fn_t) tdr_pull_nk_block, &sub_nk);
1446 if (strcasecmp(name, sub_nk.key_name) < 0) {
1447 break;
1448 }
1449 }
1450
1451 lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash,
1452 lh.key_count+1);
1453 W_ERROR_HAVE_NO_MEMORY(lh.hr);
1454
1455 /* Move everything behind this hash record */
1456 for (j = lh.key_count - 1; j >= i; j--) {
1457 lh.hr[j+1] = lh.hr[j];
1458 }
1459
1460 lh.hr[i].nk_offset = key_offset;
1461 lh.hr[i].base37 = regf_create_lh_hash(name);
1462 lh.key_count++;
1463 *ret = hbin_store_tdr_resize(regf,
1464 (tdr_push_fn_t)tdr_push_lh_block,
1465 list_offset, &lh);
1466
1467 talloc_free(lh.hr);
1468 } else if (!strncmp((char *)data.data, "ri", 2)) {
1469 /* FIXME */
1470 DEBUG(0, ("Adding to 'ri' subkey list is not supported yet.\n"));
1471 return WERR_NOT_SUPPORTED;
1472 } else {
1473 DEBUG(0, ("Cannot add to unknown subkey list\n"));
1474 return WERR_BADFILE;
1475 }
1476
1477 return WERR_OK;
1478}
1479
1480static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset,
1481 uint32_t key_offset, uint32_t *ret)
1482{
1483 DATA_BLOB data;
1484
1485 data = hbin_get(regf, list_offset);
1486 if (!data.data) {
1487 DEBUG(0, ("Unable to find subkey list\n"));
1488 return WERR_BADFILE;
1489 }
1490
1491 if (strncmp((char *)data.data, "li", 2) == 0) {
1492 struct li_block li;
1493 struct tdr_pull *pull = tdr_pull_init(regf);
1494 uint16_t i;
1495 bool found_offset = false;
1496
1497 DEBUG(10, ("Subkeys in LI list\n"));
1498
1499 pull->data = data;
1500
1501 if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) {
1502 DEBUG(0, ("Error parsing LI list\n"));
1503 talloc_free(pull);
1504 return WERR_BADFILE;
1505 }
1506 talloc_free(pull);
1507
1508 SMB_ASSERT(!strncmp(li.header, "li", 2));
1509
1510 for (i = 0; i < li.key_count; i++) {
1511 if (found_offset) {
1512 li.nk_offset[i-1] = li.nk_offset[i];
1513 }
1514 if (li.nk_offset[i] == key_offset) {
1515 found_offset = true;
1516 continue;
1517 }
1518 }
1519 if (!found_offset) {
1520 DEBUG(2, ("Subkey not found\n"));
1521 return WERR_BADFILE;
1522 }
1523 li.key_count--;
1524
1525 /* If the there are no entries left, free the subkey list */
1526 if (li.key_count == 0) {
1527 hbin_free(regf, list_offset);
1528 *ret = -1;
1529 }
1530
1531 /* Store li block */
1532 *ret = hbin_store_tdr_resize(regf,
1533 (tdr_push_fn_t) tdr_push_li_block,
1534 list_offset, &li);
1535 } else if (strncmp((char *)data.data, "lf", 2) == 0) {
1536 struct lf_block lf;
1537 struct tdr_pull *pull = tdr_pull_init(regf);
1538 uint16_t i;
1539 bool found_offset = false;
1540
1541 DEBUG(10, ("Subkeys in LF list\n"));
1542
1543 pull->data = data;
1544
1545 if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) {
1546 DEBUG(0, ("Error parsing LF list\n"));
1547 talloc_free(pull);
1548 return WERR_BADFILE;
1549 }
1550 talloc_free(pull);
1551
1552 SMB_ASSERT(!strncmp(lf.header, "lf", 2));
1553
1554 for (i = 0; i < lf.key_count; i++) {
1555 if (found_offset) {
1556 lf.hr[i-1] = lf.hr[i];
1557 continue;
1558 }
1559 if (lf.hr[i].nk_offset == key_offset) {
1560 found_offset = 1;
1561 continue;
1562 }
1563 }
1564 if (!found_offset) {
1565 DEBUG(2, ("Subkey not found\n"));
1566 return WERR_BADFILE;
1567 }
1568 lf.key_count--;
1569
1570 /* If the there are no entries left, free the subkey list */
1571 if (lf.key_count == 0) {
1572 hbin_free(regf, list_offset);
1573 *ret = -1;
1574 return WERR_OK;
1575 }
1576
1577 /* Store lf block */
1578 *ret = hbin_store_tdr_resize(regf,
1579 (tdr_push_fn_t) tdr_push_lf_block,
1580 list_offset, &lf);
1581 } else if (strncmp((char *)data.data, "lh", 2) == 0) {
1582 struct lh_block lh;
1583 struct tdr_pull *pull = tdr_pull_init(regf);
1584 uint16_t i;
1585 bool found_offset = false;
1586
1587 DEBUG(10, ("Subkeys in LH list\n"));
1588
1589 pull->data = data;
1590
1591 if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) {
1592 DEBUG(0, ("Error parsing LF list\n"));
1593 talloc_free(pull);
1594 return WERR_BADFILE;
1595 }
1596 talloc_free(pull);
1597
1598 SMB_ASSERT(!strncmp(lh.header, "lh", 2));
1599
1600 for (i = 0; i < lh.key_count; i++) {
1601 if (found_offset) {
1602 lh.hr[i-1] = lh.hr[i];
1603 continue;
1604 }
1605 if (lh.hr[i].nk_offset == key_offset) {
1606 found_offset = 1;
1607 continue;
1608 }
1609 }
1610 if (!found_offset) {
1611 DEBUG(0, ("Subkey not found\n"));
1612 return WERR_BADFILE;
1613 }
1614 lh.key_count--;
1615
1616 /* If the there are no entries left, free the subkey list */
1617 if (lh.key_count == 0) {
1618 hbin_free(regf, list_offset);
1619 *ret = -1;
1620 return WERR_OK;
1621 }
1622
1623 /* Store lh block */
1624 *ret = hbin_store_tdr_resize(regf,
1625 (tdr_push_fn_t) tdr_push_lh_block,
1626 list_offset, &lh);
1627 } else if (strncmp((char *)data.data, "ri", 2) == 0) {
1628 /* FIXME */
1629 DEBUG(0, ("Sorry, deletion from ri block is not supported yet.\n"));
1630 return WERR_NOT_SUPPORTED;
1631 } else {
1632 DEBUG (0, ("Unknown header found in subkey list.\n"));
1633 return WERR_BADFILE;
1634 }
1635 return WERR_OK;
1636}
1637
1638static WERROR regf_del_value(TALLOC_CTX *mem_ctx, struct hive_key *key,
1639 const char *name)
1640{
1641 struct regf_key_data *private_data = (struct regf_key_data *)key;
1642 struct regf_data *regf = private_data->hive;
1643 struct nk_block *nk = private_data->nk;
1644 struct vk_block vk;
1645 uint32_t vk_offset;
1646 bool found_offset = false;
1647 DATA_BLOB values;
1648 unsigned int i;
1649
1650 if (nk->values_offset == -1) {
1651 return WERR_BADFILE;
1652 }
1653
1654 values = hbin_get(regf, nk->values_offset);
1655
1656 for (i = 0; i < nk->num_values; i++) {
1657 if (found_offset) {
1658 ((uint32_t *)values.data)[i-1] = ((uint32_t *) values.data)[i];
1659 } else {
1660 vk_offset = IVAL(values.data, i * 4);
1661 if (!hbin_get_tdr(regf, vk_offset, private_data,
1662 (tdr_pull_fn_t)tdr_pull_vk_block,
1663 &vk)) {
1664 DEBUG(0, ("Unable to get VK block at %d\n",
1665 vk_offset));
1666 return WERR_BADFILE;
1667 }
1668 if (strcmp(vk.data_name, name) == 0) {
1669 hbin_free(regf, vk_offset);
1670 found_offset = true;
1671 }
1672 }
1673 }
1674 if (!found_offset) {
1675 return WERR_BADFILE;
1676 } else {
1677 nk->num_values--;
1678 values.length = (nk->num_values)*4;
1679 }
1680
1681 /* Store values list and nk */
1682 if (nk->num_values == 0) {
1683 hbin_free(regf, nk->values_offset);
1684 nk->values_offset = -1;
1685 } else {
1686 nk->values_offset = hbin_store_resize(regf,
1687 nk->values_offset,
1688 values);
1689 }
1690 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
1691 private_data->offset, nk);
1692
1693 return regf_save_hbin(private_data->hive, 0);
1694}
1695
1696
1697static WERROR regf_del_key(TALLOC_CTX *mem_ctx, const struct hive_key *parent,
1698 const char *name)
1699{
1700 const struct regf_key_data *private_data =
1701 (const struct regf_key_data *)parent;
1702 struct regf_key_data *key;
1703 struct nk_block *parent_nk;
1704 WERROR error;
1705
1706 SMB_ASSERT(private_data);
1707
1708 parent_nk = private_data->nk;
1709
1710 if (parent_nk->subkeys_offset == -1) {
1711 DEBUG(4, ("Subkey list is empty, this key cannot contain subkeys.\n"));
1712 return WERR_BADFILE;
1713 }
1714
1715 /* Find the key */
1716 if (!W_ERROR_IS_OK(regf_get_subkey_by_name(parent_nk, parent, name,
1717 (struct hive_key **)&key))) {
1718 DEBUG(2, ("Key '%s' not found\n", name));
1719 return WERR_BADFILE;
1720 }
1721
1722 if (key->nk->subkeys_offset != -1) {
1723 struct hive_key *sk = (struct hive_key *)key;
1724 unsigned int i = key->nk->num_subkeys;
1725 while (i--) {
1726 char *sk_name;
1727 const char *p = NULL;
1728
1729 /* Get subkey information. */
1730 error = regf_get_subkey_by_index(parent_nk, sk, 0,
1731 &p,
1732 NULL, NULL);
1733 if (!W_ERROR_IS_OK(error)) {
1734 DEBUG(0, ("Can't retrieve subkey by index.\n"));
1735 return error;
1736 }
1737 sk_name = discard_const_p(char, p);
1738
1739 /* Delete subkey. */
1740 error = regf_del_key(NULL, sk, sk_name);
1741 if (!W_ERROR_IS_OK(error)) {
1742 DEBUG(0, ("Can't delete key '%s'.\n", sk_name));
1743 return error;
1744 }
1745
1746 talloc_free(sk_name);
1747 }
1748 }
1749
1750 if (key->nk->values_offset != -1) {
1751 struct hive_key *sk = (struct hive_key *)key;
1752 DATA_BLOB data;
1753 unsigned int i = key->nk->num_values;
1754 while (i--) {
1755 char *val_name;
1756 const char *p = NULL;
1757
1758 /* Get value information. */
1759 error = regf_get_value(parent_nk, sk, 0,
1760 &p,
1761 NULL, &data);
1762 if (!W_ERROR_IS_OK(error)) {
1763 DEBUG(0, ("Can't retrieve value by index.\n"));
1764 return error;
1765 }
1766 val_name = discard_const_p(char, p);
1767
1768 /* Delete value. */
1769 error = regf_del_value(NULL, sk, val_name);
1770 if (!W_ERROR_IS_OK(error)) {
1771 DEBUG(0, ("Can't delete value '%s'.\n", val_name));
1772 return error;
1773 }
1774
1775 talloc_free(val_name);
1776 }
1777 }
1778
1779 /* Delete it from the subkey list. */
1780 error = regf_sl_del_entry(private_data->hive, parent_nk->subkeys_offset,
1781 key->offset, &parent_nk->subkeys_offset);
1782 if (!W_ERROR_IS_OK(error)) {
1783 DEBUG(0, ("Can't store new subkey list for parent key. Won't delete.\n"));
1784 return error;
1785 }
1786
1787 /* Re-store parent key */
1788 parent_nk->num_subkeys--;
1789 hbin_store_tdr_resize(private_data->hive,
1790 (tdr_push_fn_t) tdr_push_nk_block,
1791 private_data->offset, parent_nk);
1792
1793 if (key->nk->clsname_offset != -1) {
1794 hbin_free(private_data->hive, key->nk->clsname_offset);
1795 }
1796 hbin_free(private_data->hive, key->offset);
1797
1798 return regf_save_hbin(private_data->hive, 0);
1799}
1800
1801static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent,
1802 const char *name, const char *classname,
1803 struct security_descriptor *sec_desc,
1804 struct hive_key **ret)
1805{
1806 const struct regf_key_data *private_data =
1807 (const struct regf_key_data *)parent;
1808 struct nk_block *parent_nk = private_data->nk, nk;
1809 struct nk_block *root;
1810 struct regf_data *regf = private_data->hive;
1811 uint32_t offset;
1812 WERROR error;
1813
1814 nk.header = "nk";
1815 nk.type = REG_SUB_KEY;
1816 unix_to_nt_time(&nk.last_change, time(NULL));
1817 nk.uk1 = 0;
1818 nk.parent_offset = private_data->offset;
1819 nk.num_subkeys = 0;
1820 nk.uk2 = 0;
1821 nk.subkeys_offset = -1;
1822 nk.unknown_offset = -1;
1823 nk.num_values = 0;
1824 nk.values_offset = -1;
1825 memset(nk.unk3, 0, sizeof(nk.unk3));
1826 nk.clsname_offset = -1; /* FIXME: fill in */
1827 nk.clsname_length = 0;
1828 nk.key_name = name;
1829
1830 /* Get the security descriptor of the root key */
1831 root = talloc_zero(ctx, struct nk_block);
1832 W_ERROR_HAVE_NO_MEMORY(root);
1833
1834 if (!hbin_get_tdr(regf, regf->header->data_offset, root,
1835 (tdr_pull_fn_t)tdr_pull_nk_block, root)) {
1836 DEBUG(0, ("Unable to find HBIN data for offset 0x%x\n",
1837 regf->header->data_offset));
1838 return WERR_GENERAL_FAILURE;
1839 }
1840 nk.sk_offset = root->sk_offset;
1841 talloc_free(root);
1842
1843 /* Store the new nk key */
1844 offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk);
1845
1846 error = regf_sl_add_entry(regf, parent_nk->subkeys_offset, name, offset,
1847 &parent_nk->subkeys_offset);
1848 if (!W_ERROR_IS_OK(error)) {
1849 hbin_free(regf, offset);
1850 return error;
1851 }
1852
1853 parent_nk->num_subkeys++;
1854
1855 /* Since the subkey offset of the parent can change, store it again */
1856 hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
1857 nk.parent_offset, parent_nk);
1858
1859 *ret = (struct hive_key *)regf_get_key(ctx, regf, offset);
1860
1861 DEBUG(9, ("Storing key %s\n", name));
1862 return regf_save_hbin(private_data->hive, 0);
1863}
1864
1865static WERROR regf_set_value(struct hive_key *key, const char *name,
1866 uint32_t type, const DATA_BLOB data)
1867{
1868 struct regf_key_data *private_data = (struct regf_key_data *)key;
1869 struct regf_data *regf = private_data->hive;
1870 struct nk_block *nk = private_data->nk;
1871 struct vk_block vk;
1872 uint32_t i;
1873 uint32_t tmp_vk_offset, vk_offset, old_vk_offset = (uint32_t) -1;
1874 DATA_BLOB values = {0};
1875
1876 ZERO_STRUCT(vk);
1877
1878 /* find the value offset, if it exists */
1879 if (nk->values_offset != -1) {
1880 values = hbin_get(regf, nk->values_offset);
1881
1882 for (i = 0; i < nk->num_values; i++) {
1883 tmp_vk_offset = IVAL(values.data, i * 4);
1884 if (!hbin_get_tdr(regf, tmp_vk_offset, private_data,
1885 (tdr_pull_fn_t)tdr_pull_vk_block,
1886 &vk)) {
1887 DEBUG(0, ("Unable to get VK block at 0x%x\n",
1888 tmp_vk_offset));
1889 return WERR_GENERAL_FAILURE;
1890 }
1891 if (strcmp(vk.data_name, name) == 0) {
1892 old_vk_offset = tmp_vk_offset;
1893 break;
1894 }
1895 }
1896 }
1897
1898 /* If it's new, create the vk struct, if it's old, free the old data. */
1899 if (old_vk_offset == -1) {
1900 vk.header = "vk";
1901 if (name != NULL && name[0] != '\0') {
1902 vk.flag = 1;
1903 vk.data_name = name;
1904 vk.name_length = strlen(name);
1905 } else {
1906 vk.flag = 0;
1907 vk.data_name = NULL;
1908 vk.name_length = 0;
1909 }
1910 } else {
1911 /* Free data, if any */
1912 if (!(vk.data_length & 0x80000000)) {
1913 hbin_free(regf, vk.data_offset);
1914 }
1915 }
1916
1917 /* Set the type and data */
1918 vk.data_length = data.length;
1919 vk.data_type = type;
1920 if ((type == REG_DWORD) || (type == REG_DWORD_BIG_ENDIAN)) {
1921 if (vk.data_length != sizeof(uint32_t)) {
1922 DEBUG(0, ("DWORD or DWORD_BIG_ENDIAN value with size other than 4 byte!\n"));
1923 return WERR_NOT_SUPPORTED;
1924 }
1925 vk.data_length |= 0x80000000;
1926 vk.data_offset = IVAL(data.data, 0);
1927 } else {
1928 /* Store data somewhere */
1929 vk.data_offset = hbin_store(regf, data);
1930 }
1931 if (old_vk_offset == -1) {
1932 /* Store new vk */
1933 vk_offset = hbin_store_tdr(regf,
1934 (tdr_push_fn_t) tdr_push_vk_block,
1935 &vk);
1936 } else {
1937 /* Store vk at offset */
1938 vk_offset = hbin_store_tdr_resize(regf,
1939 (tdr_push_fn_t) tdr_push_vk_block,
1940 old_vk_offset ,&vk);
1941 }
1942
1943 /* Re-allocate the value list */
1944 if (nk->values_offset == -1) {
1945 nk->values_offset = hbin_store_tdr(regf,
1946 (tdr_push_fn_t) tdr_push_uint32,
1947 &vk_offset);
1948 nk->num_values = 1;
1949 } else {
1950
1951 /* Change if we're changing, otherwise we're adding the value */
1952 if (old_vk_offset != -1) {
1953 /* Find and overwrite the offset. */
1954 for (i = 0; i < nk->num_values; i++) {
1955 if (IVAL(values.data, i * 4) == old_vk_offset) {
1956 SIVAL(values.data, i * 4, vk_offset);
1957 break;
1958 }
1959 }
1960 } else {
1961 /* Create a new value list */
1962 DATA_BLOB value_list;
1963
1964 value_list.length = (nk->num_values+1)*4;
1965 value_list.data = (uint8_t *)talloc_array(private_data,
1966 uint32_t,
1967 nk->num_values+1);
1968 W_ERROR_HAVE_NO_MEMORY(value_list.data);
1969 memcpy(value_list.data, values.data, nk->num_values * 4);
1970
1971 SIVAL(value_list.data, nk->num_values * 4, vk_offset);
1972 nk->num_values++;
1973 nk->values_offset = hbin_store_resize(regf,
1974 nk->values_offset,
1975 value_list);
1976 }
1977
1978 }
1979 hbin_store_tdr_resize(regf,
1980 (tdr_push_fn_t) tdr_push_nk_block,
1981 private_data->offset, nk);
1982 return regf_save_hbin(private_data->hive, 0);
1983}
1984
1985static WERROR regf_save_hbin(struct regf_data *regf, bool flush)
1986{
1987 struct tdr_push *push = tdr_push_init(regf);
1988 unsigned int i;
1989
1990 W_ERROR_HAVE_NO_MEMORY(push);
1991
1992 /* Only write once every 5 seconds, or when flush is set */
1993 if (!flush && regf->last_write + 5 >= time(NULL)) {
1994 return WERR_OK;
1995 }
1996
1997 regf->last_write = time(NULL);
1998
1999 if (lseek(regf->fd, 0, SEEK_SET) == -1) {
2000 DEBUG(0, ("Error lseeking in regf file\n"));
2001 return WERR_GENERAL_FAILURE;
2002 }
2003
2004 /* Recompute checksum */
2005 if (NT_STATUS_IS_ERR(tdr_push_regf_hdr(push, regf->header))) {
2006 DEBUG(0, ("Failed to push regf header\n"));
2007 return WERR_GENERAL_FAILURE;
2008 }
2009 regf->header->chksum = regf_hdr_checksum(push->data.data);
2010 talloc_free(push);
2011
2012 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd,
2013 (tdr_push_fn_t)tdr_push_regf_hdr,
2014 regf->header))) {
2015 DEBUG(0, ("Error writing registry file header\n"));
2016 return WERR_GENERAL_FAILURE;
2017 }
2018
2019 if (lseek(regf->fd, 0x1000, SEEK_SET) == -1) {
2020 DEBUG(0, ("Error lseeking to 0x1000 in regf file\n"));
2021 return WERR_GENERAL_FAILURE;
2022 }
2023
2024 for (i = 0; regf->hbins[i]; i++) {
2025 if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd,
2026 (tdr_push_fn_t)tdr_push_hbin_block,
2027 regf->hbins[i]))) {
2028 DEBUG(0, ("Error writing HBIN block\n"));
2029 return WERR_GENERAL_FAILURE;
2030 }
2031 }
2032
2033 return WERR_OK;
2034}
2035
2036WERROR reg_create_regf_file(TALLOC_CTX *parent_ctx,
2037 const char *location,
2038 int minor_version, struct hive_key **key)
2039{
2040 struct regf_data *regf;
2041 struct regf_hdr *regf_hdr;
2042 struct nk_block nk;
2043 struct sk_block sk;
2044 WERROR error;
2045 DATA_BLOB data;
2046 struct security_descriptor *sd;
2047 uint32_t sk_offset;
2048
2049 regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
2050
2051 W_ERROR_HAVE_NO_MEMORY(regf);
2052
2053 DEBUG(5, ("Attempting to create registry file\n"));
2054
2055 /* Get the header */
2056 regf->fd = creat(location, 0644);
2057
2058 if (regf->fd == -1) {
2059 DEBUG(0,("Could not create file: %s, %s\n", location,
2060 strerror(errno)));
2061 talloc_free(regf);
2062 return WERR_GENERAL_FAILURE;
2063 }
2064
2065 regf_hdr = talloc_zero(regf, struct regf_hdr);
2066 W_ERROR_HAVE_NO_MEMORY(regf_hdr);
2067 regf_hdr->REGF_ID = "regf";
2068 unix_to_nt_time(&regf_hdr->modtime, time(NULL));
2069 regf_hdr->version.major = 1;
2070 regf_hdr->version.minor = minor_version;
2071 regf_hdr->last_block = 0x1000; /* Block size */
2072 regf_hdr->description = talloc_strdup(regf_hdr,
2073 "Registry created by Samba 4");
2074 W_ERROR_HAVE_NO_MEMORY(regf_hdr->description);
2075 regf_hdr->chksum = 0;
2076
2077 regf->header = regf_hdr;
2078
2079 /* Create all hbin blocks */
2080 regf->hbins = talloc_array(regf, struct hbin_block *, 1);
2081 W_ERROR_HAVE_NO_MEMORY(regf->hbins);
2082 regf->hbins[0] = NULL;
2083
2084 nk.header = "nk";
2085 nk.type = REG_ROOT_KEY;
2086 unix_to_nt_time(&nk.last_change, time(NULL));
2087 nk.uk1 = 0;
2088 nk.parent_offset = -1;
2089 nk.num_subkeys = 0;
2090 nk.uk2 = 0;
2091 nk.subkeys_offset = -1;
2092 nk.unknown_offset = -1;
2093 nk.num_values = 0;
2094 nk.values_offset = -1;
2095 memset(nk.unk3, 0, 5);
2096 nk.clsname_offset = -1;
2097 nk.clsname_length = 0;
2098 nk.sk_offset = 0x80;
2099 nk.key_name = "SambaRootKey";
2100
2101 /*
2102 * It should be noted that changing the key_name to something shorter
2103 * creates a shorter nk block, which makes the position of the sk block
2104 * change. All Windows registries I've seen have the sk at 0x80.
2105 * I therefore recommend that our regf files share that offset -- Wilco
2106 */
2107
2108 /* Create a security descriptor. */
2109 sd = security_descriptor_dacl_create(regf,
2110 0,
2111 NULL, NULL,
2112 SID_NT_AUTHENTICATED_USERS,
2113 SEC_ACE_TYPE_ACCESS_ALLOWED,
2114 SEC_GENERIC_ALL,
2115 SEC_ACE_FLAG_OBJECT_INHERIT,
2116 NULL);
2117
2118 /* Push the security descriptor to a blob */
2119 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(&data, regf,
2120 sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor))) {
2121 DEBUG(0, ("Unable to push security descriptor\n"));
2122 return WERR_GENERAL_FAILURE;
2123 }
2124
2125 ZERO_STRUCT(sk);
2126 sk.header = "sk";
2127 sk.prev_offset = 0x80;
2128 sk.next_offset = 0x80;
2129 sk.ref_cnt = 1;
2130 sk.rec_size = data.length;
2131 sk.sec_desc = data.data;
2132
2133 /* Store the new nk key */
2134 regf->header->data_offset = hbin_store_tdr(regf,
2135 (tdr_push_fn_t)tdr_push_nk_block,
2136 &nk);
2137 /* Store the sk block */
2138 sk_offset = hbin_store_tdr(regf,
2139 (tdr_push_fn_t) tdr_push_sk_block,
2140 &sk);
2141 if (sk_offset != 0x80) {
2142 DEBUG(0, ("Error storing sk block, should be at 0x80, stored at 0x%x\n", nk.sk_offset));
2143 return WERR_GENERAL_FAILURE;
2144 }
2145
2146
2147 *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
2148 regf->header->data_offset);
2149
2150 error = regf_save_hbin(regf, 1);
2151 if (!W_ERROR_IS_OK(error)) {
2152 return error;
2153 }
2154
2155 /* We can drop our own reference now that *key will have created one */
2156 talloc_unlink(NULL, regf);
2157
2158 return WERR_OK;
2159}
2160
2161static WERROR regf_flush_key(struct hive_key *key)
2162{
2163 struct regf_key_data *private_data = (struct regf_key_data *)key;
2164 struct regf_data *regf = private_data->hive;
2165 WERROR error;
2166
2167 error = regf_save_hbin(regf, 1);
2168 if (!W_ERROR_IS_OK(error)) {
2169 DEBUG(0, ("Failed to flush regf to disk\n"));
2170 return error;
2171 }
2172
2173 return WERR_OK;
2174}
2175
2176static int regf_destruct(struct regf_data *regf)
2177{
2178 WERROR error;
2179
2180 /* Write to disk */
2181 error = regf_save_hbin(regf, 1);
2182 if (!W_ERROR_IS_OK(error)) {
2183 DEBUG(0, ("Failed to flush registry to disk\n"));
2184 return -1;
2185 }
2186
2187 /* Close file descriptor */
2188 close(regf->fd);
2189
2190 return 0;
2191}
2192
2193WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location,
2194 struct hive_key **key)
2195{
2196 struct regf_data *regf;
2197 struct regf_hdr *regf_hdr;
2198 struct tdr_pull *pull;
2199 unsigned int i;
2200
2201 regf = (struct regf_data *)talloc_zero(parent_ctx, struct regf_data);
2202 W_ERROR_HAVE_NO_MEMORY(regf);
2203
2204 talloc_set_destructor(regf, regf_destruct);
2205
2206 DEBUG(5, ("Attempting to load registry file\n"));
2207
2208 /* Get the header */
2209 regf->fd = open(location, O_RDWR);
2210
2211 if (regf->fd == -1) {
2212 DEBUG(0,("Could not load file: %s, %s\n", location,
2213 strerror(errno)));
2214 talloc_free(regf);
2215 return WERR_GENERAL_FAILURE;
2216 }
2217
2218 pull = tdr_pull_init(regf);
2219
2220 pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, 0, regf);
2221
2222 if (pull->data.data == NULL) {
2223 DEBUG(0, ("Error reading data from file: %s\n", location));
2224 talloc_free(regf);
2225 return WERR_GENERAL_FAILURE;
2226 }
2227
2228 regf_hdr = talloc(regf, struct regf_hdr);
2229 W_ERROR_HAVE_NO_MEMORY(regf_hdr);
2230
2231 if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr, regf_hdr))) {
2232 DEBUG(0, ("Failed to pull regf header from file: %s\n", location));
2233 talloc_free(regf);
2234 return WERR_GENERAL_FAILURE;
2235 }
2236
2237 regf->header = regf_hdr;
2238
2239 if (strcmp(regf_hdr->REGF_ID, "regf") != 0) {
2240 DEBUG(0, ("Unrecognized NT registry header id: %s, %s\n",
2241 regf_hdr->REGF_ID, location));
2242 talloc_free(regf);
2243 return WERR_GENERAL_FAILURE;
2244 }
2245
2246 /* Validate the header ... */
2247 if (regf_hdr_checksum(pull->data.data) != regf_hdr->chksum) {
2248 DEBUG(0, ("Registry file checksum error: %s: %d,%d\n",
2249 location, regf_hdr->chksum,
2250 regf_hdr_checksum(pull->data.data)));
2251 talloc_free(regf);
2252 return WERR_GENERAL_FAILURE;
2253 }
2254
2255 pull->offset = 0x1000;
2256
2257 i = 0;
2258 /* Read in all hbin blocks */
2259 regf->hbins = talloc_array(regf, struct hbin_block *, 1);
2260 W_ERROR_HAVE_NO_MEMORY(regf->hbins);
2261
2262 regf->hbins[0] = NULL;
2263
2264 while (pull->offset < pull->data.length &&
2265 pull->offset <= regf->header->last_block) {
2266 struct hbin_block *hbin = talloc(regf->hbins,
2267 struct hbin_block);
2268
2269 W_ERROR_HAVE_NO_MEMORY(hbin);
2270
2271 if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(pull, hbin, hbin))) {
2272 DEBUG(0, ("[%d] Error parsing HBIN block\n", i));
2273 talloc_free(regf);
2274 return WERR_FOOBAR;
2275 }
2276
2277 if (strcmp(hbin->HBIN_ID, "hbin") != 0) {
2278 DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n",
2279 i, hbin->HBIN_ID));
2280 talloc_free(regf);
2281 return WERR_FOOBAR;
2282 }
2283
2284 regf->hbins[i] = hbin;
2285 i++;
2286 regf->hbins = talloc_realloc(regf, regf->hbins,
2287 struct hbin_block *, i+2);
2288 regf->hbins[i] = NULL;
2289 }
2290
2291 talloc_free(pull);
2292
2293 DEBUG(1, ("%d HBIN blocks read\n", i));
2294
2295 *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
2296 regf->header->data_offset);
2297
2298 /* We can drop our own reference now that *key will have created one */
2299 talloc_unlink(parent_ctx, regf);
2300
2301 return WERR_OK;
2302}
2303
2304static struct hive_operations reg_backend_regf = {
2305 .name = "regf",
2306 .get_key_info = regf_get_info,
2307 .enum_key = regf_get_subkey_by_index,
2308 .get_key_by_name = regf_get_subkey_by_name,
2309 .get_value_by_name = regf_get_value_by_name,
2310 .enum_value = regf_get_value,
2311 .get_sec_desc = regf_get_sec_desc,
2312 .set_sec_desc = regf_set_sec_desc,
2313 .add_key = regf_add_key,
2314 .set_value = regf_set_value,
2315 .del_key = regf_del_key,
2316 .delete_value = regf_del_value,
2317 .flush_key = regf_flush_key
2318};
Note: See TracBrowser for help on using the repository browser.