~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/lib/registry/regf.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 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
 
 
30
static 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
 
 
48
struct regf_data {
 
49
        int fd;
 
50
        struct hbin_block **hbins;
 
51
        struct regf_hdr *header;
 
52
        struct smb_iconv_convenience *iconv_convenience;
 
53
};
 
54
 
 
55
static WERROR regf_save_hbin(struct regf_data *data);
 
56
 
 
57
struct regf_key_data {
 
58
        struct hive_key key;
 
59
        struct regf_data *hive;
 
60
        uint32_t offset;
 
61
        struct nk_block *nk;
 
62
};
 
63
 
 
64
static struct hbin_block *hbin_by_offset(const struct regf_data *data,
 
65
                                         uint32_t offset, uint32_t *rel_offset)
 
66
{
 
67
        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
 */
 
86
static uint32_t regf_hdr_checksum(const uint8_t *buffer)
 
87
{
 
88
        uint32_t checksum = 0, x;
 
89
        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
 */
 
102
static 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 containing 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
 
 
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)
 
136
{
 
137
        struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
 
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 */
 
158
static 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 = -1; /* Relative offset ! */
 
163
        struct hbin_block *hbin = NULL;
 
164
        int i;
 
165
 
 
166
        *offset = 0;
 
167
 
 
168
        if (size == 0)
 
169
                return data_blob(NULL, 0);
 
170
 
 
171
        size += 4; /* Need to include int32 for the length */
 
172
 
 
173
        /* Allocate as a multiple of 8 */
 
174
        size = (size + 7) & ~7;
 
175
 
 
176
        ret.data = NULL;
 
177
        ret.length = 0;
 
178
 
 
179
        for (i = 0; (hbin = data->hbins[i]); i++) {
 
180
                int j;
 
181
                int32_t my_size;
 
182
                for (j = 0; j < hbin->offset_to_next-0x20; j+= my_size) {
 
183
                        my_size = IVALS(hbin->data, j);
 
184
 
 
185
                        if (my_size == 0x0) {
 
186
                                DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
 
187
                                return ret;
 
188
                        }
 
189
 
 
190
                        if (my_size % 8 != 0) {
 
191
                                DEBUG(0, ("Encountered non-aligned block!\n"));
 
192
                        }
 
193
 
 
194
                        if (my_size < 0) { /* Used... */
 
195
                                my_size = -my_size;
 
196
                        } else if (my_size == size) { /* exact match */
 
197
                                rel_offset = j;
 
198
                                DEBUG(4, ("Found free block of exact size %d in middle of HBIN\n",
 
199
                                        size));
 
200
                                break;
 
201
                        } else if (my_size > size) { /* data will remain */
 
202
                                rel_offset = j;
 
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",
 
206
                                        my_size, size));
 
207
                                break;
 
208
                        }
 
209
                }
 
210
 
 
211
                if (rel_offset != -1)
 
212
                        break;
 
213
        }
 
214
 
 
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",
 
219
                        size));
 
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);
 
224
 
 
225
                data->hbins[i] = hbin;
 
226
                data->hbins[i+1] = NULL;
 
227
 
 
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);
 
236
 
 
237
                rel_offset = 0x0;
 
238
                SIVAL(hbin->data, size, hbin->block_size - size - 0x20);
 
239
        }
 
240
 
 
241
        /* Set size and mark as used */
 
242
        SIVAL(hbin->data, rel_offset, -size);
 
243
 
 
244
        ret.data = hbin->data + rel_offset + 0x4; /* Skip past length */
 
245
        ret.length = size - 0x4;
 
246
        if (offset) {
 
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);
 
251
        }
 
252
 
 
253
        return ret;
 
254
}
 
255
 
 
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)
 
258
{
 
259
        uint32_t ret;
 
260
        DATA_BLOB dest = hbin_alloc(data, blob.length, &ret);
 
261
 
 
262
        memcpy(dest.data, blob.data, blob.length);
 
263
 
 
264
        return ret;
 
265
}
 
266
 
 
267
static uint32_t hbin_store_tdr(struct regf_data *data,
 
268
                               tdr_push_fn_t push_fn, void *p)
 
269
{
 
270
        struct tdr_push *push = tdr_push_init(data, data->iconv_convenience);
 
271
        uint32_t ret;
 
272
 
 
273
        if (NT_STATUS_IS_ERR(push_fn(push, p))) {
 
274
                DEBUG(0, ("Error during push\n"));
 
275
                return -1;
 
276
        }
 
277
 
 
278
        ret = hbin_store(data, push->data);
 
279
 
 
280
        talloc_free(push);
 
281
 
 
282
        return ret;
 
283
}
 
284
 
 
285
 
 
286
/* Free existing data */
 
287
static void hbin_free (struct regf_data *data, uint32_t offset)
 
288
{
 
289
        int32_t size;
 
290
        uint32_t rel_offset;
 
291
        int32_t next_size;
 
292
        struct hbin_block *hbin;
 
293
 
 
294
        SMB_ASSERT (offset > 0);
 
295
 
 
296
        hbin = hbin_by_offset(data, offset, &rel_offset);
 
297
 
 
298
        if (hbin == NULL)
 
299
                return;
 
300
 
 
301
        /* Get original size */
 
302
        size = IVALS(hbin->data, rel_offset);
 
303
 
 
304
        if (size > 0) {
 
305
                DEBUG(1, ("Trying to free already freed block at 0x%04x\n",
 
306
                        offset));
 
307
                return;
 
308
        }
 
309
        /* Mark as unused */
 
310
        size = -size;
 
311
 
 
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);
 
315
                if (next_size > 0) {
 
316
                        size += next_size;
 
317
                }
 
318
        }
 
319
 
 
320
        /* Write block size */
 
321
        SIVALS(hbin->data, rel_offset, size);
 
322
}
 
323
 
 
324
/**
 
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)
 
330
{
 
331
        uint32_t rel_offset;
 
332
        struct hbin_block *hbin = hbin_by_offset(data, orig_offset,
 
333
                                                 &rel_offset);
 
334
        int32_t my_size;
 
335
        int32_t orig_size;
 
336
        int32_t needed_size;
 
337
        int32_t possible_size;
 
338
        int i;
 
339
 
 
340
        SMB_ASSERT(orig_offset > 0);
 
341
 
 
342
        if (!hbin)
 
343
                return hbin_store(data, blob);
 
344
 
 
345
        /* Get original size */
 
346
        orig_size = -IVALS(hbin->data, rel_offset);
 
347
 
 
348
        needed_size = blob.length + 4; /* Add int32 containing length */
 
349
        needed_size = (needed_size + 7) & ~7; /* Align */
 
350
 
 
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);
 
361
                }
 
362
                return orig_offset;
 
363
        }
 
364
 
 
365
        possible_size = orig_size;
 
366
 
 
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 */
 
370
                        break;
 
371
 
 
372
                my_size = IVALS(hbin->data, i);
 
373
 
 
374
                if (my_size == 0x0) {
 
375
                        DEBUG(0, ("Invalid zero-length block! File is corrupt.\n"));
 
376
                        break;
 
377
                } else {
 
378
                        possible_size += my_size;
 
379
                }
 
380
 
 
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);
 
385
                        return orig_offset;
 
386
                }
 
387
        }
 
388
 
 
389
        hbin_free(data, orig_offset);
 
390
        return hbin_store(data, blob);
 
391
}
 
392
 
 
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)
 
396
{
 
397
        struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience);
 
398
        uint32_t ret;
 
399
 
 
400
        if (NT_STATUS_IS_ERR(push_fn(push, p))) {
 
401
                DEBUG(0, ("Error during push\n"));
 
402
                return -1;
 
403
        }
 
404
 
 
405
        ret = hbin_store_resize(regf, orig_offset, push->data);
 
406
 
 
407
        talloc_free(push);
 
408
 
 
409
        return ret;
 
410
}
 
411
 
 
412
static uint32_t regf_create_lh_hash(const char *name)
 
413
{
 
414
        char *hash_name;
 
415
        uint32_t ret = 0;
 
416
        uint16_t i;
 
417
 
 
418
        hash_name = strupper_talloc(NULL, name);
 
419
        for (i = 0; *(hash_name + i) != 0; i++) {
 
420
                ret *= 37;
 
421
                ret += *(hash_name + i);
 
422
        }
 
423
        talloc_free(hash_name);
 
424
        return ret;
 
425
}
 
426
 
 
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)
 
