~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/registry/reg_backend_db.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
 *  Unix SMB/CIFS implementation.
 
3
 *  Virtual Windows Registry Layer
 
4
 *  Copyright (C) Gerald Carter                     2002-2005
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 3 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *  
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *  
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
/* Implementation of internal registry database functions. */
 
21
 
 
22
#include "includes.h"
 
23
 
 
24
#undef DBGC_CLASS
 
25
#define DBGC_CLASS DBGC_REGISTRY
 
26
 
 
27
static struct db_context *regdb = NULL;
 
28
static int regdb_refcount;
 
29
 
 
30
static bool regdb_key_exists(const char *key);
 
31
static bool regdb_key_is_base_key(const char *key);
 
32
 
 
33
/* List the deepest path into the registry.  All part components will be created.*/
 
34
 
 
35
/* If you want to have a part of the path controlled by the tdb and part by
 
36
   a virtual registry db (e.g. printing), then you have to list the deepest path.
 
37
   For example,"HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Print" 
 
38
   allows the reg_db backend to handle everything up to 
 
39
   "HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion" and then we'll hook 
 
40
   the reg_printing backend onto the last component of the path (see 
 
41
   KEY_PRINTING_2K in include/rpc_reg.h)   --jerry */
 
42
 
 
43
static const char *builtin_registry_paths[] = {
 
44
        KEY_PRINTING_2K,
 
45
        KEY_PRINTING_PORTS,
 
46
        KEY_PRINTING,
 
47
        KEY_SHARES,
 
48
        KEY_EVENTLOG,
 
49
        KEY_SMBCONF,
 
50
        KEY_PERFLIB,
 
51
        KEY_PERFLIB_009,
 
52
        KEY_GROUP_POLICY,
 
53
        KEY_SAMBA_GROUP_POLICY,
 
54
        KEY_GP_MACHINE_POLICY,
 
55
        KEY_GP_MACHINE_WIN_POLICY,
 
56
        KEY_HKCU,
 
57
        KEY_GP_USER_POLICY,
 
58
        KEY_GP_USER_WIN_POLICY,
 
59
        KEY_WINLOGON_GPEXT_PATH,
 
60
        "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors",
 
61
        KEY_PROD_OPTIONS,
 
62
        "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\DefaultUserConfiguration",
 
63
        KEY_TCPIP_PARAMS,
 
64
        KEY_NETLOGON_PARAMS,
 
65
        KEY_HKU,
 
66
        KEY_HKCR,
 
67
        KEY_HKPD,
 
68
        KEY_HKPT,
 
69
         NULL };
 
70
 
 
71
struct builtin_regkey_value {
 
72
        const char *path;
 
73
        const char *valuename;
 
74
        uint32 type;
 
75
        union {
 
76
                const char *string;
 
77
                uint32 dw_value;
 
78
        } data;
 
79
};
 
80
 
 
81
static struct builtin_regkey_value builtin_registry_values[] = {
 
82
        { KEY_PRINTING_PORTS,
 
83
                SAMBA_PRINTER_PORT_NAME, REG_SZ, { "" } },
 
84
        { KEY_PRINTING_2K,
 
85
                "DefaultSpoolDirectory", REG_SZ, { "C:\\Windows\\System32\\Spool\\Printers" } },
 
86
        { KEY_EVENTLOG,
 
87
                "DisplayName", REG_SZ, { "Event Log" } }, 
 
88
        { KEY_EVENTLOG,
 
89
                "ErrorControl", REG_DWORD, { (char*)0x00000001 } },
 
90
        { NULL, NULL, 0, { NULL } }
 
91
};
 
92
 
 
93
/**
 
94
 * Initialize a key in the registry:
 
95
 * create each component key of the specified path.
 
96
 */
 
97
static WERROR init_registry_key_internal(const char *add_path)
 
98
{
 
99
        WERROR werr;
 
100
        TALLOC_CTX *frame = talloc_stackframe();
 
101
        char *path = NULL;
 
102
        char *base = NULL;
 
103
        char *remaining = NULL;
 
104
        char *keyname;
 
105
        char *subkeyname;
 
106
        struct regsubkey_ctr *subkeys;
 
107
        const char *p, *p2;
 
108
 
 
109
        DEBUG(6, ("init_registry_key: Adding [%s]\n", add_path));
 
110
 
 
111
        path = talloc_strdup(frame, add_path);
 
112
        base = talloc_strdup(frame, "");
 
113
        if (!path || !base) {
 
114
                werr = WERR_NOMEM;
 
115
                goto fail;
 
116
        }
 
117
        p = path;
 
118
 
 
119
        while (next_token_talloc(frame, &p, &keyname, "\\")) {
 
120
 
 
121
                /* build up the registry path from the components */
 
122
 
 
123
                if (*base) {
 
124
                        base = talloc_asprintf(frame, "%s\\", base);
 
125
                        if (!base) {
 
126
                                werr = WERR_NOMEM;
 
127
                                goto fail;
 
128
                        }
 
129
                }
 
130
                base = talloc_asprintf_append(base, "%s", keyname);
 
131
                if (!base) {
 
132
                        werr = WERR_NOMEM;
 
133
                        goto fail;
 
134
                }
 
135
 
 
136
                /* get the immediate subkeyname (if we have one ) */
 
137
 
 
138
                subkeyname = talloc_strdup(frame, "");
 
139
                if (!subkeyname) {
 
140
                        werr = WERR_NOMEM;
 
141
                        goto fail;
 
142
                }
 
143
                if (*p) {
 
144
                        remaining = talloc_strdup(frame, p);
 
145
                        if (!remaining) {
 
146
                                werr = WERR_NOMEM;
 
147
                                goto fail;
 
148
                        }
 
149
                        p2 = remaining;
 
150
 
 
151
                        if (!next_token_talloc(frame, &p2,
 
152
                                                &subkeyname, "\\"))
 
153
                        {
 
154
                                subkeyname = talloc_strdup(frame,p2);
 
155
                                if (!subkeyname) {
 
156
                                        werr = WERR_NOMEM;
 
157
                                        goto fail;
 
158
                                }
 
159
                        }
 
160
                }
 
161
 
 
162
                DEBUG(10,("init_registry_key: Storing key [%s] with "
 
163
                          "subkey [%s]\n", base,
 
164
                          *subkeyname ? subkeyname : "NULL"));
 
165
 
 
166
                /* we don't really care if the lookup succeeds or not
 
167
                 * since we are about to update the record.
 
168
                 * We just want any subkeys already present */
 
169
 
 
170
                werr = regsubkey_ctr_init(frame, &subkeys);
 
171
                if (!W_ERROR_IS_OK(werr)) {
 
172
                        DEBUG(0,("talloc() failure!\n"));
 
173
                        goto fail;
 
174
                }
 
175
 
 
176
                regdb_fetch_keys(base, subkeys);
 
177
                if (*subkeyname) {
 
178
                        werr = regsubkey_ctr_addkey(subkeys, subkeyname);
 
179
                        if (!W_ERROR_IS_OK(werr)) {
 
180
                                goto fail;
 
181
                        }
 
182
                }
 
183
                if (!regdb_store_keys( base, subkeys)) {
 
184
                        werr = WERR_CAN_NOT_COMPLETE;
 
185
                        goto fail;
 
186
                }
 
187
        }
 
188
 
 
189
        werr = WERR_OK;
 
190
 
 
191
fail:
 
192
        TALLOC_FREE(frame);
 
193
        return werr;
 
194
}
 
195
 
 
196
/**
 
197
 * Initialize a key in the registry:
 
198
 * create each component key of the specified path,
 
199
 * wrapped in one db transaction.
 
200
 */
 
201
WERROR init_registry_key(const char *add_path)
 
202
{
 
203
        WERROR werr;
 
204
 
 
205
        if (regdb_key_exists(add_path)) {
 
206
                return WERR_OK;
 
207
        }
 
208
 
 
209
        if (regdb->transaction_start(regdb) != 0) {
 
210
                DEBUG(0, ("init_registry_key: transaction_start failed\n"));
 
211
                return WERR_REG_IO_FAILURE;
 
212
        }
 
213
 
 
214
        werr = init_registry_key_internal(add_path);
 
215
        if (!W_ERROR_IS_OK(werr)) {
 
216
                goto fail;
 
217
        }
 
218
 
 
219
        if (regdb->transaction_commit(regdb) != 0) {
 
220
                DEBUG(0, ("init_registry_key: Could not commit transaction\n"));
 
221
                return WERR_REG_IO_FAILURE;
 
222
        }
 
223
 
 
224
        return WERR_OK;
 
225
 
 
226
fail:
 
227
        if (regdb->transaction_cancel(regdb) != 0) {
 
228
                smb_panic("init_registry_key: transaction_cancel failed\n");
 
229
        }
 
230
 
 
231
        return werr;
 
232
}
 
233
 
 
234
/***********************************************************************
 
235
 Open the registry data in the tdb
 
236
 ***********************************************************************/
 
237
 
 
238
WERROR init_registry_data(void)
 
239
{
 
240
        WERROR werr;
 
241
        TALLOC_CTX *frame = talloc_stackframe();
 
242
        REGVAL_CTR *values;
 
243
        int i;
 
244
        UNISTR2 data;
 
245
 
 
246
        /*
 
247
         * First, check for the existence of the needed keys and values.
 
248
         * If all do already exist, we can save the writes.
 
249
         */
 
250
        for (i=0; builtin_registry_paths[i] != NULL; i++) {
 
251
                if (!regdb_key_exists(builtin_registry_paths[i])) {
 
252
                        goto do_init;
 
253
                }
 
254
        }
 
255
 
 
256
        for (i=0; builtin_registry_values[i].path != NULL; i++) {
 
257
                values = TALLOC_ZERO_P(frame, REGVAL_CTR);
 
258
                if (values == NULL) {
 
259
                        werr = WERR_NOMEM;
 
260
                        goto done;
 
261
                }
 
262
 
 
263
                regdb_fetch_values(builtin_registry_values[i].path, values);
 
264
                if (!regval_ctr_key_exists(values,
 
265
                                        builtin_registry_values[i].valuename))
 
266
                {
 
267
                        TALLOC_FREE(values);
 
268
                        goto do_init;
 
269
                }
 
270
 
 
271
                TALLOC_FREE(values);
 
272
        }
 
273
 
 
274
        werr = WERR_OK;
 
275
        goto done;
 
276
 
 
277
do_init:
 
278
 
 
279
        /*
 
280
         * There are potentially quite a few store operations which are all
 
281
         * indiviually wrapped in tdb transactions. Wrapping them in a single
 
282
         * transaction gives just a single transaction_commit() to actually do
 
283
         * its fsync()s. See tdb/common/transaction.c for info about nested
 
284
         * transaction behaviour.
 
285
         */
 
286
 
 
287
        if (regdb->transaction_start(regdb) != 0) {
 
288
                DEBUG(0, ("init_registry_data: tdb_transaction_start "
 
289
                          "failed\n"));
 
290
                werr = WERR_REG_IO_FAILURE;
 
291
                goto done;
 
292
        }
 
293
 
 
294
        /* loop over all of the predefined paths and add each component */
 
295
 
 
296
        for (i=0; builtin_registry_paths[i] != NULL; i++) {
 
297
                if (regdb_key_exists(builtin_registry_paths[i])) {
 
298
                        continue;
 
299
                }
 
300
                werr = init_registry_key_internal(builtin_registry_paths[i]);
 
301
                if (!W_ERROR_IS_OK(werr)) {
 
302
                        goto fail;
 
303
                }
 
304
        }
 
305
 
 
306
        /* loop over all of the predefined values and add each component */
 
307
 
 
308
        for (i=0; builtin_registry_values[i].path != NULL; i++) {
 
309
 
 
310
                values = TALLOC_ZERO_P(frame, REGVAL_CTR);
 
311
                if (values == NULL) {
 
312
                        werr = WERR_NOMEM;
 
313
                        goto fail;
 
314
                }
 
315
 
 
316
                regdb_fetch_values(builtin_registry_values[i].path, values);
 
317
 
 
318
                /* preserve existing values across restarts. Only add new ones */
 
319
 
 
320
                if (!regval_ctr_key_exists(values,
 
321
                                        builtin_registry_values[i].valuename))
 
322
                {
 
323
                        switch(builtin_registry_values[i].type) {
 
324
                        case REG_DWORD:
 
325
                                regval_ctr_addvalue(values,
 
326
                                        builtin_registry_values[i].valuename,
 
327
                                        REG_DWORD,
 
328
                                        (char*)&builtin_registry_values[i].data.dw_value,
 
329
                                        sizeof(uint32));
 
330
                                break;
 
331
 
 
332
                        case REG_SZ:
 
333
                                init_unistr2(&data,
 
334
                                        builtin_registry_values[i].data.string,
 
335
                                        UNI_STR_TERMINATE);
 
336
                                regval_ctr_addvalue(values,
 
337
                                        builtin_registry_values[i].valuename,
 
338
                                        REG_SZ,
 
339
                                        (char*)data.buffer,
 
340
                                        data.uni_str_len*sizeof(uint16));
 
341
                                break;
 
342
 
 
343
                        default:
 
344
                                DEBUG(0, ("init_registry_data: invalid value "
 
345
                                          "type in builtin_registry_values "
 
346
                                          "[%d]\n",
 
347
                                          builtin_registry_values[i].type));
 
348
                        }
 
349
                        regdb_store_values(builtin_registry_values[i].path,
 
350
                                           values);
 
351
                }
 
352
                TALLOC_FREE(values);
 
353
        }
 
354
 
 
355
        if (regdb->transaction_commit(regdb) != 0) {
 
356
                DEBUG(0, ("init_registry_data: Could not commit "
 
357
                          "transaction\n"));
 
358
                werr = WERR_REG_IO_FAILURE;
 
359
        } else {
 
360
                werr = WERR_OK;
 
361
        }
 
362
 
 
363
        goto done;
 
364
 
 
365
fail:
 
366
        if (regdb->transaction_cancel(regdb) != 0) {
 
367
                smb_panic("init_registry_data: tdb_transaction_cancel "
 
368
                          "failed\n");
 
369
        }
 
370
 
 
371
done:
 
372
        TALLOC_FREE(frame);
 
373
        return werr;
 
374
}
 
375
 
 
376
/***********************************************************************
 
377
 Open the registry database
 
378
 ***********************************************************************/
 
379
 
 
380
WERROR regdb_init(void)
 
381
{
 
382
        const char *vstring = "INFO/version";
 
383
        uint32 vers_id;
 
384
        WERROR werr;
 
385
 
 
386
        if (regdb) {
 
387
                DEBUG(10, ("regdb_init: incrementing refcount (%d)\n",
 
388
                          regdb_refcount));
 
389
                regdb_refcount++;
 
390
                return WERR_OK;
 
391
        }
 
392
 
 
393
        regdb = db_open(NULL, state_path("registry.tdb"), 0,
 
394
                              REG_TDB_FLAGS, O_RDWR, 0600);
 
395
        if (!regdb) {
 
396
                regdb = db_open(NULL, state_path("registry.tdb"), 0,
 
397
                                      REG_TDB_FLAGS, O_RDWR|O_CREAT, 0600);
 
398
                if (!regdb) {
 
399
                        werr = ntstatus_to_werror(map_nt_error_from_unix(errno));
 
400
                        DEBUG(1,("regdb_init: Failed to open registry %s (%s)\n",
 
401
                                state_path("registry.tdb"), strerror(errno) ));
 
402
                        return werr;
 
403
                }
 
404
                
 
405
                DEBUG(10,("regdb_init: Successfully created registry tdb\n"));
 
406
        }
 
407
 
 
408
        regdb_refcount = 1;
 
409
 
 
410
        vers_id = dbwrap_fetch_int32(regdb, vstring);
 
411
 
 
412
        if ( vers_id != REGVER_V1 ) {
 
413
                NTSTATUS status;
 
414
                /* any upgrade code here if needed */
 
415
                DEBUG(10, ("regdb_init: got %s = %d != %d\n", vstring,
 
416
                           vers_id, REGVER_V1));
 
417
                status = dbwrap_trans_store_int32(regdb, vstring, REGVER_V1);
 
418
                if (!NT_STATUS_IS_OK(status)) {
 
419
                        DEBUG(1, ("regdb_init: error storing %s = %d: %s\n",
 
420
                                  vstring, REGVER_V1, nt_errstr(status)));
 
421
                        return ntstatus_to_werror(status);
 
422
                } else {
 
423
                        DEBUG(10, ("regdb_init: stored %s = %d\n",
 
424
                                  vstring, REGVER_V1));
 
425
                }
 
426
        }
 
427
 
 
428
        return WERR_OK;
 
429
}
 