436
{
 
437
        const struct regf_key_data *private_data =
 
438
                (const struct regf_key_data *)key;
 
439
 
 
440
        if (num_subkeys != NULL)
 
441
                *num_subkeys = private_data->nk->num_subkeys;
 
442
 
 
443
        if (num_values != NULL)
 
444
                *num_values = private_data->nk->num_values;
 
445
 
 
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,
 
451
                                                    (char*)data.data,
 
452
                                                    private_data->nk->clsname_length);
 
453
                } else
 
454
                        *classname = NULL;
 
455
        }
 
456
 
 
457
        /* TODO: Last mod time */
 
458
 
 
459
        /* TODO: max valnamelen */
 
460
        
 
461
        /* TODO: max valbufsize */
 
462
 
 
463
        /* TODO: max subkeynamelen */
 
464
 
 
465
        return WERR_OK;
 
466
}
 
467
 
 
468
static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx,
 
469
                                          struct regf_data *regf,
 
470
                                          uint32_t offset)
 
471
{
 
472
        struct nk_block *nk;
 
473
        struct regf_key_data *ret;
 
474
 
 
475
        ret = talloc_zero(ctx, struct regf_key_data);
 
476
        ret->key.ops = &reg_backend_regf;
 
477
        ret->hive = talloc_reference(ret, regf);
 
478
        ret->offset = offset;
 
479
        nk = talloc(ret, struct nk_block);
 
480
        if (nk == NULL)
 
481
                return NULL;
 
482
 
 
483
        ret->nk = nk;
 
484
 
 
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));
 
488
                return NULL;
 
489
        }
 
490
 
 
491
        if (strcmp(nk->header, "nk") != 0) {
 
492
                DEBUG(0, ("Expected nk record, got %s\n", nk->header));
 
493
                talloc_free(ret);
 
494
                return NULL;
 
495
        }
 
496
 
 
497
        return ret;
 
498
}
 
499
 
 
500
 
 
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)
 
504
{
 
505
        const struct regf_key_data *private_data =
 
506
                        (const struct regf_key_data *)key;
 
507
        struct vk_block *vk;
 
508
        struct regf_data *regf = private_data->hive;
 
509
        uint32_t vk_offset;
 
510
        DATA_BLOB tmp;
 
511
 
 
512
        if (idx >= private_data->nk->num_values)
 
513
                return WERR_NO_MORE_ITEMS;
 
514
 
 
515
        tmp = hbin_get(regf, private_data->nk->values_offset);
 
516
        if (!tmp.data) {
 
517
                DEBUG(0, ("Unable to find value list\n"));
 
518
                return WERR_GENERAL_FAILURE;
 
519
        }
 
520
 
 
521
        if (tmp.length < private_data->nk->num_values * 4) {
 
522
                DEBUG(1, ("Value counts mismatch\n"));
 
523
        }
 
524
 
 
525
        vk_offset = IVAL(tmp.data, idx * 4);
 
526
 
 
527
        vk = talloc(NULL, struct vk_block);
 
528
        W_ERROR_HAVE_NO_MEMORY(vk);
 
529
 
 
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));
 
533
                talloc_free(vk);
 
534
                return WERR_GENERAL_FAILURE;
 
535
        }
 
536
 
 
537
        /* FIXME: name character set ?*/
 
538
        if (name != NULL)
 
539
                *name = talloc_strndup(ctx, vk->data_name, vk->name_length);
 
540
 
 
541
        if (data_type != NULL)
 
542
                *data_type = vk->data_type;
 
543
 
 
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;
 
548
        } else {
 
549
                *data = hbin_get(regf, vk->data_offset);
 
550
        }
 
551
 
 
552
        if (data->length < vk->data_length) {
 
553
                DEBUG(1, ("Read data less than indicated data length!\n"));
 
554
        }
 
555
 
 
556
        talloc_free(vk);
 
557
 
 
558
        return WERR_OK;
 
559
}
 
560
 
 
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)
 
564
{
 
565
        int i;
 
566
        const char *vname;
 
567
        WERROR error;
 
568
 
 
569
        /* FIXME: Do binary search? Is this list sorted at all? */
 
570
 
 
571
        for (i = 0; W_ERROR_IS_OK(error = regf_get_value(mem_ctx, key, i,
 
572
                                                         &vname, type, data));
 
573
                                                         i++) {
 
574
                if (!strcmp(vname, name))
 
575
                        return WERR_OK;
 
576
        }
 
577
 
 
578
        if (W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS))
 
579
                return WERR_BADFILE;
 
580
 
 
581
        return error;
 
582
}
 
583
 
 
584
 
 
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)
 
590
{
 
591
        DATA_BLOB data;
 
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;
 
595
        uint32_t key_off=0;
 
596
 
 
597
        if (idx >= nk->num_subkeys)
 
598
                return WERR_NO_MORE_ITEMS;
 
599
 
 
600
        data = hbin_get(private_data->hive, nk->subkeys_offset);
 
601
        if (!data.data) {
 
602
                DEBUG(0, ("Unable to find subkey list\n"));
 
603
                return WERR_GENERAL_FAILURE;
 
604
        }
 
605
 
 
606
        if (!strncmp((char *)data.data, "li", 2)) {
 
607
                struct li_block li;
 
608
                struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
 
609
 
 
610
                DEBUG(10, ("Subkeys in LI list\n"));
 
611
                pull->data = data;
 
612
 
 
613
                if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) {
 
614
                        DEBUG(0, ("Error parsing LI list\n"));
 
615
                        talloc_free(pull);
 
616
                        return WERR_GENERAL_FAILURE;
 
617
                }
 
618
                talloc_free(pull);
 
619
                SMB_ASSERT(!strncmp(li.header, "li", 2));
 
620
 
 
621
                if (li.key_count != nk->num_subkeys) {
 
622
                        DEBUG(0, ("Subkey counts don't match\n"));
 
623
                        return WERR_GENERAL_FAILURE;
 
624
                }
 
625
                key_off = li.nk_offset[idx];
 
626
 
 
627
        } else if (!strncmp((char *)data.data, "lf", 2)) {
 
628
                struct lf_block lf;
 
629
                struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
 
630
 
 
631
                DEBUG(10, ("Subkeys in LF list\n"));
 
632
                pull->data = data;
 
633
 
 
634
                if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) {
 
635
                        DEBUG(0, ("Error parsing LF list\n"));
 
636
                        talloc_free(pull);
 
637
                        return WERR_GENERAL_FAILURE;
 
638
                }
 
639
                talloc_free(pull);
 
640
                SMB_ASSERT(!strncmp(lf.header, "lf", 2));
 
641
 
 
642
                if (lf.key_count != nk->num_subkeys) {
 
643
                        DEBUG(0, ("Subkey counts don't match\n"));
 
644
                        return WERR_GENERAL_FAILURE;
 
645
                }
 
646
 
 
647
                key_off = lf.hr[idx].nk_offset;
 
648
        } else if (!strncmp((char *)data.data, "lh", 2)) {
 
649
                struct lh_block lh;
 
650
                struct tdr_pull *pull = tdr_pull_init(private_data->hive, private_data->hive->iconv_convenience);
 
651
 
 
652
                DEBUG(10, ("Subkeys in LH list\n"));
 
653
                pull->data = data;
 
654
 
 
655
                if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) {
 
656
                        DEBUG(0, ("Error parsing LH list\n"));
 
657
                        talloc_free(pull);
 
658
                        return WERR_GENERAL_FAILURE;
 
659
                }
 
660
                talloc_free(pull);
 
661
                SMB_ASSERT(!strncmp(lh.header, "lh", 2));
 
662
 
 
663
                if (lh.key_count != nk->num_subkeys) {
 
664
                        DEBUG(0, ("Subkey counts don't match\n"));
 
665
                        return WERR_GENERAL_FAILURE;
 
666
                }
 
667
                key_off = lh.hr[idx].nk_offset;
 
668
        } else if (!strncmp((char *)data.data, "ri", 2)) {
 
669
                struct ri_block ri;
 
670
                struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
 
671
                uint16_t i;
 
672
                uint16_t sublist_count = 0;
 
673
 
 
674
                DEBUG(10, ("Subkeys in RI list\n"));
 
675
                pull->data = data;
 
676
 
 
677
                if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) {
 
678
                        DEBUG(0, ("Error parsing RI list\n"));
 
679
                        talloc_free(pull);
 
680
                        return WERR_GENERAL_FAILURE;
 
681
                }
 