430
 
 
431
/***********************************************************************
 
432
 Open the registry.  Must already have been initialized by regdb_init()
 
433
 ***********************************************************************/
 
434
 
 
435
WERROR regdb_open( void )
 
436
{
 
437
        WERROR result = WERR_OK;
 
438
 
 
439
        if ( regdb ) {
 
440
                DEBUG(10,("regdb_open: incrementing refcount (%d)\n", regdb_refcount));
 
441
                regdb_refcount++;
 
442
                return WERR_OK;
 
443
        }
 
444
        
 
445
        become_root();
 
446
 
 
447
        regdb = db_open(NULL, state_path("registry.tdb"), 0,
 
448
                              REG_TDB_FLAGS, O_RDWR, 0600);
 
449
        if ( !regdb ) {
 
450
                result = ntstatus_to_werror( map_nt_error_from_unix( errno ) );
 
451
                DEBUG(0,("regdb_open: Failed to open %s! (%s)\n", 
 
452
                        state_path("registry.tdb"), strerror(errno) ));
 
453
        }
 
454
 
 
455
        unbecome_root();
 
456
 
 
457
        regdb_refcount = 1;
 
458
        DEBUG(10,("regdb_open: refcount reset (%d)\n", regdb_refcount));
 
459
 
 
460
        return result;
 
461
}
 
462
 
 
463
/***********************************************************************
 
464
 ***********************************************************************/
 
465
 
 
466
int regdb_close( void )
 
467
{
 
468
        if (regdb_refcount == 0) {
 
469
                return 0;
 
470
        }
 
471
 
 
472
        regdb_refcount--;
 
473
 
 
474
        DEBUG(10,("regdb_close: decrementing refcount (%d)\n", regdb_refcount));
 
475
 
 
476
        if ( regdb_refcount > 0 )
 
477
                return 0;
 
478
 
 
479
        SMB_ASSERT( regdb_refcount >= 0 );
 
480
 
 
481
        TALLOC_FREE(regdb);
 
482
        return 0;
 
483
}
 
484
 
 
485
WERROR regdb_transaction_start(void)
 
486
{
 
487
        return (regdb->transaction_start(regdb) == 0) ?
 
488
                WERR_OK : WERR_REG_IO_FAILURE;
 
489
}
 
490
 
 
491
WERROR regdb_transaction_commit(void)
 
492
{
 
493
        return (regdb->transaction_commit(regdb) == 0) ?
 
494
                WERR_OK : WERR_REG_IO_FAILURE;
 
495
}
 
496
 
 
497
WERROR regdb_transaction_cancel(void)
 
498
{
 
499
        return (regdb->transaction_cancel(regdb) == 0) ?
 
500
                WERR_OK : WERR_REG_IO_FAILURE;
 
501
}
 
502
 
 
503
/***********************************************************************
 
504
 return the tdb sequence number of the registry tdb.
 
505
 this is an indicator for the content of the registry
 
506
 having changed. it will change upon regdb_init, too, though.
 
507
 ***********************************************************************/
 
508
int regdb_get_seqnum(void)
 
509
{
 
510
        return regdb->get_seqnum(regdb);
 
511
}
 
512
 
 
513
 
 
514
static WERROR regdb_delete_key_with_prefix(const char *keyname,
 
515
                                           const char *prefix)
 
516
{
 
517
        char *path;
 
518
        WERROR werr = WERR_NOMEM;
 
519
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
520
 
 
521
        if (keyname == NULL) {
 
522
                werr = WERR_INVALID_PARAM;
 
523
                goto done;
 
524
        }
 
525
 
 
526
        if (prefix == NULL) {
 
527
                path = discard_const_p(char, keyname);
 
528
        } else {
 
529
                path = talloc_asprintf(mem_ctx, "%s/%s", prefix, keyname);
 
530
                if (path == NULL) {
 
531
                        goto done;
 
532
                }
 
533
        }
 
534
 
 
535
        path = normalize_reg_path(mem_ctx, path);
 
536
        if (path == NULL) {
 
537
                goto done;
 
538
        }
 
539
 
 
540
        werr = ntstatus_to_werror(dbwrap_delete_bystring(regdb, path));
 
541
 
 
542
        /* treat "not" found" as ok */
 
543
        if (W_ERROR_EQUAL(werr, WERR_NOT_FOUND)) {
 
544
                werr = WERR_OK;
 
545
        }
 
546
 
 
547
done:
 
548
        talloc_free(mem_ctx);
 
549
        return werr;
 
550
}
 
551
 
 
552
 
 
553
static WERROR regdb_delete_values(const char *keyname)
 
554
{
 
555
        return regdb_delete_key_with_prefix(keyname, REG_VALUE_PREFIX);
 
556
}
 
557
 
 
558
static WERROR regdb_delete_secdesc(const char *keyname)
 
559
{
 
560
        return regdb_delete_key_with_prefix(keyname, REG_SECDESC_PREFIX);
 
561
}
 
562
 
 
563
static WERROR regdb_delete_subkeylist(const char *keyname)
 
564
{
 
565
        return regdb_delete_key_with_prefix(keyname, NULL);
 
566
}
 
567
 
 
568
static WERROR regdb_delete_key_lists(const char *keyname)
 
569
{
 
570
        WERROR werr;
 
571
 
 
572
        werr = regdb_delete_values(keyname);
 
573
        if (!W_ERROR_IS_OK(werr)) {
 
574
                DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
 
575
                          REG_VALUE_PREFIX, keyname, win_errstr(werr)));
 
576
                goto done;
 
577
        }
 
578
 
 
579
        werr = regdb_delete_secdesc(keyname);
 
580
        if (!W_ERROR_IS_OK(werr)) {
 
581
                DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
 
582
                          REG_SECDESC_PREFIX, keyname, win_errstr(werr)));
 
583
                goto done;
 
584
        }
 
585
 
 
586
        werr = regdb_delete_subkeylist(keyname);
 
587
        if (!W_ERROR_IS_OK(werr)) {
 
588
                DEBUG(1, (__location__ " Deleting %s failed: %s\n",
 
589
                          keyname, win_errstr(werr)));
 
590
                goto done;
 
591
        }
 
592
 
 
593
done:
 
594
        return werr;
 
595
}
 
596
 
 
597
/***********************************************************************
 
598
 Add subkey strings to the registry tdb under a defined key
 
599
 fmt is the same format as tdb_pack except this function only supports
 
600
 fstrings
 
601
 ***********************************************************************/
 
602
 
 
603
static bool regdb_store_keys_internal(const char *key, struct regsubkey_ctr *ctr)
 
604
{
 
605
        TDB_DATA dbuf;
 
606
        uint8 *buffer = NULL;
 
607
        int i = 0;
 
608
        uint32 len, buflen;
 
609
        bool ret = true;
 
610
        uint32 num_subkeys = regsubkey_ctr_numkeys(ctr);
 
611
        char *keyname = NULL;
 
612
        TALLOC_CTX *ctx = talloc_stackframe();
 
613
        NTSTATUS status;
 
614
 
 
615
        if (!key) {
 
616
                return false;
 
617
        }
 
618
 
 
619
        keyname = talloc_strdup(ctx, key);
 
620
        if (!keyname) {
 
621
                return false;
 
622
        }
 
623
        keyname = normalize_reg_path(ctx, keyname);
 
624
 
 
625
        /* allocate some initial memory */
 
626
 
 
627
        buffer = (uint8 *)SMB_MALLOC(1024);
 
628
        if (buffer == NULL) {
 
629
                return false;
 
630
        }
 
631
        buflen = 1024;
 
632
        len = 0;
 
633
 
 
634
        /* store the number of subkeys */
 
635
 
 
636
        len += tdb_pack(buffer+len, buflen-len, "d", num_subkeys);
 
637
 
 
638
        /* pack all the strings */
 
639
 
 
640
        for (i=0; i<num_subkeys; i++) {
 
641
                size_t thistime;
 
642
 
 
643
                thistime = tdb_pack(buffer+len, buflen-len, "f",
 
644
                                    regsubkey_ctr_specific_key(ctr, i));
 
645
                if (len+thistime > buflen) {
 
646
                        size_t thistime2;
 
647
                        /*
 
648
                         * tdb_pack hasn't done anything because of the short
 
649
                         * buffer, allocate extra space.
 
650
                         */
 
651
                        buffer = SMB_REALLOC_ARRAY(buffer, uint8_t,
 
652
                                                   (len+thistime)*2);
 
653
                        if(buffer == NULL) {
 
654
                                DEBUG(0, ("regdb_store_keys: Failed to realloc "
 
655
                                          "memory of size [%u]\n",
 
656
                                          (unsigned int)(len+thistime)*2));
 
657
                                ret = false;
 
658
                                goto done;
 
659
                        }
 
660
                        buflen = (len+thistime)*2;
 
661
                        thistime2 = tdb_pack(
 
662
                                buffer+len, buflen-len, "f",
 
663
                                regsubkey_ctr_specific_key(ctr, i));
 
664
                        if (thistime2 != thistime) {
 
665
                                DEBUG(0, ("tdb_pack failed\n"));
 
666
                                ret = false;
 
667
                                goto done;
 
668
                        }
 
669
                }
 
670
                len += thistime;
 
671
        }
 
672
 
 
673
        /* finally write out the data */
 
674
 
 
675
        dbuf.dptr = buffer;
 
676
        dbuf.dsize = len;
 
677
        status = dbwrap_store_bystring(regdb, keyname, dbuf, TDB_REPLACE);
 
678
        if (!NT_STATUS_IS_OK(status)) {
 
679
                ret = false;
 
680
                goto done;
 
681
        }
 
682
 
 
683
        /*
 
684
         * Delete a sorted subkey cache for regdb_key_exists, will be
 
685
         * recreated automatically
 
686
         */
 
687
        keyname = talloc_asprintf(ctx, "%s/%s", REG_SORTED_SUBKEYS_PREFIX,
 
688
                                  keyname);
 
689
        if (keyname != NULL) {
 
690
                dbwrap_delete_bystring(regdb, keyname);
 
691
        }
 
692
 
 
693
done:
 
694
        TALLOC_FREE(ctx);
 
695
        SAFE_FREE(buffer);
 
696
        return ret;
 
697
}
 
698
 
 
699
/***********************************************************************
 
700
 Store the new subkey record and create any child key records that
 
701
 do not currently exist
 
702
 ***********************************************************************/
 
703
 
 
704
bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr)
 
705
{
 
706
        int num_subkeys, old_num_subkeys, i;
 
707
        char *path = NULL;
 
708
        struct regsubkey_ctr *subkeys = NULL, *old_subkeys = NULL;
 
709
        char *oldkeyname = NULL;
 
710
        TALLOC_CTX *ctx = talloc_stackframe();
 
711
        WERROR werr;
 
712
 
 
713
        if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) {
 
714
                goto fail;
 
715
        }
 
716
 
 
717
        /*
 
718
         * fetch a list of the old subkeys so we can determine if anything has
 
719
         * changed
 
720
         */
 
721
 
 
722
        werr = regsubkey_ctr_init(ctx, &old_subkeys);
 
723
        if (!W_ERROR_IS_OK(werr)) {
 
724
                DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
 
725
                return false;
 
726
        }
 
727
 
 
728
        regdb_fetch_keys(key, old_subkeys);
 
729
 
 
730
        num_subkeys = regsubkey_ctr_numkeys(ctr);
 
731
        old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
 
732
        if ((num_subkeys && old_num_subkeys) &&
 
733
            (num_subkeys == old_num_subkeys)) {
 
734
 
 
735
                for (i = 0; i < num_subkeys; i++) {
 
736
                        if (strcmp(regsubkey_ctr_specific_key(ctr, i),
 
737
                                   regsubkey_ctr_specific_key(old_subkeys, i))
 
738
                            != 0)
 
739
                        {
 
740
                                break;
 
741
                        }
 
742
                }
 
743
                if (i == num_subkeys) {
 
744
                        /*
 
745
                         * Nothing changed, no point to even start a tdb
 
746
                         * transaction
 
747
                         */
 
748
                        TALLOC_FREE(old_subkeys);
 
749
                        return true;
 
750
                }
 
751
        }
 
752
 
 
753
        TALLOC_FREE(old_subkeys);
 
754
 
 
755
        if (regdb->transaction_start(regdb) != 0) {
 
756
                DEBUG(0, ("regdb_store_keys: transaction_start failed\n"));
 
757
                goto fail;
 
758
        }
 
759
 
 
760
        /*
 
761
         * Re-fetch the old keys inside the transaction
 
762
         */
 
763
 
 
764
        werr = regsubkey_ctr_init(ctx, &old_subkeys);
 
765
        if (!W_ERROR_IS_OK(werr)) {
 
766
                DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
 
767
                goto cancel;
 
768
        }
 
769
 
 
770
        regdb_fetch_keys(key, old_subkeys);
 
771
 
 
772
        /*
 
773
         * Make the store operation as safe as possible without transactions:
 
774
         *
 
775
         * (1) For each subkey removed from ctr compared with old_subkeys:
 
776
         *
 
777
         *     (a) First delete the value db entry.
 
778
         *
 
779
         *     (b) Next delete the secdesc db record.
 
780
         *
 
781
         *     (c) Then delete the subkey list entry.
 
782
         *
 
783
         * (2) Now write the list of subkeys of the parent key,
 
784
         *     deleting removed entries and adding new ones.
 
785
         *
 
786
         * (3) Finally create the subkey list entries for the added keys.
 
787
         *
 
788
         * This way if we crash half-way in between deleting the subkeys
 
789
         * and storing the parent's list of subkeys, no old data can pop up
 
790
         * out of the blue when re-adding keys later on.
 
791
         */
 
792
 
 
793
        /* (1) delete removed keys' lists (values/secdesc/subkeys) */
 
794
 
 
795
        num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
 
796
        for (i=0; i<num_subkeys; i++) {
 
797
                oldkeyname = regsubkey_ctr_specific_key(old_subkeys, i);
 
798
 
 
799
                if (regsubkey_ctr_key_exists(ctr, oldkeyname)) {
 
800
                        /*
 
801
                         * It's still around, don't delete
 
802
                         */
 
803
 
 
804
                        continue;
 
805
                }
 
806
 
 
807
                path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname);
 
808
                if (!path) {
 
809
                        goto cancel;
 
810
                }
 
811
 
 
812
                werr = regdb_delete_key_lists(path);
 
813
                W_ERROR_NOT_OK_GOTO(werr, cancel);
 
814
 
 
815
                TALLOC_FREE(path);
 
816
        }
 
817
 
 
818
        TALLOC_FREE(old_subkeys);
 
819
 
 
820
        /* (2) store the subkey list for the parent */
 
821
 
 
822
        if (!regdb_store_keys_internal(key, ctr) ) {
 
823
                DEBUG(0,("regdb_store_keys: Failed to store new subkey list "
 
824
                         "for parent [%s]\n", key));
 
825
                goto cancel;
 
826
        }
 
827
 
 
828
        /* (3) now create records for any subkeys that don't already exist */
 
829
 
 
830
        num_subkeys = regsubkey_ctr_numkeys(ctr);
 
831
 
 
832
        if (num_subkeys == 0) {
 
833
                werr = regsubkey_ctr_init(ctx, &subkeys);
 
834
                if (!W_ERROR_IS_OK(werr)) {
 
835
                        DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
 
836
                        goto cancel;
 
837
                }
 
838
 
 
839
                if (!regdb_store_keys_internal(key, subkeys)) {
 
840
                        DEBUG(0,("regdb_store_keys: Failed to store "
 
841
                                 "new record for key [%s]\n", key));
 
842
                        goto cancel;
 
843
                }
 
844
                TALLOC_FREE(subkeys);
 
845
 
 
846
        }
 
847
 
 
848
        for (i=0; i<num_subkeys; i++) {
 
849
                path = talloc_asprintf(ctx, "%s/%s",
 
850
                                        key,
 
851
                                        regsubkey_ctr_specific_key(ctr, i));
 
852
                if (!path) {
 
853
                        goto cancel;
 
854
                }
 
855
                werr = regsubkey_ctr_init(ctx, &subkeys);
 
856
                if (!W_ERROR_IS_OK(werr)) {
 
857
                        DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
 
858
                        goto cancel;
 
859
                }
 
860
 
 
861
                if (regdb_fetch_keys( path, subkeys ) == -1) {
 
862
                        /* create a record with 0 subkeys */
 
863
                        if (!regdb_store_keys_internal(path, subkeys)) {
 
864
                                DEBUG(0,("regdb_store_keys: Failed to store "
 
865
                                         "new record for key [%s]\n", path));
 
866
                                goto cancel;
 
867
                        }
 
868
                }
 
869
 
 
870
                TALLOC_FREE(subkeys);
 
871
                TALLOC_FREE(path);
 
872
        }
 