682
                SMB_ASSERT(!strncmp(ri.header, "ri", 2));
 
683
 
 
684
                for (i = 0; i < ri.key_count; i++) {
 
685
                        DATA_BLOB list_data;
 
686
 
 
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."));
 
691
                                talloc_free(pull);
 
692
                                return WERR_GENERAL_FAILURE;
 
693
                        }
 
694
 
 
695
                        pull->data = list_data;
 
696
 
 
697
                        if (!strncmp((char *)list_data.data, "li", 2)) {
 
698
                                struct li_block li;
 
699
 
 
700
                                DEBUG(10, ("Subkeys in RI->LI list\n"));
 
701
 
 
702
                                if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull,
 
703
                                                                       nk,
 
704
                                                                       &li))) {
 
705
                                        DEBUG(0, ("Error parsing LI list from RI\n"));
 
706
                                        talloc_free(pull);
 
707
                                        return WERR_GENERAL_FAILURE;
 
708
                                }
 
709
                                SMB_ASSERT(!strncmp(li.header, "li", 2));
 
710
 
 
711
                                /* Advance to next sublist if necessary */
 
712
                                if (idx >= sublist_count + li.key_count) {
 
713
                                        sublist_count += li.key_count;
 
714
                                        continue;
 
715
                                }
 
716
                                key_off = li.nk_offset[idx - sublist_count];
 
717
                                sublist_count += li.key_count;
 
718
                                break;
 
719
                        } else if (!strncmp((char *)list_data.data, "lh", 2)) {
 
720
                                struct lh_block lh;
 
721
 
 
722
                                DEBUG(10, ("Subkeys in RI->LH list\n"));
 
723
 
 
724
                                if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull,
 
725
                                                                       nk,
 
726
                                                                       &lh))) {
 
727
                                        DEBUG(0, ("Error parsing LH list from RI\n"));
 
728
                                        talloc_free(pull);
 
729
                                        return WERR_GENERAL_FAILURE;
 
730
                                }
 
731
                                SMB_ASSERT(!strncmp(lh.header, "lh", 2));
 
732
 
 
733
                                /* Advance to next sublist if necessary */
 
734
                                if (idx >= sublist_count + lh.key_count) {
 
735
                                        sublist_count += lh.key_count;
 
736
                                        continue;
 
737
                                }
 
738
                                key_off = lh.hr[idx - sublist_count].nk_offset;
 
739
                                sublist_count += lh.key_count;
 
740
                                break;
 
741
                        } else {
 
742
                                DEBUG(0,("Unknown sublist in ri block\n"));
 
743
                                talloc_free(pull);
 
744
 
 
745
                                return WERR_GENERAL_FAILURE;
 
746
                        }
 
747
 
 
748
                }
 
749
                talloc_free(pull);
 
750
 
 
751
 
 
752
                if (idx > sublist_count) {
 
753
                        return WERR_NO_MORE_ITEMS;
 
754
                }
 
755
 
 
756
        } else {
 
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;
 
760
        }
 
761
 
 
762
        ret = regf_get_key (ctx, private_data->hive, key_off);
 
763
 
 
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,
 
769
                                                    (char*)db.data,
 
770
                                                    ret->nk->clsname_length);
 
771
                } else
 
772
                        *classname = NULL;
 
773
        }
 
774
 
 
775
        if (last_mod_time != NULL)
 
776
                *last_mod_time = ret->nk->last_change;
 
777
 
 
778
        if (name != NULL)
 
779
                *name = talloc_steal(ctx, ret->nk->key_name);
 
780
 
 
781
        talloc_free(ret);
 
782
 
 
783
        return WERR_OK;
 
784
}
 
785
 
 
786
static WERROR regf_match_subkey_by_name(TALLOC_CTX *ctx,
 
787
                                        const struct hive_key *key,
 
788
                                        uint32_t offset,
 
789
                                        const char *name, uint32_t *ret)
 
790
{
 
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;
 
796
 
 
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;
 
801
        }
 
802
 
 
803
        pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
 
804
 
 
805
        pull->data = subkey_data;
 
806
 
 
807
        if (NT_STATUS_IS_ERR(tdr_pull_nk_block(pull, ctx, &subkey))) {
 
808
                DEBUG(0, ("Error parsing NK structure.\n"));
 
809
                talloc_free(pull);
 
810
                return WERR_GENERAL_FAILURE;
 
811
        }
 
812
        talloc_free(pull);
 
813
 
 
814
        if (strncmp(subkey.header, "nk", 2)) {
 
815
                DEBUG(0, ("Not an NK structure.\n"));
 
816
                return WERR_GENERAL_FAILURE;
 
817
        }
 
818
 
 
819
        if (!strcasecmp(subkey.key_name, name)) {
 
820
                *ret = offset;
 
821
        } else {
 
822
                *ret = 0;
 
823
        }
 
824
        return WERR_OK;
 
825
}
 
826
 
 
827
static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx,
 
828
                                      const struct hive_key *key,
 
829
                                      const char *name,
 
830
                                      struct hive_key **ret)
 
831
{
 
832
        DATA_BLOB data;
 
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;
 
837
 
 
838
        data = hbin_get(private_data->hive, nk->subkeys_offset);
 
839
        if (!data.data) {
 
840
                DEBUG(0, ("Unable to find subkey list\n"));
 
841
                return WERR_GENERAL_FAILURE;
 
842
        }
 
843
 
 
844
        if (!strncmp((char *)data.data, "li", 2)) {
 
845
                struct li_block li;
 
846
                struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
 
847
                uint16_t i;
 
848
 
 
849
                DEBUG(10, ("Subkeys in LI list\n"));
 
850
                pull->data = data;
 
851
 
 
852
                if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, nk, &li))) {
 
853
                        DEBUG(0, ("Error parsing LI list\n"));
 
854
                        talloc_free(pull);
 
855
                        return WERR_GENERAL_FAILURE;
 
856
                }
 
857
                talloc_free(pull);
 
858
                SMB_ASSERT(!strncmp(li.header, "li", 2));
 
859
 
 
860
                if (li.key_count != nk->num_subkeys) {
 
861
                        DEBUG(0, ("Subkey counts don't match\n"));
 
862
                        return WERR_GENERAL_FAILURE;
 
863
                }
 
864
 
 
865
                for (i = 0; i < li.key_count; i++) {
 
866
                        W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
 
867
                                                                        li.nk_offset[i],
 
868
                                                                        name,
 
869
                                                                        &key_off));
 
870
                        if (key_off != 0)
 
871
                                break;
 
872
                }
 
873
                if (key_off == 0)
 
874
                        return WERR_BADFILE;
 
875
        } else if (!strncmp((char *)data.data, "lf", 2)) {
 
876
                struct lf_block lf;
 
877
                struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
 
878
                uint16_t i;
 
879
 
 
880
                DEBUG(10, ("Subkeys in LF list\n"));
 
881
                pull->data = data;
 
882
 
 
883
                if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, nk, &lf))) {
 
884
                        DEBUG(0, ("Error parsing LF list\n"));
 
885
                        talloc_free(pull);
 
886
                        return WERR_GENERAL_FAILURE;
 
887
                }
 
888
                talloc_free(pull);
 
889
                SMB_ASSERT(!strncmp(lf.header, "lf", 2));
 
890
 
 
891
                if (lf.key_count != nk->num_subkeys) {
 
892
                        DEBUG(0, ("Subkey counts don't match\n"));
 
893
                        return WERR_GENERAL_FAILURE;
 
894
                }
 
895
 
 
896
                for (i = 0; i < lf.key_count; i++) {
 
897
                        if (strncmp(lf.hr[i].hash, name, 4)) {
 
898
                                continue;
 
899
                        }
 
900
                        W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
 
901
                                                                        key,
 
902
                                                                        lf.hr[i].nk_offset,
 
903
                                                                        name,
 
904
                                                                        &key_off));
 
905
                        if (key_off != 0)
 
906
                                break;
 
907
                }
 
908
                if (key_off == 0)
 
909
                        return WERR_BADFILE;
 
910
        } else if (!strncmp((char *)data.data, "lh", 2)) {
 
911
                struct lh_block lh;
 
912
                struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
 
913
                uint16_t i;
 
914
                uint32_t hash;
 
915
 
 
916
                DEBUG(10, ("Subkeys in LH list\n"));
 
917
                pull->data = data;
 
918
 
 
919
                if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, nk, &lh))) {
 
920
                        DEBUG(0, ("Error parsing LH list\n"));
 
921
                        talloc_free(pull);
 
922
                        return WERR_GENERAL_FAILURE;
 
923
                }
 
924
                talloc_free(pull);
 
925
                SMB_ASSERT(!strncmp(lh.header, "lh", 2));
 
926
 
 
927
                if (lh.key_count != nk->num_subkeys) {
 
928
                        DEBUG(0, ("Subkey counts don't match\n"));
 
929
                        return WERR_GENERAL_FAILURE;
 
930
                }
 
931
 
 
932
                hash = regf_create_lh_hash(name);
 
933
                for (i = 0; i < lh.key_count; i++) {
 
934
                        if (lh.hr[i].base37 != hash) {
 
935
                                continue;
 
936
                        }
 
937
                        W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk,
 
938
                                                                        key,
 
939
                                                                        lh.hr[i].nk_offset,
 
940
                                                                        name,
 
941
                                                                        &key_off));
 
942
                        if (key_off != 0)
 
943
                                break;
 
944
                }
 
945
                if (key_off == 0)
 
946
                        return WERR_BADFILE;
 
947
        } else if (!strncmp((char *)data.data, "ri", 2)) {
 
948
                struct ri_block ri;
 
949
                struct tdr_pull *pull = tdr_pull_init(ctx, private_data->hive->iconv_convenience);
 
950
                uint16_t i, j;
 
951
 
 
952
                DEBUG(10, ("Subkeys in RI list\n"));
 
953
                pull->data = data;
 
954
 
 
955
                if (NT_STATUS_IS_ERR(tdr_pull_ri_block(pull, nk, &ri))) {
 
956
                        DEBUG(0, ("Error parsing RI list\n"));
 
957
                        talloc_free(pull);
 
958
                        return WERR_GENERAL_FAILURE;
 
959
                }
 
960
                SMB_ASSERT(!strncmp(ri.header, "ri", 2));
 
961
 
 
962
                for (i = 0; i < ri.key_count; i++) {
 
963
                        DATA_BLOB list_data;
 
964
 
 
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."));
 
969
                                talloc_free(pull);
 
970
                                return WERR_GENERAL_FAILURE;
 
971
                        }
 
972
 
 
973
                        pull->data = list_data;
 
974
 
 
975
                        if (!strncmp((char *)list_data.data, "li", 2)) {
 
976
                                struct li_block li;
 
977
 
 
978
                                if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull,
 
979
                                                                       nk,
 
980
                                                                       &li))) {
 
981
                                        DEBUG(0, ("Error parsing LI list from RI\n"));
 
982
                                        talloc_free(pull);
 
983
                                        return WERR_GENERAL_FAILURE;
 
984
                                }
 
985
                                SMB_ASSERT(!strncmp(li.header, "li", 2));
 
986
 
 
987
                                for (j = 0; j < li.key_count; j++) {
 
988
                                        W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
 
989
                                                                                        li.nk_offset[j],
 
990
                                                                                        name,
 
991
                                                                                        &key_off));
 
992
                                        if (key_off)
 
993
                                                break;
 
994
                                }
 
995
                        } else if (!strncmp((char *)list_data.data, "lh", 2)) {
 
996
                                struct lh_block lh;
 
997
                                uint32_t hash;
 
998
 
 
999
                                if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull,
 
1000
                                                                       nk,
 
1001
                                                                       &lh))) {
 
1002
                                        DEBUG(0, ("Error parsing LH list from RI\n"));
 
1003
                                        talloc_free(pull);
 
1004
                                        return WERR_GENERAL_FAILURE;
 
1005
                                }
 
1006
                                SMB_ASSERT(!strncmp(lh.header, "lh", 2));
 
1007
 
 
1008
                                hash = regf_create_lh_hash(name);
 
1009
                                for (j = 0; j < lh.key_count; j++) {
 
1010
                                        if (lh.hr[j].base37 != hash) {
 
1011
                                                continue;
 
1012
                                        }
 
1013
                                        W_ERROR_NOT_OK_RETURN(regf_match_subkey_by_name(nk, key,
 
1014
                                                                                        lh.hr[j].nk_offset,
 
1015
                                                                                        name,
 
1016
                                                                                        &key_off));
 
1017
                                        if (key_off)
 
1018
                                                break;
 
1019
                                }
 
1020
                        }
 
1021
                        if (key_off)
 
1022
                                break;
 
1023
                }
 
1024
                talloc_free(pull);
 
1025
                if (!key_off)
 
1026
                        return WERR_BADFILE;
 
1027
        } else {
 
1028
                DEBUG(0, ("Unknown subkey list type.\n"));
 
1029
                return WERR_GENERAL_FAILURE;
 
1030
        }
 
1031
 
 
1032
        *ret = (struct hive_key *)regf_get_key(ctx, private_data->hive,
 
1033
                                               key_off);
 
1034
        return WERR_OK;
 
1035
}
 
1036
 
 
1037
static WERROR regf_set_sec_desc(struct hive_key *key,
 
1038
                                const struct security_descriptor *sec_desc)
 
1039
{
 
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;
 
1045
        DATA_BLOB data;
 
1046
        uint32_t sk_offset, cur_sk_offset;
 
1047
        bool update_cur_sk = false;
 
1048
 
 
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);
 
1052
 
 
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;
 
1058
        }
 
1059
 
 
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;
 
1065
        }
 
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) {
 
1069
                return WERR_OK;
 
1070
        }
 
1071
 
 
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;
 
1079
                }
 
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);
 
1084
 
 
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;
 
1090
                }
 
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);
 
1095
 
 
1096
                hbin_free(regf, private_data->nk->sk_offset);
 
1097
        } else {
 
1098
                /* This key will no longer be referring to this sk */
 
1099
                cur_sk.ref_cnt--;
 
1100
                update_cur_sk = true;
 
1101
        }
 
1102
 
 
1103
        sk_offset = root.sk_offset;
 
1104
 
 
1105
        do {
 
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;
 
1111
                }
 
1112
                if (memcmp(data.data, sk.sec_desc, MIN(data.length, sk.rec_size)) == 0) {
 
1113
                        private_data->nk->sk_offset = sk_offset;
 
1114
                        sk.ref_cnt++;
 
1115
                        hbin_store_tdr_resize(regf,
 
1116
                                              (tdr_push_fn_t) tdr_push_sk_block,
 
1117
                                              sk_offset, &sk);
 
1118
                        hbin_store_tdr_resize(regf,
 
1119
                                              (tdr_push_fn_t) tdr_push_nk_block,
 
1120
                                              private_data->offset,
 
1121
                                              private_data->nk);
 
1122
                        return WERR_OK;
 
1123
                }
 
1124
                sk_offset = sk.next_offset;
 
1125
        } while (sk_offset != root.sk_offset);
 
1126
 
 
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;
 
1131
        new_sk.ref_cnt = 1;
 
1132
        new_sk.rec_size = data.length;
 
1133
        new_sk.sec_desc = data.data;
 
1134
 
 
1135
        sk_offset = hbin_store_tdr(regf,
 
1136
                                   (tdr_push_fn_t) tdr_push_sk_block,
 
1137
                                   &new_sk);
 
1138
        if (sk_offset == -1) {
 
1139
                DEBUG(0, ("Error storing sk block\n"));
 
1140
                return WERR_GENERAL_FAILURE;
 
1141
        }
 
1142
        private_data->nk->sk_offset = sk_offset;
 
1143
 
 
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);
 
1148
        }
 
1149
 
 
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;
 
1155
        }
 
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);
 
1161
 
 
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;
 
1167
        }
 
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);
 
1173
 
 
1174
 
 
1175
        /* Store the nk. */
 
1176
        hbin_store_tdr_resize(regf,
 
1177
                              (tdr_push_fn_t) tdr_push_sk_block,
 
1178
                              private_data->offset, private_data->nk);
 
1179
        return WERR_OK;
 
1180
}
 
1181
 
 
1182
static WERROR regf_get_sec_desc(TALLOC_CTX *ctx, const struct hive_key *key,
 
1183
                                struct security_descriptor **sd)
 
1184
{
 
1185
        const struct regf_key_data *private_data =
 
1186
                (const struct regf_key_data *)key;
 
1187
        struct sk_block sk;
 
1188
        struct regf_data *regf = private_data->hive;
 
1189
        DATA_BLOB data;
 
1190
 
 
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;
 
1195
        }
 