873
 
 
874
        if (regdb->transaction_commit(regdb) != 0) {
 
875
                DEBUG(0, ("regdb_store_keys: Could not commit transaction\n"));
 
876
                goto fail;
 
877
        }
 
878
 
 
879
        TALLOC_FREE(ctx);
 
880
        return true;
 
881
 
 
882
cancel:
 
883
        if (regdb->transaction_cancel(regdb) != 0) {
 
884
                smb_panic("regdb_store_keys: transaction_cancel failed\n");
 
885
        }
 
886
 
 
887
fail:
 
888
        TALLOC_FREE(ctx);
 
889
 
 
890
        return false;
 
891
}
 
892
 
 
893
static WERROR regdb_create_subkey(const char *key, const char *subkey)
 
894
{
 
895
        WERROR werr;
 
896
        struct regsubkey_ctr *subkeys;
 
897
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
898
 
 
899
        if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) {
 
900
                werr = WERR_NOT_FOUND;
 
901
                goto done;
 
902
        }
 
903
 
 
904
        werr = regsubkey_ctr_init(mem_ctx, &subkeys);
 
905
        W_ERROR_NOT_OK_GOTO_DONE(werr);
 
906
 
 
907
        if (regdb_fetch_keys(key, subkeys) < 0) {
 
908
                werr = WERR_REG_IO_FAILURE;
 
909
                goto done;
 
910
        }
 
911
 
 
912
        if (regsubkey_ctr_key_exists(subkeys, subkey)) {
 
913
                werr = WERR_OK;
 
914
                goto done;
 
915
        }
 
916
 
 
917
        talloc_free(subkeys);
 
918
 
 
919
        werr = regdb_transaction_start();
 
920
        W_ERROR_NOT_OK_GOTO_DONE(werr);
 
921
 
 
922
        werr = regsubkey_ctr_init(mem_ctx, &subkeys);
 
923
        W_ERROR_NOT_OK_GOTO(werr, cancel);
 
924
 
 
925
        if (regdb_fetch_keys(key, subkeys) < 0) {
 
926
                werr = WERR_REG_IO_FAILURE;
 
927
                goto cancel;
 
928
        }
 
929
 
 
930
        werr = regsubkey_ctr_addkey(subkeys, subkey);
 
931
        W_ERROR_NOT_OK_GOTO(werr, cancel);
 
932
 
 
933
        if (!regdb_store_keys_internal(key, subkeys)) {
 
934
                DEBUG(0, (__location__ " failed to store new subkey list for "
 
935
                         "parent key %s\n", key));
 
936
                werr = WERR_REG_IO_FAILURE;
 
937
                goto cancel;
 
938
        }
 
939
 
 
940
        werr = regdb_transaction_commit();
 
941
        if (!W_ERROR_IS_OK(werr)) {
 
942
                DEBUG(0, (__location__ " failed to commit transaction: %s\n",
 
943
                         win_errstr(werr)));
 
944
        }
 
945
 
 
946
        goto done;
 
947
 
 
948
cancel:
 
949
        werr = regdb_transaction_cancel();
 
950
        if (!W_ERROR_IS_OK(werr)) {
 
951
                DEBUG(0, (__location__ " failed to cancel transaction: %s\n",
 
952
                         win_errstr(werr)));
 
953
        }
 
954
 
 
955
done:
 
956
        talloc_free(mem_ctx);
 
957
        return werr;
 
958
}
 
959
 
 
960
static WERROR regdb_delete_subkey(const char *key, const char *subkey)
 
961
{
 
962
        WERROR werr, werr2;
 
963
        struct regsubkey_ctr *subkeys;
 
964
        char *path;
 
965
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
966
 
 
967
        if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) {
 
968
                werr = WERR_NOT_FOUND;
 
969
                goto done;
 
970
        }
 
971
 
 
972
        path = talloc_asprintf(mem_ctx, "%s/%s", key, subkey);
 
973
        if (path == NULL) {
 
974
                werr = WERR_NOMEM;
 
975
                goto done;
 
976
        }
 
977
 
 
978
        if (!regdb_key_exists(path)) {
 
979
                werr = WERR_OK;
 
980
                goto done;
 
981
        }
 
982
 
 
983
        werr = regdb_transaction_start();
 
984
        W_ERROR_NOT_OK_GOTO_DONE(werr);
 
985
 
 
986
        werr = regdb_delete_key_lists(path);
 
987
        W_ERROR_NOT_OK_GOTO(werr, cancel);
 
988
 
 
989
        werr = regsubkey_ctr_init(mem_ctx, &subkeys);
 
990
        W_ERROR_NOT_OK_GOTO(werr, cancel);
 
991
 
 
992
        if (regdb_fetch_keys(key, subkeys) < 0) {
 
993
                werr = WERR_REG_IO_FAILURE;
 
994
                goto cancel;
 
995
        }
 
996
 
 
997
        werr = regsubkey_ctr_delkey(subkeys, subkey);
 
998
        W_ERROR_NOT_OK_GOTO(werr, cancel);
 
999
 
 
1000
        if (!regdb_store_keys_internal(key, subkeys)) {
 
1001
                DEBUG(0, (__location__ " failed to store new subkey_list for "
 
1002
                         "parent key %s\n", key));
 
1003
                werr = WERR_REG_IO_FAILURE;
 
1004
                goto cancel;
 
1005
        }
 
1006
 
 
1007
        werr = regdb_transaction_commit();
 
1008
        if (!W_ERROR_IS_OK(werr)) {
 
1009
                DEBUG(0, (__location__ " failed to commit transaction: %s\n",
 
1010
                         win_errstr(werr)));
 
1011
        }
 
1012
 
 
1013
        goto done;
 
1014
 
 
1015
cancel:
 
1016
        werr2 = regdb_transaction_cancel();
 
1017
        if (!W_ERROR_IS_OK(werr2)) {
 
1018
                DEBUG(0, (__location__ " failed to cancel transaction: %s\n",
 
1019
                         win_errstr(werr2)));
 
1020
        }
 
1021
 
 
1022
done:
 
1023
        talloc_free(mem_ctx);
 
1024
        return werr;
 
1025
}
 
1026
 
 
1027
static TDB_DATA regdb_fetch_key_internal(TALLOC_CTX *mem_ctx, const char *key)
 
1028
{
 
1029
        char *path = NULL;
 
1030
        TDB_DATA data;
 
1031
 
 
1032
        path = normalize_reg_path(mem_ctx, key);
 
1033
        if (!path) {
 
1034
                return make_tdb_data(NULL, 0);
 
1035
        }
 
1036
 
 
1037
        data = dbwrap_fetch_bystring(regdb, mem_ctx, path);
 
1038
 
 
1039
        TALLOC_FREE(path);
 
1040
        return data;
 
1041
}
 
1042
 
 
1043
 
 
1044
/**
 
1045
 * check whether a given key name represents a base key,
 
1046
 * i.e one without a subkey separator ('/' or '\').
 
1047
 */
 
1048
static bool regdb_key_is_base_key(const char *key)
 
1049
{
 
1050
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
1051
        bool ret = false;
 
1052
        char *path;
 
1053
 
 
1054
        if (key == NULL) {
 
1055
                goto done;
 
1056
        }
 
1057
 
 
1058
        path = normalize_reg_path(mem_ctx, key);
 
1059
        if (path == NULL) {
 
1060
                DEBUG(0, ("out of memory! (talloc failed)\n"));
 
1061
                goto done;
 
1062
        }
 
1063
 
 
1064
        if (*path == '\0') {
 
1065
                goto done;
 
1066
        }
 
1067
 
 
1068
        ret = (strrchr(path, '/') == NULL);
 
1069
 
 
1070
done:
 
1071
        TALLOC_FREE(mem_ctx);
 
1072
        return ret;
 
1073
}
 
1074
 
 
1075
/*
 
1076
 * regdb_key_exists() is a very frequent operation. It can be quite
 
1077
 * time-consuming to fully fetch the parent's subkey list, talloc_strdup all
 
1078
 * subkeys and then compare the keyname linearly to all the parent's subkeys.
 
1079
 *
 
1080
 * The following code tries to make this operation as efficient as possible:
 
1081
 * Per registry key we create a list of subkeys that is very efficient to
 
1082
 * search for existence of a subkey. Its format is:
 
1083
 *
 
1084
 * 4 bytes num_subkeys
 
1085
 * 4*num_subkey bytes offset into the string array
 
1086
 * then follows a sorted list of subkeys in uppercase
 
1087
 *
 
1088
 * This record is created by create_sorted_subkeys() on demand if it does not
 
1089
 * exist. scan_parent_subkeys() uses regdb->parse_record to search the sorted
 
1090
 * list, the parsing code and the binary search can be found in
 
1091
 * parent_subkey_scanner. The code uses parse_record() to avoid a memcpy of
 
1092
 * the potentially large subkey record.
 
1093
 *
 
1094
 * The sorted subkey record is deleted in regdb_store_keys_internal and
 
1095
 * recreated on demand.
 
1096
 */
 
1097
 
 
1098
static int cmp_keynames(const void *p1, const void *p2)
 
1099
{
 
1100
        return StrCaseCmp(*((char **)p1), *((char **)p2));
 
1101
}
 
1102
 
 
1103
static bool create_sorted_subkeys(const char *key, const char *sorted_keyname)
 
1104
{
 
1105
        char **sorted_subkeys;
 
1106
        struct regsubkey_ctr *ctr;
 
1107
        bool result = false;
 
1108
        NTSTATUS status;
 
1109
        char *buf;
 
1110
        char *p;
 
1111
        int i, res;
 
1112
        size_t len;
 
1113
        int num_subkeys;
 
1114
        WERROR werr;
 
1115
 
 
1116
        if (regdb->transaction_start(regdb) != 0) {
 
1117
                DEBUG(0, ("create_sorted_subkeys: transaction_start "
 
1118
                          "failed\n"));
 
1119
                return false;
 
1120
        }
 
1121
 
 
1122
        werr = regsubkey_ctr_init(talloc_tos(), &ctr);
 
1123
        if (!W_ERROR_IS_OK(werr)) {
 
1124
                goto fail;
 
1125
        }
 
1126
 
 
1127
        res = regdb_fetch_keys(key, ctr);
 
1128
        if (res == -1) {
 
1129
                goto fail;
 
1130
        }
 
1131
 
 
1132
        num_subkeys = regsubkey_ctr_numkeys(ctr);
 
1133
        sorted_subkeys = talloc_array(ctr, char *, num_subkeys);
 
1134
        if (sorted_subkeys == NULL) {
 
1135
                goto fail;
 
1136
        }
 
1137
 
 
1138
        len = 4 + 4*num_subkeys;
 
1139
 
 
1140
        for (i = 0; i < num_subkeys; i++) {
 
1141
                sorted_subkeys[i] = talloc_strdup_upper(sorted_subkeys,
 
1142
                                        regsubkey_ctr_specific_key(ctr, i));
 
1143
                if (sorted_subkeys[i] == NULL) {
 
1144
                        goto fail;
 
1145
                }
 
1146
                len += strlen(sorted_subkeys[i])+1;
 
1147
        }
 
1148
 
 
1149
        qsort(sorted_subkeys, num_subkeys, sizeof(char *), cmp_keynames);
 
1150
 
 
1151
        buf = talloc_array(ctr, char, len);
 
1152
        if (buf == NULL) {
 
1153
                goto fail;
 
1154
        }
 
1155
        p = buf + 4 + 4*num_subkeys;
 
1156
 
 
1157
        SIVAL(buf, 0, num_subkeys);
 
1158
 
 
1159
        for (i=0; i < num_subkeys; i++) {
 
1160
                ptrdiff_t offset = p - buf;
 
1161
                SIVAL(buf, 4 + 4*i, offset);
 
1162
                strlcpy(p, sorted_subkeys[i], len-offset);
 
1163
                p += strlen(sorted_subkeys[i]) + 1;
 
1164
        }
 
1165
 
 
1166
        status = dbwrap_store_bystring(
 
1167
                regdb, sorted_keyname, make_tdb_data((uint8_t *)buf, len),
 
1168
                TDB_REPLACE);
 
1169
        if (!NT_STATUS_IS_OK(status)) {
 
1170
                /*
 
1171
                 * Don't use a "goto fail;" here, this would commit the broken
 
1172
                 * transaction. See below for an explanation.
 
1173
                 */
 
1174
                if (regdb->transaction_cancel(regdb) == -1) {
 
1175
                        DEBUG(0, ("create_sorted_subkeys: transaction_cancel "
 
1176
                                  "failed\n"));
 
1177
                }
 
1178
                TALLOC_FREE(ctr);
 
1179
                return false;
 
1180
        }
 
1181
 
 
1182
        result = true;
 
1183
 fail:
 
1184
        /*
 
1185
         * We only get here via the "goto fail" when we did not write anything
 
1186
         * yet. Using transaction_commit even in a failure case is necessary
 
1187
         * because this (disposable) call might be nested in other
 
1188
         * transactions. Doing a cancel here would destroy the possibility of
 
1189
         * a transaction_commit for transactions that we might be wrapped in.
 
1190
         */
 
1191
        if (regdb->transaction_commit(regdb) == -1) {
 
1192
                DEBUG(0, ("create_sorted_subkeys: transaction_start "
 
1193
                          "failed\n"));
 
1194
                goto fail;
 
1195
        }
 
1196
 
 
1197
        TALLOC_FREE(ctr);
 
1198
        return result;
 
1199
}
 
1200
 
 
1201
struct scan_subkey_state {
 
1202
        char *name;
 
1203
        bool scanned;
 
1204
        bool found;
 
1205
};
 
1206
 
 
1207
static int parent_subkey_scanner(TDB_DATA key, TDB_DATA data,
 
1208
                                 void *private_data)
 
1209
{
 
1210
        struct scan_subkey_state *state =
 
1211
                (struct scan_subkey_state *)private_data;
 
1212
        uint32_t num_subkeys;
 
1213
        uint32_t l, u;
 
1214
 
 
1215
        if (data.dsize < sizeof(uint32_t)) {
 
1216
                return -1;
 
1217
        }
 
1218
 
 
1219
        state->scanned = true;
 
1220
        state->found = false;
 
1221
 
 
1222
        tdb_unpack(data.dptr, data.dsize, "d", &num_subkeys);
 
1223
 
 
1224
        l = 0;
 
1225
        u = num_subkeys;
 
1226
 
 
1227
        while (l < u) {
 
1228
                uint32_t idx = (l+u)/2;
 
1229
                char *s = (char *)data.dptr + IVAL(data.dptr, 4 + 4*idx);
 
1230
                int comparison = strcmp(state->name, s);
 
1231
 
 
1232
                if (comparison < 0) {
 
1233
                        u = idx;
 
1234
                } else if (comparison > 0) {
 
1235
                        l = idx + 1;
 
1236
                } else {
 
1237
                        state->found = true;
 
1238
                        return 0;
 
1239
                }
 
1240
        }
 
1241
        return 0;
 
1242
}
 
1243
 
 
1244
static bool scan_parent_subkeys(const char *parent, const char *name)
 
1245
{
 
1246
        char *path = NULL;
 
1247
        char *key = NULL;
 
1248
        struct scan_subkey_state state = { 0, };
 
1249
        bool result = false;
 
1250
        int res;
 
1251
 
 
1252
        state.name = NULL;
 
1253
 
 
1254
        path = normalize_reg_path(talloc_tos(), parent);
 
1255
        if (path == NULL) {
 
1256
                goto fail;
 
1257
        }
 
1258
 
 
1259
        key = talloc_asprintf(talloc_tos(), "%s/%s",
 
1260
                              REG_SORTED_SUBKEYS_PREFIX, path);
 
1261
        if (key == NULL) {
 
1262
                goto fail;
 
1263
        }
 
1264
 
 
1265
        state.name = talloc_strdup_upper(talloc_tos(), name);
 
1266
        if (state.name == NULL) {
 
1267
                goto fail;
 
1268
        }
 
1269
        state.scanned = false;
 
1270
 
 
1271
        res = regdb->parse_record(regdb, string_term_tdb_data(key),
 
1272
                                  parent_subkey_scanner, &state);
 
1273
 
 
1274
        if (state.scanned) {
 
1275
                result = state.found;
 
1276
        } else {
 
1277
                if (!create_sorted_subkeys(path, key)) {
 
1278
                        goto fail;
 
1279
                }
 
1280
                res = regdb->parse_record(regdb, string_term_tdb_data(key),
 
1281
                                          parent_subkey_scanner, &state);
 
1282
                if ((res == 0) && (state.scanned)) {
 
1283
                        result = state.found;
 
1284
                }
 
1285
        }
 
1286
 
 
1287
 fail:
 
1288
        TALLOC_FREE(path);
 
1289
        TALLOC_FREE(state.name);
 
1290
        return result;
 
1291
}
 