1196
 
 
1197
        if (strcmp(sk.header, "sk") != 0) {
 
1198
                DEBUG(0, ("Expected 'sk', got '%s'\n", sk.header));
 
1199
                return WERR_GENERAL_FAILURE;
 
1200
        }
 
1201
 
 
1202
        *sd = talloc(ctx, struct security_descriptor);
 
1203
        W_ERROR_HAVE_NO_MEMORY(*sd);
 
1204
 
 
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;
 
1211
        }
 
1212
 
 
1213
        return WERR_OK;
 
1214
}
 
1215
 
 
1216
static WERROR regf_sl_add_entry(struct regf_data *regf, uint32_t list_offset,
 
1217
                                const char *name,
 
1218
                                uint32_t key_offset, uint32_t *ret)
 
1219
{
 
1220
        DATA_BLOB data;
 
1221
 
 
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;
 
1227
                }
 
1228
                if (regf->header->version.minor < 3) {
 
1229
                        /* Store LI */
 
1230
                        struct li_block li;
 
1231
                        ZERO_STRUCT(li);
 
1232
                        li.header = "li";
 
1233
                        li.key_count = 1;
 
1234
 
 
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;
 
1238
 
 
1239
                        *ret = hbin_store_tdr(regf,
 
1240
                                              (tdr_push_fn_t) tdr_push_li_block,
 
1241
                                              &li);
 
1242
 
 
1243
                        talloc_free(li.nk_offset);
 
1244
                } else if (regf->header->version.minor == 3 ||
 
1245
                           regf->header->version.minor == 4) {
 
1246
                        /* Store LF */
 
1247
                        struct lf_block lf;
 
1248
                        ZERO_STRUCT(lf);
 
1249
                        lf.header = "lf";
 
1250
                        lf.key_count = 1;
 
1251
 
 
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);
 
1257
 
 
1258
                        *ret = hbin_store_tdr(regf,
 
1259
                                              (tdr_push_fn_t) tdr_push_lf_block,
 
1260
                                              &lf);
 
1261
 
 
1262
                        talloc_free(lf.hr);
 
1263
                } else if (regf->header->version.minor == 5) {
 
1264
                        /* Store LH */
 
1265
                        struct lh_block lh;
 
1266
                        ZERO_STRUCT(lh);
 
1267
                        lh.header = "lh";
 
1268
                        lh.key_count = 1;
 
1269
 
 
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);
 
1274
 
 
1275
                        *ret = hbin_store_tdr(regf,
 
1276
                                              (tdr_push_fn_t) tdr_push_lh_block,
 
1277
                                              &lh);
 
1278
 
 
1279
                        talloc_free(lh.hr);
 
1280
                }
 
1281
                return WERR_OK;
 
1282
        }
 
1283
 
 
1284
        data = hbin_get(regf, list_offset);
 
1285
        if (!data.data) {
 
1286
                DEBUG(0, ("Unable to find subkey list\n"));
 
1287
                return WERR_BADFILE;
 
1288
        }
 
1289
 
 
1290
        if (!strncmp((char *)data.data, "li", 2)) {
 
1291
                struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
 
1292
                struct li_block li;
 
1293
 
 
1294
                pull->data = data;
 
1295
 
 
1296
                if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) {
 
1297
                        DEBUG(0, ("Error parsing LI list\n"));
 
1298
                        talloc_free(pull);
 
1299
                        return WERR_BADFILE;
 
1300
                }
 
1301
                talloc_free(pull);
 
1302
 
 
1303
                if (strncmp(li.header, "li", 2) != 0) {
 
1304
                        abort();
 
1305
                        DEBUG(0, ("LI header corrupt\n"));
 
1306
                        return WERR_BADFILE;
 
1307
                }
 
1308
 
 
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;
 
1313
                li.key_count++;
 
1314
                *ret = hbin_store_tdr_resize(regf,
 
1315
                                             (tdr_push_fn_t)tdr_push_li_block,
 
1316
                                             list_offset, &li);
 
1317
 
 
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);
 
1321
                struct lf_block lf;
 
1322
 
 
1323
                pull->data = data;
 
1324
 
 
1325
                if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) {
 
1326
                        DEBUG(0, ("Error parsing LF list\n"));
 
1327
                        talloc_free(pull);
 
1328
                        return WERR_BADFILE;
 
1329
                }
 
1330
                talloc_free(pull);
 
1331
                SMB_ASSERT(!strncmp(lf.header, "lf", 2));
 
1332
 
 
1333
                lf.hr = talloc_realloc(regf, lf.hr, struct hash_record,
 
1334
                                       lf.key_count+1);
 
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);
 
1339
                lf.key_count++;
 
1340
                *ret = hbin_store_tdr_resize(regf,
 
1341
                                             (tdr_push_fn_t)tdr_push_lf_block,
 
1342
                                             list_offset, &lf);
 
1343
 
 
1344
                talloc_free(lf.hr);
 
1345
        } else if (!strncmp((char *)data.data, "lh", 2)) {
 
1346
                struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
 
1347
                struct lh_block lh;
 
1348
 
 
1349
                pull->data = data;
 
1350
 
 
1351
                if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) {
 
1352
                        DEBUG(0, ("Error parsing LH list\n"));
 
1353
                        talloc_free(pull);
 
1354
                        return WERR_BADFILE;
 
1355
                }
 
1356
                talloc_free(pull);
 
1357
                SMB_ASSERT(!strncmp(lh.header, "lh", 2));
 
1358
 
 
1359
                lh.hr = talloc_realloc(regf, lh.hr, struct lh_hash,
 
1360
                                       lh.key_count+1);
 
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);
 
1364
                lh.key_count++;
 
1365
                *ret = hbin_store_tdr_resize(regf,
 
1366
                                             (tdr_push_fn_t)tdr_push_lh_block,
 
1367
                                             list_offset, &lh);
 
1368
 
 
1369
                talloc_free(lh.hr);
 
1370
        } else if (!strncmp((char *)data.data, "ri", 2)) {
 
1371
                /* FIXME */
 
1372
                DEBUG(0, ("Adding to 'ri' subkey list is not supported yet.\n"));
 
1373
                return WERR_NOT_SUPPORTED;
 
1374
        } else {
 
1375
                DEBUG(0, ("Cannot add to unknown subkey list\n"));
 
1376
                return WERR_BADFILE;
 
1377
        }
 
1378
 
 
1379
        return WERR_OK;
 
1380
}
 
1381
 
 
1382
static WERROR regf_sl_del_entry(struct regf_data *regf, uint32_t list_offset,
 
1383
                                uint32_t key_offset, uint32_t *ret)
 