1292
 
 
1293
/**
 
1294
 * Check for the existence of a key.
 
1295
 *
 
1296
 * Existence of a key is authoritatively defined by its
 
1297
 * existence in the list of subkeys of its parent key.
 
1298
 * The exeption of this are keys without a parent key,
 
1299
 * i.e. the "base" keys (HKLM, HKCU, ...).
 
1300
 */
 
1301
static bool regdb_key_exists(const char *key)
 
1302
{
 
1303
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
1304
        TDB_DATA value;
 
1305
        bool ret = false;
 
1306
        char *path, *p;
 
1307
 
 
1308
        if (key == NULL) {
 
1309
                goto done;
 
1310
        }
 
1311
 
 
1312
        path = normalize_reg_path(mem_ctx, key);
 
1313
        if (path == NULL) {
 
1314
                DEBUG(0, ("out of memory! (talloc failed)\n"));
 
1315
                goto done;
 
1316
        }
 
1317
 
 
1318
        if (*path == '\0') {
 
1319
                goto done;
 
1320
        }
 
1321
 
 
1322
        p = strrchr(path, '/');
 
1323
        if (p == NULL) {
 
1324
                /* this is a base key */
 
1325
                value = regdb_fetch_key_internal(mem_ctx, path);
 
1326
                ret = (value.dptr != NULL);
 
1327
        } else {
 
1328
                *p = '\0';
 
1329
                ret = scan_parent_subkeys(path, p+1);
 
1330
        }
 
1331
 
 
1332
done:
 
1333
        TALLOC_FREE(mem_ctx);
 
1334
        return ret;
 
1335
}
 
1336
 
 
1337
 
 
1338
/***********************************************************************
 
1339
 Retrieve an array of strings containing subkeys.  Memory should be
 
1340
 released by the caller.
 
1341
 ***********************************************************************/
 
1342
 
 
1343
int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr)
 
1344
{
 
1345
        WERROR werr;
 
1346
        uint32 num_items;
 
1347
        uint8 *buf;
 
1348
        uint32 buflen, len;
 
1349
        int i;
 
1350
        fstring subkeyname;
 
1351
        int ret = -1;
 
1352
        TALLOC_CTX *frame = talloc_stackframe();
 
1353
        TDB_DATA value;
 
1354
 
 
1355
        DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL"));
 
1356
 
 
1357
        if (!regdb_key_exists(key)) {
 
1358
                goto done;
 
1359
        }
 
1360
 
 
1361
        werr = regsubkey_ctr_set_seqnum(ctr, regdb_get_seqnum());
 
1362
        if (!W_ERROR_IS_OK(werr)) {
 
1363
                goto done;
 
1364
        }
 
1365
 
 
1366
        value = regdb_fetch_key_internal(frame, key);
 
1367
 
 
1368
        if (value.dptr == NULL) {
 
1369
                DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n",
 
1370
                           key));
 
1371
                ret = 0;
 
1372
                goto done;
 
1373
        }
 
1374
 
 
1375
        buf = value.dptr;
 
1376
        buflen = value.dsize;
 
1377
        len = tdb_unpack( buf, buflen, "d", &num_items);
 
1378
 
 
1379
        for (i=0; i<num_items; i++) {
 
1380
                len += tdb_unpack(buf+len, buflen-len, "f", subkeyname);
 
1381
                werr = regsubkey_ctr_addkey(ctr, subkeyname);
 
1382
                if (!W_ERROR_IS_OK(werr)) {
 
1383
                        DEBUG(5, ("regdb_fetch_keys: regsubkey_ctr_addkey "
 
1384
                                  "failed: %s\n", win_errstr(werr)));
 
1385
                        goto done;
 
1386
                }
 
1387
        }
 
1388
 
 
1389
        DEBUG(11,("regdb_fetch_keys: Exit [%d] items\n", num_items));
 
1390
 
 
1391
        ret = num_items;
 
1392
done:
 
1393
        TALLOC_FREE(frame);
 
1394
        return ret;
 
1395
}
 
1396
 
 
1397
/****************************************************************************
 
1398
 Unpack a list of registry values frem the TDB
 
1399
 ***************************************************************************/
 
1400
 
 
1401
static int regdb_unpack_values(REGVAL_CTR *values, uint8 *buf, int buflen)
 
1402
{
 
1403
        int             len = 0;
 
1404
        uint32          type;
 
1405
        fstring valuename;
 
1406
        uint32          size;
 
1407
        uint8           *data_p;
 
1408
        uint32          num_values = 0;
 
1409
        int             i;
 
1410
 
 
1411
        /* loop and unpack the rest of the registry values */
 
1412
 
 
1413
        len += tdb_unpack(buf+len, buflen-len, "d", &num_values);
 
1414
 
 
1415
        for ( i=0; i<num_values; i++ ) {
 
1416
                /* unpack the next regval */
 
1417
 
 
1418
                type = REG_NONE;
 
1419
                size = 0;
 
1420
                data_p = NULL;
 
1421
                valuename[0] = '\0';
 
1422
                len += tdb_unpack(buf+len, buflen-len, "fdB",
 
1423
                                  valuename,
 
1424
                                  &type,
 
1425
                                  &size,
 
1426
                                  &data_p);
 
1427
 
 
1428
                /* add the new value. Paranoid protective code -- make sure data_p is valid */
 
1429
 
 
1430
                if (*valuename && size && data_p) {
 
1431
                        regval_ctr_addvalue(values, valuename, type,
 
1432
                                        (const char *)data_p, size);
 
1433
                }
 
1434
                SAFE_FREE(data_p); /* 'B' option to tdb_unpack does a malloc() */
 
1435
 
 
1436
                DEBUG(8,("specific: [%s], len: %d\n", valuename, size));
 
1437
        }
 
1438
 
 
1439
        return len;
 
1440
}
 
1441
 
 
1442
/****************************************************************************
 
1443
 Pack all values in all printer keys
 
1444
 ***************************************************************************/
 
1445
 
 
1446
static int regdb_pack_values(REGVAL_CTR *values, uint8 *buf, int buflen)
 
1447
{
 
1448
        int             len = 0;
 
1449
        int             i;
 
1450
        REGISTRY_VALUE  *val;
 
1451
        int             num_values;
 
1452
 
 
1453
        if ( !values )
 
1454
                return 0;
 
1455
 
 
1456
        num_values = regval_ctr_numvals( values );
 
1457
 
 
1458
        /* pack the number of values first */
 
1459
 
 
1460
        len += tdb_pack( buf+len, buflen-len, "d", num_values );
 
1461
 
 
1462
        /* loop over all values */
 
1463
 
 
1464
        for ( i=0; i<num_values; i++ ) {
 
1465
                val = regval_ctr_specific_value( values, i );
 
1466
                len += tdb_pack(buf+len, buflen-len, "fdB",
 
1467
                                regval_name(val),
 
1468
                                regval_type(val),
 
1469
                                regval_size(val),
 
1470
                                regval_data_p(val) );
 
1471
        }
 
1472
 
 
1473
        return len;
 
1474
}
 
1475
 
 
1476
/***********************************************************************
 
1477
 Retrieve an array of strings containing subkeys.  Memory should be
 
1478
 released by the caller.
 
1479
 ***********************************************************************/
 
1480
 
 
1481
int regdb_fetch_values( const char* key, REGVAL_CTR *values )
 