1384
{
 
1385
        DATA_BLOB data;
 
1386
 
 
1387
        data = hbin_get(regf, list_offset);
 
1388
        if (!data.data) {
 
1389
                DEBUG(0, ("Unable to find subkey list\n"));
 
1390
                return WERR_BADFILE;
 
1391
        }
 
1392
 
 
1393
        if (strncmp((char *)data.data, "li", 2) == 0) {
 
1394
                struct li_block li;
 
1395
                struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
 
1396
                uint16_t i;
 
1397
                bool found_offset = false;
 
1398
 
 
1399
                DEBUG(10, ("Subkeys in LI list\n"));
 
1400
 
 
1401
                pull->data = data;
 
1402
 
 
1403
                if (NT_STATUS_IS_ERR(tdr_pull_li_block(pull, regf, &li))) {
 
1404
                        DEBUG(0, ("Error parsing LI list\n"));
 
1405
                        talloc_free(pull);
 
1406
                        return WERR_BADFILE;
 
1407
                }
 
1408
                talloc_free(pull);
 
1409
 
 
1410
                SMB_ASSERT(!strncmp(li.header, "li", 2));
 
1411
 
 
1412
                for (i = 0; i < li.key_count; i++) {
 
1413
                        if (found_offset) {
 
1414
                                li.nk_offset[i-1] = li.nk_offset[i];
 
1415
                        }
 
1416
                        if (li.nk_offset[i] == key_offset) {
 
1417
                                found_offset = true;
 
1418
                                continue;
 
1419
                        }
 
1420
                }
 
1421
                if (!found_offset) {
 
1422
                        DEBUG(2, ("Subkey not found\n"));
 
1423
                        return WERR_BADFILE;
 
1424
                }
 
1425
                li.key_count--;
 
1426
 
 
1427
                /* If the there are no entries left, free the subkey list */
 
1428
                if (li.key_count == 0) {
 
1429
                        hbin_free(regf, list_offset);
 
1430
                        *ret = -1;
 
1431
                }
 
1432
 
 
1433
                /* Store li block */
 
1434
                *ret = hbin_store_tdr_resize(regf,
 
1435
                                             (tdr_push_fn_t) tdr_push_li_block,
 
1436
                                             list_offset, &li);
 
1437
        } else if (strncmp((char *)data.data, "lf", 2) == 0) {
 
1438
                struct lf_block lf;
 
1439
                struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
 
1440
                uint16_t i;
 
1441
                bool found_offset = false;
 
1442
 
 
1443
                DEBUG(10, ("Subkeys in LF list\n"));
 
1444
 
 
1445
                pull->data = data;
 
1446
 
 
1447
                if (NT_STATUS_IS_ERR(tdr_pull_lf_block(pull, regf, &lf))) {
 
1448
                        DEBUG(0, ("Error parsing LF list\n"));
 
1449
                        talloc_free(pull);
 
1450
                        return WERR_BADFILE;
 
1451
                }
 
1452
                talloc_free(pull);
 
1453
 
 
1454
                SMB_ASSERT(!strncmp(lf.header, "lf", 2));
 
1455
 
 
1456
                for (i = 0; i < lf.key_count; i++) {
 
1457
                        if (found_offset) {
 
1458
                                lf.hr[i-1] = lf.hr[i];
 
1459
                                continue;
 
1460
                        }
 
1461
                        if (lf.hr[i].nk_offset == key_offset) {
 
1462
                                found_offset = 1;
 
1463
                                continue;
 
1464
                        }
 
1465
                }
 
1466
                if (!found_offset) {
 
1467
                        DEBUG(2, ("Subkey not found\n"));
 
1468
                        return WERR_BADFILE;
 
1469
                }
 
1470
                lf.key_count--;
 
1471
 
 
1472
                /* If the there are no entries left, free the subkey list */
 
1473
                if (lf.key_count == 0) {
 
1474
                        hbin_free(regf, list_offset);
 
1475
                        *ret = -1;
 
1476
                        return WERR_OK;
 
1477
                }
 
1478
 
 
1479
                /* Store lf block */
 
1480
                *ret = hbin_store_tdr_resize(regf,
 
1481
                                             (tdr_push_fn_t) tdr_push_lf_block,
 
1482
                                             list_offset, &lf);
 
1483
        } else if (strncmp((char *)data.data, "lh", 2) == 0) {
 
1484
                struct lh_block lh;
 
1485
                struct tdr_pull *pull = tdr_pull_init(regf, regf->iconv_convenience);
 
1486
                uint16_t i;
 
1487
                bool found_offset = false;
 
1488
 
 
1489
                DEBUG(10, ("Subkeys in LH list\n"));
 
1490
 
 
1491
                pull->data = data;
 
1492
 
 
1493
                if (NT_STATUS_IS_ERR(tdr_pull_lh_block(pull, regf, &lh))) {
 
1494
                        DEBUG(0, ("Error parsing LF list\n"));
 
1495
                        talloc_free(pull);
 
1496
                        return WERR_BADFILE;
 
1497
                }
 
1498
                talloc_free(pull);
 
1499
 
 
1500
                SMB_ASSERT(!strncmp(lh.header, "lh", 2));
 
1501
 
 
1502
                for (i = 0; i < lh.key_count; i++) {
 
1503
                        if (found_offset) {
 
1504
                                lh.hr[i-1] = lh.hr[i];
 
1505
                                continue;
 
1506
                        }
 
1507
                        if (lh.hr[i].nk_offset == key_offset) {
 
1508
                                found_offset = 1;
 
1509
                                continue;
 
1510
                        }
 
1511
                }
 
1512
                if (!found_offset) {
 
1513
                        DEBUG(0, ("Subkey not found\n"));
 
1514
                        return WERR_BADFILE;
 
1515
                }
 
1516
                lh.key_count--;
 
1517
 
 
1518
                /* If the there are no entries left, free the subkey list */
 
1519
                if (lh.key_count == 0) {
 
1520
                        hbin_free(regf, list_offset);
 
1521
                        *ret = -1;
 
1522
                        return WERR_OK;
 
1523
                }
 
1524
 
 
1525
                /* Store lh block */
 
1526
                *ret = hbin_store_tdr_resize(regf,
 
1527
                                             (tdr_push_fn_t) tdr_push_lh_block,
 
1528
                                             list_offset, &lh);
 
1529
        } else if (strncmp((char *)data.data, "ri", 2) == 0) {
 
1530
                /* FIXME */
 
1531
                DEBUG(0, ("Sorry, deletion from ri block is not supported yet.\n"));
 
1532
                return WERR_NOT_SUPPORTED;
 
1533
        } else {
 
1534
                DEBUG (0, ("Unknown header found in subkey list.\n"));
 
1535
                return WERR_BADFILE;
 
1536
        }
 
1537
        return WERR_OK;
 
1538
}
 
1539
 
 
1540
static WERROR regf_del_value (struct hive_key *key, const char *name)
 
1541
{
 
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;
 
1545
        struct vk_block vk;
 
1546
        uint32_t vk_offset;
 
1547
        bool found_offset = false;
 
1548
        DATA_BLOB values;
 
1549
        uint32_t i;
 
1550
 
 
1551
        if (nk->values_offset == -1) {
 
1552
                return WERR_BADFILE;
 
1553
        }
 
1554
 
 
1555
        values = hbin_get(regf, nk->values_offset);
 
1556
 
 
1557
        for (i = 0; i < nk->num_values; i++) {
 
1558
                if (found_offset) {
 
1559
                        ((uint32_t *)values.data)[i-1] = ((uint32_t *) values.data)[i];
 
1560
                } else {
 
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,
 
1564
                                          &vk)) {
 
1565
                                DEBUG(0, ("Unable to get VK block at %d\n",
 
1566
                                        vk_offset));
 
1567
                                return WERR_BADFILE;
 
1568
                        }
 
1569
                        if (strcmp(vk.data_name, name) == 0) {
 
1570
                                hbin_free(regf, vk_offset);
 
1571
                                found_offset = true;
 
1572
                        }
 
1573
                }
 
1574
        }
 
1575
        if (!found_offset) {
 
1576
                return WERR_BADFILE;
 
1577
        } else {
 
1578
                nk->num_values--;
 
1579
                values.length = (nk->num_values)*4;
 
1580
        }
 
1581
 
 
1582
        /* Store values list and nk */
 
1583
        if (nk->num_values == 0) {
 
1584
                hbin_free(regf, nk->values_offset);
 
1585
                nk->values_offset = -1;
 
1586
        } else {
 
1587
                nk->values_offset = hbin_store_resize(regf,
 
1588
                                                      nk->values_offset,
 
1589
                                                      values);
 
1590
        }
 
1591
        hbin_store_tdr_resize(regf, (tdr_push_fn_t) tdr_push_nk_block,
 
1592
                              private_data->offset, nk);
 
1593
 
 
1594
        return regf_save_hbin(private_data->hive);
 
1595
}
 
1596
 
 
1597
 
 
1598
static WERROR regf_del_key(const struct hive_key *parent, const char *name)
 
1599
{
 
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;
 
1604
        WERROR error;
 
1605
 
 
1606
        SMB_ASSERT(private_data);
 
1607
 
 
1608
        parent_nk = private_data->nk;
 
1609
 
 
1610
        if (parent_nk->subkeys_offset == -1) {
 
1611
                DEBUG(4, ("Subkey list is empty, this key cannot contain subkeys.\n"));
 
1612
                return WERR_BADFILE;
 
1613
        }
 
1614
 
 
1615
        /* Find the key */
 
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;
 
1620
        }
 
1621
 
 
1622
        if (key->nk->subkeys_offset != -1) {
 
1623
                char *sk_name;
 
1624
                struct hive_key *sk = (struct hive_key *)key;
 
1625
                int i = key->nk->num_subkeys;
 
1626
                while (i--) {
 
1627
                        /* Get subkey information. */
 
1628
                        error = regf_get_subkey_by_index(parent_nk, sk, 0,
 
1629
                                                         (const char **)&sk_name,
 
1630
                                                         NULL, NULL);
 
1631
                        if (!W_ERROR_IS_OK(error)) {
 
1632
                                DEBUG(0, ("Can't retrieve subkey by index.\n"));
 
1633
                                return error;
 
1634
                        }
 
1635
 
 
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));
 
1640
                                return error;
 
1641
                        }
 
1642
 
 
1643
                        talloc_free(sk_name);
 
1644
                }
 
1645
        }
 
1646
 
 
1647
        if (key->nk->values_offset != -1) {
 
1648
                char *val_name;
 
1649
                struct hive_key *sk = (struct hive_key *)key;
 
1650
                DATA_BLOB data;
 
1651
                int i = key->nk->num_values;
 
1652
                while (i--) {
 
1653
                        /* Get value information. */
 
1654
                        error = regf_get_value(parent_nk, sk, 0,
 
1655
                                               (const char **)&val_name,
 
1656
                                               NULL, &data);
 
1657
                        if (!W_ERROR_IS_OK(error)) {
 
1658
                                DEBUG(0, ("Can't retrieve value by index.\n"));
 
1659
                                return error;
 
1660
                        }
 
1661
 
 
1662
                        /* Delete value. */
 
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));
 
1666
                                return error;
 
1667
                        }
 
1668
 
 
1669
                        talloc_free(val_name);
 
1670
                }
 
1671
        }
 
1672
 
 
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"));
 
1678
                return error;
 
1679
        }
 
1680
 
 
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);
 
1686
 
 
1687
        if (key->nk->clsname_offset != -1) {
 
1688
                hbin_free(private_data->hive, key->nk->clsname_offset);
 
1689
        }
 
1690
        hbin_free(private_data->hive, key->offset);
 
1691
 
 
1692
        return regf_save_hbin(private_data->hive);
 
1693
}
 
1694
 
 
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)
 
1699
{
 
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;
 
1705
        uint32_t offset;
 
1706
        WERROR error;
 
1707
 
 
1708
        nk.header = "nk";
 
1709
        nk.type = REG_SUB_KEY;
 
1710
        unix_to_nt_time(&nk.last_change, time(NULL));
 
1711
        nk.uk1 = 0;
 
1712
        nk.parent_offset = private_data->offset;
 
1713
        nk.num_subkeys = 0;
 
1714
        nk.uk2 = 0;
 
1715
        nk.subkeys_offset = -1;
 
1716
        nk.unknown_offset = -1;
 
1717
        nk.num_values = 0;
 
1718
        nk.values_offset = -1;
 
1719
        memset(nk.unk3, 0, 5);
 
1720
        nk.clsname_offset = -1; /* FIXME: fill in */
 
1721
        nk.clsname_length = 0;
 
1722
        nk.key_name = name;
 
1723
 
 
1724
        /* Get the security descriptor of the root key */
 
1725
        root = talloc_zero(ctx, struct nk_block);
 
1726
        W_ERROR_HAVE_NO_MEMORY(root);
 
1727
 
 
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;
 
1732
        }
 
1733
        nk.sk_offset = root->sk_offset;
 
1734
        talloc_free(root);
 
1735
 
 
1736
        /* Store the new nk key */
 
1737
        offset = hbin_store_tdr(regf, (tdr_push_fn_t) tdr_push_nk_block, &nk);
 
1738
 
 
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);
 
1743
                return error;
 
1744
        }
 
1745
 
 
1746
        parent_nk->num_subkeys++;
 
1747
 
 
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);
 
1751
 
 
1752
        *ret = (struct hive_key *)regf_get_key(ctx, regf, offset);
 
1753
 
 
1754
        return regf_save_hbin(private_data->hive);
 
1755
}
 
1756
 
 
1757
static WERROR regf_set_value(struct hive_key *key, const char *name,
 
1758
                             uint32_t type, const DATA_BLOB data)
 
1759
{
 
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;
 
1763
        struct vk_block vk;
 
1764
        uint32_t i;
 
1765
        uint32_t tmp_vk_offset, vk_offset, old_vk_offset = -1;
 
1766
        DATA_BLOB values;
 
1767
 
 
1768
        ZERO_STRUCT(vk);
 
1769
 
 
1770
        /* find the value offset, if it exists */
 
1771
        if (nk->values_offset != -1) {
 
1772
                values = hbin_get(regf, nk->values_offset);
 
1773
 
 
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,
 
1778
                                          &vk)) {
 
1779
                                DEBUG(0, ("Unable to get VK block at %d\n",
 
1780
                                        tmp_vk_offset));
 
1781
                                return WERR_GENERAL_FAILURE;
 
1782
                        }
 
1783
                        if (strcmp(vk.data_name, name) == 0) {
 
1784
                                old_vk_offset = tmp_vk_offset;
 
1785
                                break;
 
1786
                        }
 
1787
                }
 
1788
                /* Free data, if any */
 
1789
                if (!(vk.data_length & 0x80000000)) {
 
1790
                        hbin_free(regf, vk.data_offset);
 
1791
                }
 
1792
        }
 
1793
        if (old_vk_offset == -1) {
 
1794
                vk.header = "vk";
 
1795
                vk.name_length = strlen(name);
 
1796
                if (name != NULL && name[0] != 0) {
 
1797
                        vk.flag = 1;
 
1798
                        vk.data_name = name;
 
1799
                } else {
 
1800
                        vk.data_name = NULL;
 
1801
                        vk.flag = 0;
 
1802
                }
 
1803
        }
 
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;
 
1810
        } else {
 
1811
                /* Store data somewhere */
 
1812
                vk.data_offset = hbin_store(regf, data);
 
1813
        }
 
1814
        if (old_vk_offset == -1) {
 
1815
                /* Store new vk */
 
1816
                vk_offset = hbin_store_tdr(regf,
 
1817
                                           (tdr_push_fn_t) tdr_push_vk_block,
 
1818
                                           &vk);
 
1819
        } else {
 
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);
 
1824
        }
 
1825
 
 
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,
 
1830
                                                   &vk_offset);
 
1831
                nk->num_values = 1;
 
1832
        } else {
 
1833
 
 
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);
 
1840
                                        break;
 
1841
                                }
 
1842
                        }
 
1843
                } else {
 
1844
                        /* Create a new value list */
 
1845
                        DATA_BLOB value_list;
 
1846
 
 
1847
                        value_list.length = (nk->num_values+1)*4;
 
1848
                        value_list.data = (uint8_t *)talloc_array(private_data,
 
1849
                                                                  uint32_t,
 
1850
                                                                  nk->num_values+1);
 
1851
                        W_ERROR_HAVE_NO_MEMORY(value_list.data);
 
1852
                        memcpy(value_list.data, values.data, nk->num_values * 4);
 
1853
 
 
1854
                        SIVAL(value_list.data, nk->num_values * 4, vk_offset);
 
1855
                        nk->num_values++;
 
1856
                        nk->values_offset = hbin_store_resize(regf,
 
1857
                                                              nk->values_offset,
 
1858
                                                              value_list);
 
1859
                }
 
1860
 
 
1861
        }
 
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);
 
1866
}
 
1867
 
 
1868
static WERROR regf_save_hbin(struct regf_data *regf)
 
1869
{
 
1870
        struct tdr_push *push = tdr_push_init(regf, regf->iconv_convenience);
 
1871
        int i;
 
1872
 
 
1873
        W_ERROR_HAVE_NO_MEMORY(push);
 
1874
 
 
1875
        if (lseek(regf->fd, 0, SEEK_SET) == -1) {
 
1876
                DEBUG(0, ("Error lseeking in regf file\n"));
 
1877
                return WERR_GENERAL_FAILURE;
 
1878
        }
 
1879
 
 
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;
 
1884
        }
 
1885
        regf->header->chksum = regf_hdr_checksum(push->data.data);
 
1886
        talloc_free(push);
 
1887
 
 
1888
        if (NT_STATUS_IS_ERR(tdr_push_to_fd(regf->fd, regf->iconv_convenience,
 
1889
                                            (tdr_push_fn_t)tdr_push_regf_hdr,
 
1890
                                            regf->header))) {
 
1891
                DEBUG(0, ("Error writing registry file header\n"));
 
1892
                return WERR_GENERAL_FAILURE;
 
1893
        }
 
1894
 
 
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;
 
1898
        }
 
1899
 
 
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,
 
1903
                                                    regf->hbins[i]))) {
 
1904
                        DEBUG(0, ("Error writing HBIN block\n"));
 
1905
                        return WERR_GENERAL_FAILURE;
 
1906
                }
 
1907
        }
 
1908
 
 
1909
        return WERR_OK;
 
1910
}
 
1911
 
 
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)
 