1482
{
 
1483
        char *keystr = NULL;
 
1484
        TALLOC_CTX *ctx = talloc_stackframe();
 
1485
        int ret = 0;
 
1486
        TDB_DATA value;
 
1487
 
 
1488
        DEBUG(10,("regdb_fetch_values: Looking for value of key [%s] \n", key));
 
1489
 
 
1490
        if (!regdb_key_exists(key)) {
 
1491
                goto done;
 
1492
        }
 
1493
 
 
1494
        keystr = talloc_asprintf(ctx, "%s/%s", REG_VALUE_PREFIX, key);
 
1495
        if (!keystr) {
 
1496
                goto done;
 
1497
        }
 
1498
 
 
1499
        values->seqnum = regdb_get_seqnum();
 
1500
 
 
1501
        value = regdb_fetch_key_internal(ctx, keystr);
 
1502
 
 
1503
        if (!value.dptr) {
 
1504
                /* all keys have zero values by default */
 
1505
                goto done;
 
1506
        }
 
1507
 
 
1508
        regdb_unpack_values(values, value.dptr, value.dsize);
 
1509
        ret = regval_ctr_numvals(values);
 
1510
 
 
1511
done:
 
1512
        TALLOC_FREE(ctx);
 
1513
        return ret;
 
1514
}
 
1515
 
 
1516
bool regdb_store_values( const char *key, REGVAL_CTR *values )
 
1517
{
 
1518
        TDB_DATA old_data, data;
 
1519
        char *keystr = NULL;
 
1520
        TALLOC_CTX *ctx = talloc_stackframe();
 
1521
        int len;
 
1522
        NTSTATUS status;
 
1523
        bool result = false;
 
1524
 
 
1525
        DEBUG(10,("regdb_store_values: Looking for value of key [%s] \n", key));
 
1526
 
 
1527
        if (!regdb_key_exists(key)) {
 
1528
                goto done;
 
1529
        }
 
1530
 
 
1531
        ZERO_STRUCT(data);
 
1532
 
 
1533
        len = regdb_pack_values(values, data.dptr, data.dsize);
 
1534
        if (len <= 0) {
 
1535
                DEBUG(0,("regdb_store_values: unable to pack values. len <= 0\n"));
 
1536
                goto done;
 
1537
        }
 
1538
 
 
1539
        data.dptr = TALLOC_ARRAY(ctx, uint8, len);
 
1540
        data.dsize = len;
 
1541
 
 
1542
        len = regdb_pack_values(values, data.dptr, data.dsize);
 
1543
 
 
1544
        SMB_ASSERT( len == data.dsize );
 
1545
 
 
1546
        keystr = talloc_asprintf(ctx, "%s/%s", REG_VALUE_PREFIX, key );
 
1547
        if (!keystr) {
 
1548
                goto done;
 
1549
        }
 
1550
        keystr = normalize_reg_path(ctx, keystr);
 
1551
        if (!keystr) {
 
1552
                goto done;
 
1553
        }
 
1554
 
 
1555
        old_data = dbwrap_fetch_bystring(regdb, ctx, keystr);
 
1556
 
 
1557
        if ((old_data.dptr != NULL)
 
1558
            && (old_data.dsize == data.dsize)
 
1559
            && (memcmp(old_data.dptr, data.dptr, data.dsize) == 0))
 
1560
        {
 
1561
                result = true;
 
1562
                goto done;
 
1563
        }
 
1564
 
 
1565
        status = dbwrap_trans_store_bystring(regdb, keystr, data, TDB_REPLACE);
 
1566
 
 
1567
        result = NT_STATUS_IS_OK(status);
 
1568
 
 
1569
done:
 
1570
        TALLOC_FREE(ctx);
 
1571
        return result;
 
1572
}
 
1573
 
 
1574
static WERROR regdb_get_secdesc(TALLOC_CTX *mem_ctx, const char *key,
 
1575
                                struct security_descriptor **psecdesc)
 
1576
{
 
1577
        char *tdbkey;
 
1578
        TDB_DATA data;
 
1579
        NTSTATUS status;
 
1580
        TALLOC_CTX *tmp_ctx = talloc_stackframe();
 
1581
        WERROR err = WERR_OK;
 
1582
 
 
1583
        DEBUG(10, ("regdb_get_secdesc: Getting secdesc of key [%s]\n", key));
 
1584
 
 
1585
        if (!regdb_key_exists(key)) {
 
1586
                err = WERR_BADFILE;
 
1587
                goto done;
 
1588
        }
 
1589
 
 
1590
        tdbkey = talloc_asprintf(tmp_ctx, "%s/%s", REG_SECDESC_PREFIX, key);
 
1591
        if (tdbkey == NULL) {
 
1592
                err = WERR_NOMEM;
 
1593
                goto done;
 
1594
        }
 
1595
        normalize_dbkey(tdbkey);
 
1596
 
 
1597
        data = dbwrap_fetch_bystring(regdb, tmp_ctx, tdbkey);
 
1598
        if (data.dptr == NULL) {
 
1599
                err = WERR_BADFILE;
 
1600
                goto done;
 
1601
        }
 
1602
 
 
1603
        status = unmarshall_sec_desc(mem_ctx, (uint8 *)data.dptr, data.dsize,
 
1604
                                     psecdesc);
 
1605
 
 
1606
        if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
 
1607
                err = WERR_NOMEM;
 
1608
        } else if (!NT_STATUS_IS_OK(status)) {
 
1609
                err = WERR_REG_CORRUPT;
 
1610
        }
 
1611
 
 
1612
done:
 
1613
        TALLOC_FREE(tmp_ctx);
 
1614
        return err;
 
1615
}
 
1616
 
 
1617
static WERROR regdb_set_secdesc(const char *key,
 
1618
                                struct security_descriptor *secdesc)
 
1619
{
 
1620
        TALLOC_CTX *mem_ctx = talloc_stackframe();
 
1621
        char *tdbkey;
 
1622
        WERROR err = WERR_NOMEM;
 
1623
        TDB_DATA tdbdata;
 
1624
 
 
1625
        if (!regdb_key_exists(key)) {
 
1626
                err = WERR_BADFILE;
 
1627
                goto done;
 
1628
        }
 
1629
 
 
1630
        tdbkey = talloc_asprintf(mem_ctx, "%s/%s", REG_SECDESC_PREFIX, key);
 
1631
        if (tdbkey == NULL) {
 
1632
                goto done;
 
1633
        }
 
1634
        normalize_dbkey(tdbkey);
 
1635
 
 
1636
        if (secdesc == NULL) {
 
1637
                /* assuming a delete */
 
1638
                err = ntstatus_to_werror(dbwrap_trans_delete_bystring(regdb,
 
1639
                                                                      tdbkey));
 
1640
                goto done;
 
1641
        }
 
1642
 
 
1643
        err = ntstatus_to_werror(marshall_sec_desc(mem_ctx, secdesc,
 
1644
                                                   &tdbdata.dptr,
 
1645
                                                   &tdbdata.dsize));
 
1646
        W_ERROR_NOT_OK_GOTO_DONE(err);
 
1647
 
 
1648
        err = ntstatus_to_werror(dbwrap_trans_store_bystring(regdb, tdbkey,
 
1649
                                                             tdbdata, 0));
 
1650
 
 
1651
 done:
 
1652
        TALLOC_FREE(mem_ctx);
 
1653
        return err;
 
1654
}
 
1655
 
 
1656
bool regdb_subkeys_need_update(struct regsubkey_ctr *subkeys)
 
1657
{
 
1658
        return (regdb_get_seqnum() != regsubkey_ctr_get_seqnum(subkeys));
 
1659
}
 
1660
 
 
1661
bool regdb_values_need_update(REGVAL_CTR *values)
 
1662
{
 
1663
        return (regdb_get_seqnum() != values->seqnum);
 
1664
}
 
1665
 
 
1666
/* 
 
1667
 * Table of function pointers for default access
 
1668
 */
 
1669
 
 
1670
REGISTRY_OPS regdb_ops = {
 
1671
        .fetch_subkeys = regdb_fetch_keys,
 
1672
        .fetch_values = regdb_fetch_values,
 
1673
        .store_subkeys = regdb_store_keys,
 
1674
        .store_values = regdb_store_values,
 
1675
        .create_subkey = regdb_create_subkey,
 
1676
        .delete_subkey = regdb_delete_subkey,
 
1677
        .get_secdesc = regdb_get_secdesc,
 
1678
        .set_secdesc = regdb_set_secdesc,
 
1679
        .subkeys_need_update = regdb_subkeys_need_update,
 
1680
        .values_need_update = regdb_values_need_update
 
1681
};