1916
{
 
1917
        struct regf_data *regf;
 
1918
        struct regf_hdr *regf_hdr;
 
1919
        struct nk_block nk;
 
1920
        struct sk_block sk;
 
1921
        WERROR error;
 
1922
        DATA_BLOB data;
 
1923
        struct security_descriptor *sd;
 
1924
        uint32_t sk_offset;
 
1925
 
 
1926
        regf = (struct regf_data *)talloc_zero(NULL, struct regf_data);
 
1927
 
 
1928
        regf->iconv_convenience = iconv_convenience;
 
1929
 
 
1930
        W_ERROR_HAVE_NO_MEMORY(regf);
 
1931
 
 
1932
        DEBUG(5, ("Attempting to create registry file\n"));
 
1933
 
 
1934
        /* Get the header */
 
1935
        regf->fd = creat(location, 0644);
 
1936
 
 
1937
        if (regf->fd == -1) {
 
1938
                DEBUG(0,("Could not create file: %s, %s\n", location,
 
1939
                                 strerror(errno)));
 
1940
                talloc_free(regf);
 
1941
                return WERR_GENERAL_FAILURE;
 
1942
        }
 
1943
 
 
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(&regf_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;
 
1955
 
 
1956
        regf->header = regf_hdr;
 
1957
 
 
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;
 
1962
 
 
1963
        nk.header = "nk";
 
1964
        nk.type = REG_SUB_KEY;
 
1965
        unix_to_nt_time(&nk.last_change, time(NULL));
 
1966
        nk.uk1 = 0;
 
1967
        nk.parent_offset = -1;
 
1968
        nk.num_subkeys = 0;
 
1969
        nk.uk2 = 0;
 
1970
        nk.subkeys_offset = -1;
 
1971
        nk.unknown_offset = -1;
 
1972
        nk.num_values = 0;
 
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";
 
1979
 
 
1980
        /*
 
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
 
1985
         */
 
1986
 
 
1987
        /* Create a security descriptor. */
 
1988
        sd = security_descriptor_dacl_create(regf,
 
1989
                                         0,
 
1990
                                         NULL, NULL,
 
1991
                                         SID_NT_AUTHENTICATED_USERS,
 
1992
                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
 
1993
                                         SEC_GENERIC_ALL,
 
1994
                                         SEC_ACE_FLAG_OBJECT_INHERIT,
 
1995
                                         NULL);
 
1996
        
 
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;
 
2002
        }
 
2003
 
 
2004
        ZERO_STRUCT(sk);
 
2005
        sk.header = "sk";
 
2006
        sk.prev_offset = 0x80;
 
2007
        sk.next_offset = 0x80;
 
2008
        sk.ref_cnt = 1;
 
2009
        sk.rec_size = data.length;
 
2010
        sk.sec_desc = data.data;
 
2011
 
 
2012
        /* Store the new nk key */
 
2013
        regf->header->data_offset = hbin_store_tdr(regf,
 
2014
                                                   (tdr_push_fn_t)tdr_push_nk_block,
 
2015
                                                   &nk);
 
2016
        /* Store the sk block */
 
2017
        sk_offset = hbin_store_tdr(regf,
 
2018
                                   (tdr_push_fn_t) tdr_push_sk_block,
 
2019
                                   &sk);
 
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;
 
2023
        }
 
2024
 
 
2025
 
 
2026
        *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
 
2027
                                               regf->header->data_offset);
 
2028
 
 
2029
        error = regf_save_hbin(regf);
 
2030
        if (!W_ERROR_IS_OK(error)) {
 
2031
                return error;
 
2032
        }
 
2033
        
 
2034
        /* We can drop our own reference now that *key will have created one */
 
2035
        talloc_free(regf);
 
2036
 
 
2037
        return WERR_OK;
 
2038
}
 
2039
 
 
2040
WERROR reg_open_regf_file(TALLOC_CTX *parent_ctx, const char *location, 
 
2041
                          struct smb_iconv_convenience *iconv_convenience, struct hive_key **key)
 
2042
{
 
2043
        struct regf_data *regf;
 
2044
        struct regf_hdr *regf_hdr;
 
2045
        struct tdr_pull *pull;
 
2046
        int i;
 
2047
 
 
2048
        regf = (struct regf_data *)talloc_zero(parent_ctx, struct regf_data);
 
2049
 
 
2050
        regf->iconv_convenience = iconv_convenience;
 
2051
 
 
2052
        W_ERROR_HAVE_NO_MEMORY(regf);
 
2053
 
 
2054
        DEBUG(5, ("Attempting to load registry file\n"));
 
2055
 
 
2056
        /* Get the header */
 
2057
        regf->fd = open(location, O_RDWR);
 
2058
 
 
2059
        if (regf->fd == -1) {
 
2060
                DEBUG(0,("Could not load file: %s, %s\n", location,
 
2061
                                 strerror(errno)));
 
2062
                talloc_free(regf);
 
2063
                return WERR_GENERAL_FAILURE;
 
2064
        }
 
2065
 
 
2066
        pull = tdr_pull_init(regf, regf->iconv_convenience);
 
2067
 
 
2068
        pull->data.data = (uint8_t*)fd_load(regf->fd, &pull->data.length, 0, regf);
 
2069
 
 
2070
        if (pull->data.data == NULL) {
 
2071
                DEBUG(0, ("Error reading data\n"));
 
2072
                talloc_free(regf);
 
2073
                return WERR_GENERAL_FAILURE;
 
2074
        }
 
2075
 
 
2076
        regf_hdr = talloc(regf, struct regf_hdr);
 
2077
        W_ERROR_HAVE_NO_MEMORY(regf_hdr);
 
2078
 
 
2079
        if (NT_STATUS_IS_ERR(tdr_pull_regf_hdr(pull, regf_hdr, regf_hdr))) {
 
2080
                talloc_free(regf);
 
2081
                return WERR_GENERAL_FAILURE;
 
2082
        }
 
2083
 
 
2084
        regf->header = regf_hdr;
 
2085
 
 
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));
 
2089
                talloc_free(regf);
 
2090
                return WERR_GENERAL_FAILURE;
 
2091
        }
 
2092
 
 
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)));
 
2098
                talloc_free(regf);
 
2099
                return WERR_GENERAL_FAILURE;
 
2100
        }
 
2101
 
 
2102
        pull->offset = 0x1000;
 
2103
 
 
2104
        i = 0;
 
2105
        /* Read in all hbin blocks */
 
2106
        regf->hbins = talloc_array(regf, struct hbin_block *, 1);
 
2107
        W_ERROR_HAVE_NO_MEMORY(regf->hbins);
 
2108
 
 
2109
        regf->hbins[0] = NULL;
 
2110
 
 
2111
        while (pull->offset < pull->data.length &&
 
2112
               pull->offset <= regf->header->last_block) {
 
2113
                struct hbin_block *hbin = talloc(regf->hbins,
 
2114
                                                 struct hbin_block);
 
2115
 
 
2116
                W_ERROR_HAVE_NO_MEMORY(hbin);
 
2117
 
 
2118
                if (NT_STATUS_IS_ERR(tdr_pull_hbin_block(pull, hbin, hbin))) {
 
2119
                        DEBUG(0, ("[%d] Error parsing HBIN block\n", i));
 
2120
                        talloc_free(regf);
 
2121
                        return WERR_FOOBAR;
 
2122
                }
 
2123
 
 
2124
                if (strcmp(hbin->HBIN_ID, "hbin") != 0) {
 
2125
                        DEBUG(0, ("[%d] Expected 'hbin', got '%s'\n",
 
2126
                                i, hbin->HBIN_ID));
 
2127
                        talloc_free(regf);
 
2128
                        return WERR_FOOBAR;
 
2129
                }
 
2130
 
 
2131
                regf->hbins[i] = hbin;
 
2132
                i++;
 
2133
                regf->hbins = talloc_realloc(regf, regf->hbins,
 
2134
                                             struct hbin_block *, i+2);
 
2135
                regf->hbins[i] = NULL;
 
2136
        }
 
2137
 
 
2138
        talloc_free(pull);
 
2139
 
 
2140
        DEBUG(1, ("%d HBIN blocks read\n", i));
 
2141
 
 
2142
        *key = (struct hive_key *)regf_get_key(parent_ctx, regf,
 
2143
                                               regf->header->data_offset);
 
2144
 
 
2145
        /* We can drop our own reference now that *key will have created one */
 
2146
        talloc_free(regf);
 
2147
 
 
2148
        return WERR_OK;
 
2149
}
 
2150
 
 
2151
static struct hive_operations reg_backend_regf = {
 
2152
        .name = "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,
 
2164
};