Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/registry/reg_backend_db.c
Line
Count
Source
1
/* 
2
 *  Unix SMB/CIFS implementation.
3
 *  Virtual Windows Registry Layer
4
 *  Copyright (C) Gerald Carter                     2002-2005
5
 *  Copyright (C) Michael Adam                      2007-2011
6
 *  Copyright (C) Gregor Beck                       2011
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License as published by
10
 *  the Free Software Foundation; either version 3 of the License, or
11
 *  (at your option) any later version.
12
 *  
13
 *  This program is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *  GNU General Public License for more details.
17
 *  
18
 *  You should have received a copy of the GNU General Public License
19
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
/* Implementation of internal registry database functions. */
23
24
#include "includes.h"
25
#include "system/filesys.h"
26
#include "registry.h"
27
#include "reg_db.h"
28
#include "reg_util_internal.h"
29
#include "reg_parse_internal.h"
30
#include "reg_backend_db.h"
31
#include "reg_objects.h"
32
#include "nt_printing.h"
33
#include "util_tdb.h"
34
#include "dbwrap/dbwrap.h"
35
#include "dbwrap/dbwrap_open.h"
36
#include "../libcli/security/secdesc.h"
37
38
#undef DBGC_CLASS
39
0
#define DBGC_CLASS DBGC_REGISTRY
40
41
0
#define REGDB_VERSION_KEYNAME "INFO/version"
42
43
static struct db_context *regdb = NULL;
44
static int regdb_refcount;
45
46
static bool regdb_key_exists(struct db_context *db, const char *key);
47
static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
48
          struct regsubkey_ctr *ctr);
49
static bool regdb_store_keys_internal(struct db_context *db, const char *key,
50
              struct regsubkey_ctr *ctr);
51
static int regdb_fetch_values_internal(struct db_context *db, const char* key,
52
               struct regval_ctr *values);
53
static NTSTATUS regdb_store_values_internal(struct db_context *db, const char *key,
54
              struct regval_ctr *values);
55
static WERROR regdb_store_subkey_list(struct db_context *db, const char *parent,
56
              const char *key);
57
58
static WERROR regdb_create_basekey(struct db_context *db, const char *key);
59
static WERROR regdb_create_subkey_internal(struct db_context *db,
60
             const char *key,
61
             const char *subkey);
62
63
64
struct regdb_trans_ctx {
65
  NTSTATUS (*action)(struct db_context *, void *);
66
  void *private_data;
67
};
68
69
static NTSTATUS regdb_trans_do_action(struct db_context *db, void *private_data)
70
0
{
71
0
  NTSTATUS status;
72
0
  int32_t version_id;
73
0
  struct regdb_trans_ctx *ctx = (struct regdb_trans_ctx *)private_data;
74
75
0
  status = dbwrap_fetch_int32_bystring(db, REGDB_VERSION_KEYNAME,
76
0
               &version_id);
77
78
0
  if (!NT_STATUS_IS_OK(status)) {
79
0
    DEBUG(0, ("ERROR: could not fetch registry db version: %s. "
80
0
        "Denying access.\n", nt_errstr(status)));
81
0
    return NT_STATUS_ACCESS_DENIED;
82
0
  }
83
84
0
  if (version_id != REGDB_CODE_VERSION) {
85
0
    DEBUG(0, ("ERROR: changed registry version %d found while "
86
0
        "trying to write to the registry. Version %d "
87
0
        "expected.  Denying access.\n",
88
0
        version_id, REGDB_CODE_VERSION));
89
0
    return NT_STATUS_ACCESS_DENIED;
90
0
  }
91
92
0
  status = ctx->action(db,  ctx->private_data);
93
0
  return status;
94
0
}
95
96
static WERROR regdb_trans_do(struct db_context *db,
97
           NTSTATUS (*action)(struct db_context *, void *),
98
           void *private_data)
99
0
{
100
0
  NTSTATUS status;
101
0
  struct regdb_trans_ctx ctx;
102
103
104
0
  ctx.action = action;
105
0
  ctx.private_data = private_data;
106
107
0
  status = dbwrap_trans_do(db, regdb_trans_do_action, &ctx);
108
109
0
  return ntstatus_to_werror(status);
110
0
}
111
112
/* List the deepest path into the registry.  All part components will be created.*/
113
114
/* If you want to have a part of the path controlled by the tdb and part by
115
   a virtual registry db (e.g. printing), then you have to list the deepest path.
116
   For example,"HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Print" 
117
   allows the reg_db backend to handle everything up to 
118
   "HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion" and then we'll hook 
119
   the reg_printing backend onto the last component of the path (see 
120
   KEY_PRINTING_2K in include/rpc_reg.h)   --jerry */
121
122
static const char *builtin_registry_paths[] = {
123
  KEY_PRINTING_2K,
124
  KEY_PCC,
125
  KEY_PRINTING_PORTS,
126
  KEY_PRINTING,
127
  KEY_PRINTING "\\Forms",
128
  KEY_PRINTING "\\Printers",
129
  KEY_PRINTING "\\Environments\\Windows NT x86\\Print Processors\\winprint",
130
  KEY_PRINTING "\\Environments\\Windows x64\\Print Processors\\winprint",
131
  KEY_SHARES,
132
  KEY_EVENTLOG,
133
  KEY_SMBCONF,
134
  KEY_PERFLIB,
135
  KEY_PERFLIB_009,
136
  KEY_GROUP_POLICY,
137
  KEY_SAMBA_GROUP_POLICY,
138
  KEY_GP_MACHINE_POLICY,
139
  KEY_GP_MACHINE_WIN_POLICY,
140
  KEY_HKCU,
141
  KEY_GP_USER_POLICY,
142
  KEY_GP_USER_WIN_POLICY,
143
  "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions",
144
  "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors",
145
  KEY_PROD_OPTIONS,
146
  "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\DefaultUserConfiguration",
147
  KEY_TCPIP_PARAMS,
148
  KEY_NETLOGON_PARAMS,
149
  KEY_HKU,
150
  KEY_HKCR,
151
  KEY_HKPD,
152
  KEY_HKPT,
153
   NULL };
154
155
struct builtin_regkey_value {
156
  const char *path;
157
  const char *valuename;
158
  uint32_t type;
159
  union {
160
    const char *string;
161
    uint32_t dw_value;
162
  } data;
163
};
164
165
static struct builtin_regkey_value builtin_registry_values[] = {
166
  { KEY_PRINTING_PORTS,
167
    SAMBA_PRINTER_PORT_NAME, REG_SZ, { "" } },
168
  { KEY_PRINTING_2K,
169
    "DefaultSpoolDirectory", REG_SZ, { "C:\\Windows\\System32\\Spool\\Printers" } },
170
  { KEY_EVENTLOG,
171
    "DisplayName", REG_SZ, { "Event Log" } },
172
  { KEY_EVENTLOG,
173
    "ErrorControl", REG_DWORD, { (char*)0x00000001 } },
174
  { NULL, NULL, 0, { NULL } }
175
};
176
177
static WERROR create_key_recursive(struct db_context *db,
178
           char *path,
179
           const char *subkey)
180
0
{
181
0
  WERROR werr;
182
0
  char *p;
183
184
0
  if (subkey == NULL) {
185
0
    return WERR_INVALID_PARAMETER;
186
0
  }
187
188
0
  if (path == NULL) {
189
0
    return regdb_create_basekey(db, subkey);
190
0
  }
191
192
0
  p = strrchr_m(path, '\\');
193
194
0
  if (p == NULL) {
195
0
    werr = create_key_recursive(db, NULL, path);
196
0
  } else {
197
0
    *p = '\0';
198
0
    werr = create_key_recursive(db, path, p+1);
199
0
    *p = '\\';
200
0
  }
201
202
0
  if (!W_ERROR_IS_OK(werr)) {
203
0
    goto done;
204
0
  }
205
206
0
  werr = regdb_create_subkey_internal(db, path, subkey);
207
208
0
done:
209
0
  return werr;
210
0
}
211
212
/**
213
 * Initialize a key in the registry:
214
 * create each component key of the specified path.
215
 */
216
static WERROR init_registry_key_internal(struct db_context *db,
217
           const char *add_path)
218
0
{
219
0
  char *subkey, *key;
220
0
  WERROR werr;
221
0
  TALLOC_CTX *frame = talloc_stackframe();
222
223
0
  if (add_path == NULL) {
224
0
    werr = WERR_INVALID_PARAMETER;
225
0
    goto done;
226
0
  }
227
228
0
  key = talloc_strdup(frame, add_path);
229
230
0
  subkey = strrchr_m(key, '\\');
231
0
  if (subkey == NULL) {
232
0
    subkey = key;
233
0
    key = NULL;
234
0
  } else {
235
0
    *subkey = '\0';
236
0
    subkey++;
237
0
  }
238
239
0
  werr = create_key_recursive(db, key, subkey);
240
241
0
done:
242
0
  talloc_free(frame);
243
0
  return werr;
244
0
}
245
246
struct init_registry_key_context {
247
  const char *add_path;
248
};
249
250
static NTSTATUS init_registry_key_action(struct db_context *db,
251
           void *private_data)
252
0
{
253
0
  struct init_registry_key_context *init_ctx =
254
0
    (struct init_registry_key_context *)private_data;
255
256
0
  return werror_to_ntstatus(init_registry_key_internal(
257
0
          db, init_ctx->add_path));
258
0
}
259
260
/**
261
 * Initialize a key in the registry:
262
 * create each component key of the specified path,
263
 * wrapped in one db transaction.
264
 */
265
WERROR init_registry_key(const char *add_path)
266
0
{
267
0
  struct init_registry_key_context init_ctx;
268
269
0
  if (regdb_key_exists(regdb, add_path)) {
270
0
    return WERR_OK;
271
0
  }
272
273
0
  init_ctx.add_path = add_path;
274
275
0
  return regdb_trans_do(regdb,
276
0
            init_registry_key_action,
277
0
            &init_ctx);
278
0
}
279
280
/***********************************************************************
281
 Open the registry data in the tdb
282
 ***********************************************************************/
283
284
static void regdb_ctr_add_value(struct regval_ctr *ctr,
285
        struct builtin_regkey_value *value)
286
0
{
287
0
  switch(value->type) {
288
0
  case REG_DWORD:
289
0
    regval_ctr_addvalue(ctr, value->valuename, REG_DWORD,
290
0
            (uint8_t *)&value->data.dw_value,
291
0
            sizeof(uint32_t));
292
0
    break;
293
294
0
  case REG_SZ:
295
0
    regval_ctr_addvalue_sz(ctr, value->valuename,
296
0
               value->data.string);
297
0
    break;
298
299
0
  default:
300
0
    DEBUG(0, ("regdb_ctr_add_value: invalid value type in "
301
0
        "registry values [%d]\n", value->type));
302
0
  }
303
0
}
304
305
static NTSTATUS init_registry_data_action(struct db_context *db,
306
            void *private_data)
307
0
{
308
0
  NTSTATUS status;
309
0
  TALLOC_CTX *frame = talloc_stackframe();
310
0
  struct regval_ctr *values;
311
0
  int i;
312
313
  /* loop over all of the predefined paths and add each component */
314
315
0
  for (i=0; builtin_registry_paths[i] != NULL; i++) {
316
0
    if (regdb_key_exists(db, builtin_registry_paths[i])) {
317
0
      continue;
318
0
    }
319
0
    status = werror_to_ntstatus(init_registry_key_internal(db,
320
0
              builtin_registry_paths[i]));
321
0
    if (!NT_STATUS_IS_OK(status)) {
322
0
      goto done;
323
0
    }
324
0
  }
325
326
  /* loop over all of the predefined values and add each component */
327
328
0
  for (i=0; builtin_registry_values[i].path != NULL; i++) {
329
0
    WERROR werr;
330
331
0
    werr = regval_ctr_init(frame, &values);
332
0
    if (!W_ERROR_IS_OK(werr)) {
333
0
      status = werror_to_ntstatus(werr);
334
0
      goto done;
335
0
    }
336
337
0
    regdb_fetch_values_internal(db,
338
0
              builtin_registry_values[i].path,
339
0
              values);
340
341
    /* preserve existing values across restarts. Only add new ones */
342
343
0
    if (!regval_ctr_value_exists(values,
344
0
          builtin_registry_values[i].valuename))
345
0
    {
346
0
      regdb_ctr_add_value(values,
347
0
              &builtin_registry_values[i]);
348
0
      status = regdb_store_values_internal(db,
349
0
          builtin_registry_values[i].path,
350
0
          values);
351
0
      if (!NT_STATUS_IS_OK(status)) {
352
0
        goto done;
353
0
      }
354
0
    }
355
0
    TALLOC_FREE(values);
356
0
  }
357
358
0
  status = NT_STATUS_OK;
359
360
0
done:
361
362
0
  TALLOC_FREE(frame);
363
0
  return status;
364
0
}
365
366
WERROR init_registry_data(void)
367
0
{
368
0
  WERROR werr;
369
0
  TALLOC_CTX *frame = talloc_stackframe();
370
0
  struct regval_ctr *values;
371
0
  int i;
372
373
  /*
374
   * First, check for the existence of the needed keys and values.
375
   * If all do already exist, we can save the writes.
376
   */
377
0
  for (i=0; builtin_registry_paths[i] != NULL; i++) {
378
0
    if (!regdb_key_exists(regdb, builtin_registry_paths[i])) {
379
0
      goto do_init;
380
0
    }
381
0
  }
382
383
0
  for (i=0; builtin_registry_values[i].path != NULL; i++) {
384
0
    werr = regval_ctr_init(frame, &values);
385
0
    W_ERROR_NOT_OK_GOTO_DONE(werr);
386
387
0
    regdb_fetch_values_internal(regdb,
388
0
              builtin_registry_values[i].path,
389
0
              values);
390
0
    if (!regval_ctr_value_exists(values,
391
0
          builtin_registry_values[i].valuename))
392
0
    {
393
0
      TALLOC_FREE(values);
394
0
      goto do_init;
395
0
    }
396
397
0
    TALLOC_FREE(values);
398
0
  }
399
400
0
  werr = WERR_OK;
401
0
  goto done;
402
403
0
do_init:
404
405
  /*
406
   * There are potentially quite a few store operations which are all
407
   * individually wrapped in tdb transactions. Wrapping them in a single
408
   * transaction gives just a single transaction_commit() to actually do
409
   * its fsync()s. See tdb/common/transaction.c for info about nested
410
   * transaction behaviour.
411
   */
412
413
0
  werr = regdb_trans_do(regdb,
414
0
            init_registry_data_action,
415
0
            NULL);
416
417
0
done:
418
0
  TALLOC_FREE(frame);
419
0
  return werr;
420
0
}
421
422
static int regdb_normalize_keynames_fn(struct db_record *rec,
423
               void *private_data)
424
0
{
425
0
  TALLOC_CTX *mem_ctx = talloc_tos();
426
0
  const char *keyname;
427
0
  NTSTATUS status;
428
0
  TDB_DATA key;
429
0
  TDB_DATA value;
430
0
  struct db_context *db = (struct db_context *)private_data;
431
432
0
  key = dbwrap_record_get_key(rec);
433
0
  if (key.dptr == NULL || key.dsize == 0) {
434
0
    return 0;
435
0
  }
436
437
0
  value = dbwrap_record_get_value(rec);
438
439
0
  if (db == NULL) {
440
0
    DEBUG(0, ("regdb_normalize_keynames_fn: ERROR: "
441
0
        "NULL db context handed in via private_data\n"));
442
0
    return 1;
443
0
  }
444
445
0
  if (strncmp((const char *)key.dptr, REGDB_VERSION_KEYNAME,
446
0
      strlen(REGDB_VERSION_KEYNAME)) == 0)
447
0
  {
448
0
    return 0;
449
0
  }
450
451
0
  keyname = strchr((const char *)key.dptr, '/');
452
0
  if (keyname) {
453
0
    keyname = talloc_string_sub(mem_ctx,
454
0
              (const char *)key.dptr,
455
0
              "/",
456
0
              "\\");
457
458
0
    DEBUG(2, ("regdb_normalize_keynames_fn: Convert %s to %s\n",
459
0
        (const char *)key.dptr,
460
0
        keyname));
461
462
    /* Delete the original record and store the normalized key */
463
0
    status = dbwrap_record_delete(rec);
464
0
    if (!NT_STATUS_IS_OK(status)) {
465
0
      DEBUG(0,("regdb_normalize_keynames_fn: "
466
0
         "tdb_delete for [%s] failed!\n",
467
0
         (const char *)key.dptr));
468
0
      return 1;
469
0
    }
470
471
0
    status = dbwrap_store_bystring(db, keyname, value, TDB_REPLACE);
472
0
    if (!NT_STATUS_IS_OK(status)) {
473
0
      DEBUG(0,("regdb_normalize_keynames_fn: "
474
0
         "failed to store new record for [%s]!\n",
475
0
         keyname));
476
0
      return 1;
477
0
    }
478
0
  }
479
480
0
  return 0;
481
0
}
482
483
static WERROR regdb_store_regdb_version(struct db_context *db, uint32_t version)
484
0
{
485
0
  NTSTATUS status;
486
0
  if (db == NULL) {
487
0
    return WERR_CAN_NOT_COMPLETE;
488
0
  }
489
490
0
  status = dbwrap_trans_store_int32_bystring(db, REGDB_VERSION_KEYNAME,
491
0
               version);
492
0
  if (!NT_STATUS_IS_OK(status)) {
493
0
    DEBUG(1, ("regdb_store_regdb_version: error storing %s = %d: %s\n",
494
0
        REGDB_VERSION_KEYNAME, version, nt_errstr(status)));
495
0
    return ntstatus_to_werror(status);
496
0
  } else {
497
0
    DEBUG(10, ("regdb_store_regdb_version: stored %s = %d\n",
498
0
        REGDB_VERSION_KEYNAME, version));
499
0
    return WERR_OK;
500
0
  }
501
0
}
502
503
static WERROR regdb_upgrade_v1_to_v2(struct db_context *db)
504
0
{
505
0
  TALLOC_CTX *mem_ctx;
506
0
  NTSTATUS status;
507
0
  WERROR werr;
508
509
0
  mem_ctx = talloc_stackframe();
510
511
0
  status = dbwrap_traverse(db, regdb_normalize_keynames_fn, db, NULL);
512
0
  if (!NT_STATUS_IS_OK(status)) {
513
0
    werr = WERR_REGISTRY_IO_FAILED;
514
0
    goto done;
515
0
  }
516
517
0
  werr = regdb_store_regdb_version(db, REGDB_VERSION_V2);
518
519
0
done:
520
0
  talloc_free(mem_ctx);
521
0
  return werr;
522
0
}
523
524
static bool tdb_data_read_uint32(TDB_DATA *buf, uint32_t *result)
525
0
{
526
0
  const size_t len = sizeof(uint32_t);
527
0
  if (buf->dsize >= len) {
528
0
    *result = IVAL(buf->dptr, 0);
529
0
    buf->dptr += len;
530
0
    buf->dsize -= len;
531
0
    return true;
532
0
  }
533
0
  return false;
534
0
}
535
536
static bool tdb_data_read_cstr(TDB_DATA *buf, char **result)
537
0
{
538
0
  const size_t len = strnlen((char*)buf->dptr, buf->dsize) + 1;
539
0
  if (buf->dsize >= len) {
540
0
    *result = (char*)buf->dptr;
541
0
    buf->dptr += len;
542
0
    buf->dsize -= len;
543
0
    return true;
544
0
  }
545
0
  return false;
546
0
}
547
548
0
static bool tdb_data_is_cstr(TDB_DATA d) {
549
0
  if (tdb_data_is_empty(d) || (d.dptr[d.dsize-1] != '\0')) {
550
0
    return false;
551
0
  }
552
0
  return strlen((char *)d.dptr) == (d.dsize-1);
553
0
}
554
555
static bool upgrade_v2_to_v3_check_subkeylist(struct db_context *db,
556
                const char *key,
557
                const char *subkey)
558
0
{
559
0
  static uint32_t zero = 0;
560
0
  static TDB_DATA empty_subkey_list = {
561
0
    .dptr = (unsigned char*)&zero,
562
0
    .dsize = sizeof(uint32_t),
563
0
  };
564
0
  bool success = false;
565
0
  char *path = talloc_asprintf(talloc_tos(), "%s\\%s", key, subkey);
566
0
  if (!strupper_m(path)) {
567
0
    goto done;
568
0
  }
569
570
0
  if (!dbwrap_exists(db, string_term_tdb_data(path))) {
571
0
    NTSTATUS status;
572
573
0
    DEBUG(10, ("regdb_upgrade_v2_to_v3: writing subkey list [%s]\n",
574
0
         path));
575
576
0
    status = dbwrap_store_bystring(db, path, empty_subkey_list,
577
0
                 TDB_INSERT);
578
0
    if (!NT_STATUS_IS_OK(status)) {
579
0
      DEBUG(0, ("regdb_upgrade_v2_to_v3: writing subkey list "
580
0
          "[%s] failed\n", path));
581
0
      goto done;
582
0
    }
583
0
  }
584
0
  success = true;
585
0
done:
586
0
  talloc_free(path);
587
0
  return success;
588
0
}
589
590
static bool upgrade_v2_to_v3_check_parent(struct db_context *db,
591
            const char *key)
592
0
{
593
0
  const char *sep = strrchr_m(key, '\\');
594
0
  if (sep != NULL) {
595
0
    char *pkey = talloc_strndup(talloc_tos(), key, sep-key);
596
0
    if (!dbwrap_exists(db, string_term_tdb_data(pkey))) {
597
0
      DEBUG(0, ("regdb_upgrade_v2_to_v3: missing subkey list "
598
0
          "[%s]\nrun \"net registry check\"\n", pkey));
599
0
    }
600
0
    talloc_free(pkey);
601
0
  }
602
0
  return true;
603
0
}
604
605
606
0
#define IS_EQUAL(d,s) (((d).dsize == strlen(s)+1) && \
607
0
           (strcmp((char*)(d).dptr, (s)) == 0))
608
0
#define STARTS_WITH(d,s) (((d).dsize > strlen(s)) &&     \
609
0
        (strncmp((char*)(d).dptr, (s), strlen(s)) == 0))
610
#define SSTR(d) (int)(d).dsize , (char*)(d).dptr
611
612
613
static int regdb_upgrade_v2_to_v3_fn(struct db_record *rec, void *private_data)
614
0
{
615
0
  struct db_context *db = (struct db_context *)private_data;
616
0
  TDB_DATA key = dbwrap_record_get_key(rec);
617
0
  TDB_DATA val = dbwrap_record_get_value(rec);
618
619
0
  if (tdb_data_is_empty(key)) {
620
0
    return 0;
621
0
  }
622
623
0
  if (db == NULL) {
624
0
    DEBUG(0, ("regdb_upgrade_v2_to_v3_fn: ERROR: "
625
0
        "NULL db context handed in via private_data\n"));
626
0
    return 1;
627
0
  }
628
629
0
  if (IS_EQUAL(key, REGDB_VERSION_KEYNAME) ||
630
0
      STARTS_WITH(key, REG_VALUE_PREFIX) ||
631
0
      STARTS_WITH(key, REG_SECDESC_PREFIX))
632
0
  {
633
0
    DEBUG(10, ("regdb_upgrade_v2_to_v3: skipping [%.*s]\n",
634
0
         SSTR(key)));
635
0
    return 0;
636
0
  }
637
638
0
  if (STARTS_WITH(key, REG_SORTED_SUBKEYS_PREFIX)) {
639
0
    NTSTATUS status;
640
    /* Delete the deprecated sorted subkeys cache. */
641
642
0
    DEBUG(10, ("regdb_upgrade_v2_to_v3: deleting [%.*s]\n",
643
0
         SSTR(key)));
644
645
0
    status = dbwrap_record_delete(rec);
646
0
    if (!NT_STATUS_IS_OK(status)) {
647
0
      DEBUG(0, ("regdb_upgrade_v2_to_v3: deleting [%.*s] "
648
0
          "failed!\n", SSTR(key)));
649
0
      return 1;
650
0
    }
651
652
0
    return 0;
653
0
  }
654
655
0
  if ( tdb_data_is_cstr(key) &&
656
0
       hive_info((char*)key.dptr) != NULL )
657
0
  {
658
    /*
659
     * Found a regular subkey list record.
660
     * Walk the list and create the list record for those
661
     * subkeys that don't already have one.
662
     */
663
0
    TDB_DATA pos = val;
664
0
    char *subkey, *path = (char*)key.dptr;
665
0
    uint32_t num_items, found_items = 0;
666
667
668
0
    DEBUG(10, ("regdb_upgrade_v2_to_v3: scanning subkeylist of "
669
0
         "[%s]\n", path));
670
671
0
    if (!tdb_data_read_uint32(&pos, &num_items)) {
672
      /* invalid or empty - skip */
673
0
      return 0;
674
0
    }
675
676
0
    while (tdb_data_read_cstr(&pos, &subkey)) {
677
0
      found_items++;
678
679
0
      if (!upgrade_v2_to_v3_check_subkeylist(db, path, subkey))
680
0
      {
681
0
        return 1;
682
0
      }
683
684
0
      if (!upgrade_v2_to_v3_check_parent(db, path)) {
685
0
        return 1;
686
0
      }
687
0
    }
688
0
    if (found_items != num_items) {
689
0
      DEBUG(0, ("regdb_upgrade_v2_to_v3: inconsistent subkey "
690
0
          "list [%s]\nrun \"net registry check\"\n",
691
0
          path));
692
0
    }
693
0
  } else {
694
0
    DEBUG(10, ("regdb_upgrade_v2_to_v3: skipping invalid [%.*s]\n"
695
0
         "run \"net registry check\"\n", SSTR(key)));
696
0
  }
697
698
0
  return 0;
699
0
}
700
701
static WERROR regdb_upgrade_v2_to_v3(struct db_context *db)
702
0
{
703
0
  NTSTATUS status;
704
0
  WERROR werr;
705
706
0
  status = dbwrap_traverse(db, regdb_upgrade_v2_to_v3_fn, db, NULL);
707
0
  if (!NT_STATUS_IS_OK(status)) {
708
0
    werr = WERR_REGISTRY_IO_FAILED;
709
0
    goto done;
710
0
  }
711
712
0
  werr = regdb_store_regdb_version(db, REGDB_VERSION_V3);
713
714
0
done:
715
0
  return werr;
716
0
}
717
718
/***********************************************************************
719
 Open the registry database
720
 ***********************************************************************/
721
722
WERROR regdb_init(void)
723
0
{
724
0
  int32_t vers_id;
725
0
  WERROR werr;
726
0
  NTSTATUS status;
727
0
  char *db_path;
728
729
0
  if (regdb) {
730
0
    DEBUG(10, ("regdb_init: incrementing refcount (%d->%d)\n",
731
0
         regdb_refcount, regdb_refcount+1));
732
0
    regdb_refcount++;
733
0
    return WERR_OK;
734
0
  }
735
736
        /*
737
         * Clustered Samba can only work as root because we need messaging to
738
         * talk to ctdb which only works as root.
739
         */
740
0
        if (!uid_wrapper_enabled() && lp_clustering() && geteuid() != 0) {
741
0
                DBG_ERR("Cluster mode requires running as root.\n");
742
0
    return WERR_ACCESS_DENIED;
743
0
        }
744
745
0
  db_path = state_path(talloc_tos(), "registry.tdb");
746
0
  if (db_path == NULL) {
747
0
    return WERR_NOT_ENOUGH_MEMORY;
748
0
  }
749
750
0
  regdb = db_open(NULL, db_path, 0,
751
0
      REG_TDB_FLAGS, O_RDWR, 0600,
752
0
      DBWRAP_LOCK_ORDER_1, REG_DBWRAP_FLAGS);
753
0
  if (!regdb) {
754
0
    regdb = db_open(NULL, db_path, 0,
755
0
        REG_TDB_FLAGS, O_RDWR|O_CREAT, 0600,
756
0
        DBWRAP_LOCK_ORDER_1, REG_DBWRAP_FLAGS);
757
0
    if (!regdb) {
758
0
      werr = ntstatus_to_werror(map_nt_error_from_unix(errno));
759
0
      DEBUG(1,("regdb_init: Failed to open registry %s (%s)\n",
760
0
        db_path, strerror(errno) ));
761
0
      TALLOC_FREE(db_path);
762
0
      return werr;
763
0
    }
764
765
0
    werr = regdb_store_regdb_version(regdb, REGDB_CODE_VERSION);
766
0
    if (!W_ERROR_IS_OK(werr)) {
767
0
      DEBUG(1, ("regdb_init: Failed to store version: %s\n",
768
0
          win_errstr(werr)));
769
0
      TALLOC_FREE(db_path);
770
0
      return werr;
771
0
    }
772
773
0
    DEBUG(10,("regdb_init: Successfully created registry tdb\n"));
774
0
  }
775
0
  TALLOC_FREE(db_path);
776
777
0
  regdb_refcount = 1;
778
0
  DEBUG(10, ("regdb_init: registry db opened. refcount reset (%d)\n",
779
0
       regdb_refcount));
780
781
0
  status = dbwrap_fetch_int32_bystring(regdb, REGDB_VERSION_KEYNAME,
782
0
               &vers_id);
783
0
  if (!NT_STATUS_IS_OK(status)) {
784
0
    DBG_DEBUG("Reading registry version failed: %s, "
785
0
        "initializing to version %d\n",
786
0
        nt_errstr(status), REGDB_VERSION_V1);
787
788
    /*
789
     * There was a regdb format version prior to version 1
790
     * which did not store a INFO/version key. The format
791
     * of this version was identical to version 1 except for
792
     * the lack of the sorted subkey cache records.
793
     * Since these are disposable, we can safely assume version
794
     * 1 if no INFO/version key is found and run the db through
795
     * the whole chain of upgrade. If the database was not
796
     * initialized, this does not harm. If it was the unversioned
797
     * version ("0"), then it do the right thing with the records.
798
     */
799
0
    werr = regdb_store_regdb_version(regdb, REGDB_VERSION_V1);
800
0
    if (!W_ERROR_IS_OK(werr)) {
801
0
      return werr;
802
0
    }
803
0
    vers_id = REGDB_VERSION_V1;
804
0
  }
805
806
0
  if (vers_id == REGDB_CODE_VERSION) {
807
0
    return WERR_OK;
808
0
  }
809
810
0
  if (vers_id > REGDB_CODE_VERSION || vers_id == 0) {
811
0
    DEBUG(0, ("regdb_init: unknown registry version %d "
812
0
        "(code version = %d), refusing initialization\n",
813
0
        vers_id, REGDB_CODE_VERSION));
814
0
    return WERR_CAN_NOT_COMPLETE;
815
0
  }
816
817
0
  if (dbwrap_transaction_start(regdb) != 0) {
818
0
    return WERR_REGISTRY_IO_FAILED;
819
0
  }
820
821
0
  if (vers_id == REGDB_VERSION_V1) {
822
0
    DEBUG(10, ("regdb_init: upgrading registry from version %d "
823
0
         "to %d\n", REGDB_VERSION_V1, REGDB_VERSION_V2));
824
825
0
    werr = regdb_upgrade_v1_to_v2(regdb);
826
0
    if (!W_ERROR_IS_OK(werr)) {
827
0
      dbwrap_transaction_cancel(regdb);
828
0
      return werr;
829
0
    }
830
831
0
    vers_id = REGDB_VERSION_V2;
832
0
  }
833
834
0
  if (vers_id == REGDB_VERSION_V2) {
835
0
    DEBUG(10, ("regdb_init: upgrading registry from version %d "
836
0
         "to %d\n", REGDB_VERSION_V2, REGDB_VERSION_V3));
837
838
0
    werr = regdb_upgrade_v2_to_v3(regdb);
839
0
    if (!W_ERROR_IS_OK(werr)) {
840
0
      dbwrap_transaction_cancel(regdb);
841
0
      return werr;
842
0
    }
843
844
0
    vers_id = REGDB_VERSION_V3;
845
0
  }
846
847
  /* future upgrade code should go here */
848
849
0
  if (dbwrap_transaction_commit(regdb) != 0) {
850
0
    return WERR_REGISTRY_IO_FAILED;
851
0
  }
852
853
0
  return WERR_OK;
854
0
}
855
856
/***********************************************************************
857
 Open the registry.  Must already have been initialized by regdb_init()
858
 ***********************************************************************/
859
860
WERROR regdb_open( void )
861
0
{
862
0
  WERROR result;
863
0
  char *db_path = NULL;
864
0
  int saved_errno;
865
866
0
  if ( regdb ) {
867
0
    DEBUG(10, ("regdb_open: incrementing refcount (%d->%d)\n",
868
0
         regdb_refcount, regdb_refcount+1));
869
0
    regdb_refcount++;
870
0
    result = WERR_OK;
871
0
    goto done;
872
0
  }
873
874
0
  db_path = state_path(talloc_tos(), "registry.tdb");
875
0
  if (db_path == NULL) {
876
0
    result = WERR_NOT_ENOUGH_MEMORY;
877
0
    goto done;
878
0
  }
879
880
0
  become_root();
881
882
0
  regdb = db_open(NULL, db_path, 0,
883
0
      REG_TDB_FLAGS, O_RDWR, 0600,
884
0
      DBWRAP_LOCK_ORDER_1, REG_DBWRAP_FLAGS);
885
0
  saved_errno = errno;
886
0
  unbecome_root();
887
0
  if ( !regdb ) {
888
0
    result = ntstatus_to_werror(map_nt_error_from_unix(saved_errno));
889
0
    DEBUG(0,("regdb_open: Failed to open %s! (%s)\n",
890
0
       db_path, strerror(saved_errno)));
891
0
    goto done;
892
0
  }
893
894
0
  regdb_refcount = 1;
895
0
  DEBUG(10, ("regdb_open: registry db opened. refcount reset (%d)\n",
896
0
       regdb_refcount));
897
898
0
  result = WERR_OK;
899
0
done:
900
0
  TALLOC_FREE(db_path);
901
0
  return result;
902
0
}
903
904
/***********************************************************************
905
 ***********************************************************************/
906
907
int regdb_close( void )
908
0
{
909
0
  if (regdb_refcount == 0) {
910
0
    return 0;
911
0
  }
912
913
0
  regdb_refcount--;
914
915
0
  DEBUG(10, ("regdb_close: decrementing refcount (%d->%d)\n",
916
0
       regdb_refcount+1, regdb_refcount));
917
918
0
  if ( regdb_refcount > 0 )
919
0
    return 0;
920
921
0
  SMB_ASSERT( regdb_refcount >= 0 );
922
923
0
  TALLOC_FREE(regdb);
924
0
  return 0;
925
0
}
926
927
WERROR regdb_transaction_start(void)
928
0
{
929
0
  return (dbwrap_transaction_start(regdb) == 0) ?
930
0
    WERR_OK : WERR_REGISTRY_IO_FAILED;
931
0
}
932
933
WERROR regdb_transaction_commit(void)
934
0
{
935
0
  return (dbwrap_transaction_commit(regdb) == 0) ?
936
0
    WERR_OK : WERR_REGISTRY_IO_FAILED;
937
0
}
938
939
WERROR regdb_transaction_cancel(void)
940
0
{
941
0
  return (dbwrap_transaction_cancel(regdb) == 0) ?
942
0
    WERR_OK : WERR_REGISTRY_IO_FAILED;
943
0
}
944
945
/***********************************************************************
946
 return the tdb sequence number of the registry tdb.
947
 this is an indicator for the content of the registry
948
 having changed. it will change upon regdb_init, too, though.
949
 ***********************************************************************/
950
int regdb_get_seqnum(void)
951
0
{
952
0
  return dbwrap_get_seqnum(regdb);
953
0
}
954
955
956
static WERROR regdb_delete_key_with_prefix(struct db_context *db,
957
             const char *keyname,
958
             const char *prefix)
959
0
{
960
0
  char *path;
961
0
  WERROR werr = WERR_NOT_ENOUGH_MEMORY;
962
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
963
964
0
  if (keyname == NULL) {
965
0
    werr = WERR_INVALID_PARAMETER;
966
0
    goto done;
967
0
  }
968
969
0
  if (prefix == NULL) {
970
0
    path = discard_const_p(char, keyname);
971
0
  } else {
972
0
    path = talloc_asprintf(mem_ctx, "%s\\%s", prefix, keyname);
973
0
    if (path == NULL) {
974
0
      goto done;
975
0
    }
976
0
  }
977
978
0
  path = normalize_reg_path(mem_ctx, path);
979
0
  if (path == NULL) {
980
0
    goto done;
981
0
  }
982
983
0
  werr = ntstatus_to_werror(dbwrap_purge_bystring(db, path));
984
985
0
done:
986
0
  talloc_free(mem_ctx);
987
0
  return werr;
988
0
}
989
990
991
static WERROR regdb_delete_values(struct db_context *db, const char *keyname)
992
0
{
993
0
  return regdb_delete_key_with_prefix(db, keyname, REG_VALUE_PREFIX);
994
0
}
995
996
static WERROR regdb_delete_secdesc(struct db_context *db, const char *keyname)
997
0
{
998
0
  return regdb_delete_key_with_prefix(db, keyname, REG_SECDESC_PREFIX);
999
0
}
1000
1001
static WERROR regdb_delete_subkeylist(struct db_context *db, const char *keyname)
1002
0
{
1003
0
  return regdb_delete_key_with_prefix(db, keyname, NULL);
1004
0
}
1005
1006
1007
static WERROR regdb_delete_key_lists(struct db_context *db, const char *keyname)
1008
0
{
1009
0
  WERROR werr;
1010
1011
0
  werr = regdb_delete_values(db, keyname);
1012
0
  if (!W_ERROR_IS_OK(werr)) {
1013
0
    DEBUG(1, (__location__ " Deleting %s\\%s failed: %s\n",
1014
0
        REG_VALUE_PREFIX, keyname, win_errstr(werr)));
1015
0
    goto done;
1016
0
  }
1017
1018
0
  werr = regdb_delete_secdesc(db, keyname);
1019
0
  if (!W_ERROR_IS_OK(werr)) {
1020
0
    DEBUG(1, (__location__ " Deleting %s\\%s failed: %s\n",
1021
0
        REG_SECDESC_PREFIX, keyname, win_errstr(werr)));
1022
0
    goto done;
1023
0
  }
1024
1025
0
  werr = regdb_delete_subkeylist(db, keyname);
1026
0
  if (!W_ERROR_IS_OK(werr)) {
1027
0
    DEBUG(1, (__location__ " Deleting %s failed: %s\n",
1028
0
        keyname, win_errstr(werr)));
1029
0
    goto done;
1030
0
  }
1031
1032
0
done:
1033
0
  return werr;
1034
0
}
1035
1036
/***********************************************************************
1037
 Add subkey strings to the registry tdb under a defined key
1038
 fmt is the same format as tdb_pack except this function only supports
1039
 fstrings
1040
 ***********************************************************************/
1041
1042
static WERROR regdb_store_keys_internal2(struct db_context *db,
1043
           const char *key,
1044
           struct regsubkey_ctr *ctr)
1045
0
{
1046
0
  TDB_DATA dbuf;
1047
0
  uint8_t *buffer = NULL;
1048
0
  uint32_t i = 0;
1049
0
  uint32_t len, buflen;
1050
0
  uint32_t num_subkeys = regsubkey_ctr_numkeys(ctr);
1051
0
  char *keyname = NULL;
1052
0
  TALLOC_CTX *ctx = talloc_stackframe();
1053
0
  WERROR werr;
1054
1055
0
  if (!key) {
1056
0
    werr = WERR_INVALID_PARAMETER;
1057
0
    goto done;
1058
0
  }
1059
1060
0
  keyname = talloc_strdup(ctx, key);
1061
0
  if (!keyname) {
1062
0
    werr = WERR_NOT_ENOUGH_MEMORY;
1063
0
    goto done;
1064
0
  }
1065
1066
0
  keyname = normalize_reg_path(ctx, keyname);
1067
0
  if (!keyname) {
1068
0
    werr = WERR_NOT_ENOUGH_MEMORY;
1069
0
    goto done;
1070
0
  }
1071
1072
  /* allocate some initial memory */
1073
1074
0
  buffer = (uint8_t *)SMB_MALLOC(1024);
1075
0
  if (buffer == NULL) {
1076
0
    werr = WERR_NOT_ENOUGH_MEMORY;
1077
0
    goto done;
1078
0
  }
1079
0
  buflen = 1024;
1080
0
  len = 0;
1081
1082
  /* store the number of subkeys */
1083
1084
0
  len += tdb_pack(buffer+len, buflen-len, "d", num_subkeys);
1085
1086
  /* pack all the strings */
1087
1088
0
  for (i=0; i<num_subkeys; i++) {
1089
0
    size_t thistime;
1090
1091
0
    thistime = tdb_pack(buffer+len, buflen-len, "f",
1092
0
            regsubkey_ctr_specific_key(ctr, i));
1093
0
    if (len+thistime > buflen) {
1094
0
      size_t thistime2;
1095
      /*
1096
       * tdb_pack hasn't done anything because of the short
1097
       * buffer, allocate extra space.
1098
       */
1099
0
      buffer = SMB_REALLOC_ARRAY(buffer, uint8_t,
1100
0
               (len+thistime)*2);
1101
0
      if(buffer == NULL) {
1102
0
        DEBUG(0, ("regdb_store_keys: Failed to realloc "
1103
0
            "memory of size [%u]\n",
1104
0
            (unsigned int)(len+thistime)*2));
1105
0
        werr = WERR_NOT_ENOUGH_MEMORY;
1106
0
        goto done;
1107
0
      }
1108
0
      buflen = (len+thistime)*2;
1109
0
      thistime2 = tdb_pack(
1110
0
        buffer+len, buflen-len, "f",
1111
0
        regsubkey_ctr_specific_key(ctr, i));
1112
0
      if (thistime2 != thistime) {
1113
0
        DEBUG(0, ("tdb_pack failed\n"));
1114
0
        werr = WERR_CAN_NOT_COMPLETE;
1115
0
        goto done;
1116
0
      }
1117
0
    }
1118
0
    len += thistime;
1119
0
  }
1120
1121
  /* finally write out the data */
1122
1123
0
  dbuf.dptr = buffer;
1124
0
  dbuf.dsize = len;
1125
0
  werr = ntstatus_to_werror(dbwrap_store_bystring(db, keyname, dbuf,
1126
0
              TDB_REPLACE));
1127
1128
0
done:
1129
0
  TALLOC_FREE(ctx);
1130
0
  SAFE_FREE(buffer);
1131
0
  return werr;
1132
0
}
1133
1134
/**
1135
 * Utility function to store a new empty list of
1136
 * subkeys of given key specified as parent and subkey name
1137
 * (thereby creating the key).
1138
 * If the parent keyname is NULL, then the "subkey" is
1139
 * interpreted as a base key.
1140
 * If the subkey list does already exist, it is not modified.
1141
 *
1142
 * Must be called from within a transaction.
1143
 */
1144
static WERROR regdb_store_subkey_list(struct db_context *db, const char *parent,
1145
              const char *key)
1146
0
{
1147
0
  WERROR werr;
1148
0
  char *path = NULL;
1149
0
  struct regsubkey_ctr *subkeys = NULL;
1150
0
  TALLOC_CTX *frame = talloc_stackframe();
1151
1152
0
  if (parent == NULL) {
1153
0
    path = talloc_strdup(frame, key);
1154
0
  } else {
1155
0
    path = talloc_asprintf(frame, "%s\\%s", parent, key);
1156
0
  }
1157
0
  if (!path) {
1158
0
    werr = WERR_NOT_ENOUGH_MEMORY;
1159
0
    goto done;
1160
0
  }
1161
1162
0
  werr = regsubkey_ctr_init(frame, &subkeys);
1163
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1164
1165
0
  werr = regdb_fetch_keys_internal(db, path, subkeys);
1166
0
  if (W_ERROR_IS_OK(werr)) {
1167
    /* subkey list exists already - don't modify */
1168
0
    goto done;
1169
0
  }
1170
1171
0
  werr = regsubkey_ctr_reinit(subkeys);
1172
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1173
1174
  /* create a record with 0 subkeys */
1175
0
  werr = regdb_store_keys_internal2(db, path, subkeys);
1176
0
  if (!W_ERROR_IS_OK(werr)) {
1177
0
    DEBUG(0, ("regdb_store_keys: Failed to store new record for "
1178
0
        "key [%s]: %s\n", path, win_errstr(werr)));
1179
0
    goto done;
1180
0
  }
1181
1182
0
done:
1183
0
  talloc_free(frame);
1184
0
  return werr;
1185
0
}
1186
1187
/***********************************************************************
1188
 Store the new subkey record and create any child key records that
1189
 do not currently exist
1190
 ***********************************************************************/
1191
1192
struct regdb_store_keys_context {
1193
  const char *key;
1194
  struct regsubkey_ctr *ctr;
1195
};
1196
1197
static NTSTATUS regdb_store_keys_action(struct db_context *db,
1198
          void *private_data)
1199
0
{
1200
0
  struct regdb_store_keys_context *store_ctx;
1201
0
  WERROR werr;
1202
0
  int num_subkeys, i;
1203
0
  char *path = NULL;
1204
0
  struct regsubkey_ctr *old_subkeys = NULL;
1205
0
  char *oldkeyname = NULL;
1206
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
1207
1208
0
  store_ctx = (struct regdb_store_keys_context *)private_data;
1209
1210
  /*
1211
   * Re-fetch the old keys inside the transaction
1212
   */
1213
1214
0
  werr = regsubkey_ctr_init(mem_ctx, &old_subkeys);
1215
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1216
1217
0
  werr = regdb_fetch_keys_internal(db, store_ctx->key, old_subkeys);
1218
0
  if (!W_ERROR_IS_OK(werr) &&
1219
0
      !W_ERROR_EQUAL(werr, WERR_NOT_FOUND))
1220
0
  {
1221
0
    goto done;
1222
0
  }
1223
1224
  /*
1225
   * Make the store operation as safe as possible without transactions:
1226
   *
1227
   * (1) For each subkey removed from ctr compared with old_subkeys:
1228
   *
1229
   *     (a) First delete the value db entry.
1230
   *
1231
   *     (b) Next delete the secdesc db record.
1232
   *
1233
   *     (c) Then delete the subkey list entry.
1234
   *
1235
   * (2) Now write the list of subkeys of the parent key,
1236
   *     deleting removed entries and adding new ones.
1237
   *
1238
   * (3) Finally create the subkey list entries for the added keys.
1239
   *
1240
   * This way if we crash half-way in between deleting the subkeys
1241
   * and storing the parent's list of subkeys, no old data can pop up
1242
   * out of the blue when re-adding keys later on.
1243
   */
1244
1245
  /* (1) delete removed keys' lists (values/secdesc/subkeys) */
1246
1247
0
  num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
1248
0
  for (i=0; i<num_subkeys; i++) {
1249
0
    oldkeyname = regsubkey_ctr_specific_key(old_subkeys, i);
1250
1251
0
    if (regsubkey_ctr_key_exists(store_ctx->ctr, oldkeyname)) {
1252
      /*
1253
       * It's still around, don't delete
1254
       */
1255
0
      continue;
1256
0
    }
1257
1258
0
    path = talloc_asprintf(mem_ctx, "%s\\%s", store_ctx->key,
1259
0
               oldkeyname);
1260
0
    if (!path) {
1261
0
      werr = WERR_NOT_ENOUGH_MEMORY;
1262
0
      goto done;
1263
0
    }
1264
1265
0
    werr = regdb_delete_key_lists(db, path);
1266
0
    W_ERROR_NOT_OK_GOTO_DONE(werr);
1267
1268
0
    TALLOC_FREE(path);
1269
0
  }
1270
1271
0
  TALLOC_FREE(old_subkeys);
1272
1273
  /* (2) store the subkey list for the parent */
1274
1275
0
  werr = regdb_store_keys_internal2(db, store_ctx->key, store_ctx->ctr);
1276
0
  if (!W_ERROR_IS_OK(werr)) {
1277
0
    DEBUG(0,("regdb_store_keys: Failed to store new subkey list "
1278
0
       "for parent [%s]: %s\n", store_ctx->key,
1279
0
       win_errstr(werr)));
1280
0
    goto done;
1281
0
  }
1282
1283
  /* (3) now create records for any subkeys that don't already exist */
1284
1285
0
  num_subkeys = regsubkey_ctr_numkeys(store_ctx->ctr);
1286
1287
0
  for (i=0; i<num_subkeys; i++) {
1288
0
    const char *subkey;
1289
1290
0
    subkey = regsubkey_ctr_specific_key(store_ctx->ctr, i);
1291
1292
0
    werr = regdb_store_subkey_list(db, store_ctx->key, subkey);
1293
0
    W_ERROR_NOT_OK_GOTO_DONE(werr);
1294
0
  }
1295
1296
  /*
1297
   * Update the seqnum in the container to possibly
1298
   * prevent next read from going to disk
1299
   */
1300
0
  werr = regsubkey_ctr_set_seqnum(store_ctx->ctr, dbwrap_get_seqnum(db));
1301
1302
0
done:
1303
0
  talloc_free(mem_ctx);
1304
0
  return werror_to_ntstatus(werr);
1305
0
}
1306
1307
static bool regdb_store_keys_internal(struct db_context *db, const char *key,
1308
              struct regsubkey_ctr *ctr)
1309
0
{
1310
0
  int num_subkeys, old_num_subkeys, i;
1311
0
  struct regsubkey_ctr *old_subkeys = NULL;
1312
0
  TALLOC_CTX *ctx = talloc_stackframe();
1313
0
  WERROR werr;
1314
0
  bool ret = false;
1315
0
  struct regdb_store_keys_context store_ctx;
1316
1317
0
  if (!regdb_key_exists(db, key)) {
1318
0
    goto done;
1319
0
  }
1320
1321
  /*
1322
   * fetch a list of the old subkeys so we can determine if anything has
1323
   * changed
1324
   */
1325
1326
0
  werr = regsubkey_ctr_init(ctx, &old_subkeys);
1327
0
  if (!W_ERROR_IS_OK(werr)) {
1328
0
    DEBUG(0,("regdb_store_keys: talloc() failure!\n"));
1329
0
    goto done;
1330
0
  }
1331
1332
0
  werr = regdb_fetch_keys_internal(db, key, old_subkeys);
1333
0
  if (!W_ERROR_IS_OK(werr) &&
1334
0
      !W_ERROR_EQUAL(werr, WERR_NOT_FOUND))
1335
0
  {
1336
0
    goto done;
1337
0
  }
1338
1339
0
  num_subkeys = regsubkey_ctr_numkeys(ctr);
1340
0
  old_num_subkeys = regsubkey_ctr_numkeys(old_subkeys);
1341
0
  if ((num_subkeys && old_num_subkeys) &&
1342
0
      (num_subkeys == old_num_subkeys)) {
1343
1344
0
    for (i = 0; i < num_subkeys; i++) {
1345
0
      if (strcmp(regsubkey_ctr_specific_key(ctr, i),
1346
0
           regsubkey_ctr_specific_key(old_subkeys, i))
1347
0
          != 0)
1348
0
      {
1349
0
        break;
1350
0
      }
1351
0
    }
1352
0
    if (i == num_subkeys) {
1353
      /*
1354
       * Nothing changed, no point to even start a tdb
1355
       * transaction
1356
       */
1357
1358
0
      ret = true;
1359
0
      goto done;
1360
0
    }
1361
0
  }
1362
1363
0
  TALLOC_FREE(old_subkeys);
1364
1365
0
  store_ctx.key = key;
1366
0
  store_ctx.ctr = ctr;
1367
1368
0
  werr = regdb_trans_do(db,
1369
0
            regdb_store_keys_action,
1370
0
            &store_ctx);
1371
1372
0
  ret = W_ERROR_IS_OK(werr);
1373
1374
0
done:
1375
0
  TALLOC_FREE(ctx);
1376
1377
0
  return ret;
1378
0
}
1379
1380
static bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr)
1381
0
{
1382
0
  return regdb_store_keys_internal(regdb, key, ctr);
1383
0
}
1384
1385
/**
1386
 * create a subkey of a given key
1387
 */
1388
1389
struct regdb_create_subkey_context {
1390
  const char *key;
1391
  const char *subkey;
1392
};
1393
1394
static NTSTATUS regdb_create_subkey_action(struct db_context *db,
1395
             void *private_data)
1396
0
{
1397
0
  WERROR werr;
1398
0
  struct regdb_create_subkey_context *create_ctx;
1399
0
  struct regsubkey_ctr *subkeys;
1400
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
1401
1402
0
  create_ctx = (struct regdb_create_subkey_context *)private_data;
1403
1404
0
  werr = regsubkey_ctr_init(mem_ctx, &subkeys);
1405
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1406
1407
0
  werr = regdb_fetch_keys_internal(db, create_ctx->key, subkeys);
1408
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1409
1410
0
  werr = regsubkey_ctr_addkey(subkeys, create_ctx->subkey);
1411
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1412
1413
0
  werr = regdb_store_keys_internal2(db, create_ctx->key, subkeys);
1414
0
  if (!W_ERROR_IS_OK(werr)) {
1415
0
    DEBUG(0, (__location__ " failed to store new subkey list for "
1416
0
       "parent key %s: %s\n", create_ctx->key,
1417
0
       win_errstr(werr)));
1418
0
  }
1419
1420
0
  werr = regdb_store_subkey_list(db, create_ctx->key, create_ctx->subkey);
1421
1422
0
done:
1423
0
  talloc_free(mem_ctx);
1424
0
  return werror_to_ntstatus(werr);
1425
0
}
1426
1427
static WERROR regdb_create_subkey_internal(struct db_context *db,
1428
             const char *key,
1429
             const char *subkey)
1430
0
{
1431
0
  WERROR werr;
1432
0
  struct regsubkey_ctr *subkeys;
1433
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
1434
0
  struct regdb_create_subkey_context create_ctx;
1435
1436
0
  if (!regdb_key_exists(db, key)) {
1437
0
    werr = WERR_NOT_FOUND;
1438
0
    goto done;
1439
0
  }
1440
1441
0
  werr = regsubkey_ctr_init(mem_ctx, &subkeys);
1442
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1443
1444
0
  werr = regdb_fetch_keys_internal(db, key, subkeys);
1445
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1446
1447
0
  if (regsubkey_ctr_key_exists(subkeys, subkey)) {
1448
0
    char *newkey;
1449
1450
0
    newkey = talloc_asprintf(mem_ctx, "%s\\%s", key, subkey);
1451
0
    if (newkey == NULL) {
1452
0
      werr = WERR_NOT_ENOUGH_MEMORY;
1453
0
      goto done;
1454
0
    }
1455
1456
0
    if (regdb_key_exists(db, newkey)) {
1457
0
      werr = WERR_OK;
1458
0
      goto done;
1459
0
    }
1460
0
  }
1461
1462
0
  talloc_free(subkeys);
1463
1464
0
  create_ctx.key = key;
1465
0
  create_ctx.subkey = subkey;
1466
1467
0
  werr = regdb_trans_do(db,
1468
0
            regdb_create_subkey_action,
1469
0
            &create_ctx);
1470
1471
0
done:
1472
0
  talloc_free(mem_ctx);
1473
0
  return werr;
1474
0
}
1475
1476
static WERROR regdb_create_subkey(const char *key, const char *subkey)
1477
0
{
1478
0
  return regdb_create_subkey_internal(regdb, key, subkey);
1479
0
}
1480
1481
/**
1482
 * create a base key
1483
 */
1484
1485
struct regdb_create_basekey_context {
1486
  const char *key;
1487
};
1488
1489
static NTSTATUS regdb_create_basekey_action(struct db_context *db,
1490
              void *private_data)
1491
0
{
1492
0
  WERROR werr;
1493
0
  struct regdb_create_basekey_context *create_ctx;
1494
1495
0
  create_ctx = (struct regdb_create_basekey_context *)private_data;
1496
1497
0
  werr = regdb_store_subkey_list(db, NULL, create_ctx->key);
1498
1499
0
  return werror_to_ntstatus(werr);
1500
0
}
1501
1502
static WERROR regdb_create_basekey(struct db_context *db, const char *key)
1503
0
{
1504
0
  WERROR werr;
1505
0
  struct regdb_create_subkey_context create_ctx;
1506
1507
0
  create_ctx.key = key;
1508
1509
0
  werr = regdb_trans_do(db,
1510
0
            regdb_create_basekey_action,
1511
0
            &create_ctx);
1512
1513
0
  return werr;
1514
0
}
1515
1516
/**
1517
 * create a subkey of a given key
1518
 */
1519
1520
struct regdb_delete_subkey_context {
1521
  const char *key;
1522
  const char *subkey;
1523
  const char *path;
1524
  bool lazy;
1525
};
1526
1527
static NTSTATUS regdb_delete_subkey_action(struct db_context *db,
1528
             void *private_data)
1529
0
{
1530
0
  WERROR werr;
1531
0
  struct regdb_delete_subkey_context *delete_ctx;
1532
0
  struct regsubkey_ctr *subkeys;
1533
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
1534
1535
0
  delete_ctx = (struct regdb_delete_subkey_context *)private_data;
1536
1537
0
  werr = regdb_delete_key_lists(db, delete_ctx->path);
1538
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1539
1540
0
  if (delete_ctx->lazy) {
1541
0
    goto done;
1542
0
  }
1543
1544
0
  werr = regsubkey_ctr_init(mem_ctx, &subkeys);
1545
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1546
1547
0
  werr = regdb_fetch_keys_internal(db, delete_ctx->key, subkeys);
1548
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1549
1550
0
  werr = regsubkey_ctr_delkey(subkeys, delete_ctx->subkey);
1551
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1552
1553
0
  werr = regdb_store_keys_internal2(db, delete_ctx->key, subkeys);
1554
0
  if (!W_ERROR_IS_OK(werr)) {
1555
0
    DEBUG(0, (__location__ " failed to store new subkey_list for "
1556
0
       "parent key %s: %s\n", delete_ctx->key,
1557
0
       win_errstr(werr)));
1558
0
  }
1559
1560
0
done:
1561
0
  talloc_free(mem_ctx);
1562
0
  return werror_to_ntstatus(werr);
1563
0
}
1564
1565
static WERROR regdb_delete_subkey(const char *key, const char *subkey, bool lazy)
1566
0
{
1567
0
  WERROR werr;
1568
0
  char *path;
1569
0
  struct regdb_delete_subkey_context delete_ctx;
1570
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
1571
1572
0
  if (!regdb_key_exists(regdb, key)) {
1573
0
    werr = WERR_NOT_FOUND;
1574
0
    goto done;
1575
0
  }
1576
1577
0
  path = talloc_asprintf(mem_ctx, "%s\\%s", key, subkey);
1578
0
  if (path == NULL) {
1579
0
    werr = WERR_NOT_ENOUGH_MEMORY;
1580
0
    goto done;
1581
0
  }
1582
1583
0
  if (!regdb_key_exists(regdb, path)) {
1584
0
    werr = WERR_OK;
1585
0
    goto done;
1586
0
  }
1587
1588
0
  delete_ctx.key = key;
1589
0
  delete_ctx.subkey = subkey;
1590
0
  delete_ctx.path = path;
1591
0
  delete_ctx.lazy = lazy;
1592
1593
0
  werr = regdb_trans_do(regdb,
1594
0
            regdb_delete_subkey_action,
1595
0
            &delete_ctx);
1596
1597
0
done:
1598
0
  talloc_free(mem_ctx);
1599
0
  return werr;
1600
0
}
1601
1602
static TDB_DATA regdb_fetch_key_internal(struct db_context *db,
1603
           TALLOC_CTX *mem_ctx, const char *key)
1604
0
{
1605
0
  char *path = NULL;
1606
0
  TDB_DATA data;
1607
0
  NTSTATUS status;
1608
1609
0
  path = normalize_reg_path(mem_ctx, key);
1610
0
  if (!path) {
1611
0
    return make_tdb_data(NULL, 0);
1612
0
  }
1613
1614
0
  status = dbwrap_fetch_bystring(db, mem_ctx, path, &data);
1615
0
  if (!NT_STATUS_IS_OK(status)) {
1616
0
    data = tdb_null;
1617
0
  }
1618
1619
0
  TALLOC_FREE(path);
1620
0
  return data;
1621
0
}
1622
1623
1624
/**
1625
 * Check for the existence of a key.
1626
 *
1627
 * Existence of a key is authoritatively defined by
1628
 * the existence of the record that contains the list
1629
 * of its subkeys.
1630
 *
1631
 * Return false, if the record does not match the correct
1632
 * structure of an initial 4-byte counter and then a
1633
 * list of the corresponding number of zero-terminated
1634
 * strings.
1635
 */
1636
static bool regdb_key_exists(struct db_context *db, const char *key)
1637
0
{
1638
0
  TALLOC_CTX *mem_ctx = talloc_stackframe();
1639
0
  TDB_DATA value;
1640
0
  bool ret = false;
1641
0
  char *path;
1642
0
  uint32_t buflen;
1643
0
  const char *buf;
1644
0
  uint32_t num_items, i;
1645
0
  int32_t len;
1646
1647
0
  if (key == NULL) {
1648
0
    goto done;
1649
0
  }
1650
1651
0
  path = normalize_reg_path(mem_ctx, key);
1652
0
  if (path == NULL) {
1653
0
    DEBUG(0, ("out of memory! (talloc failed)\n"));
1654
0
    goto done;
1655
0
  }
1656
1657
0
  if (*path == '\0') {
1658
0
    goto done;
1659
0
  }
1660
1661
0
  value = regdb_fetch_key_internal(db, mem_ctx, path);
1662
0
  if (value.dptr == NULL) {
1663
0
    goto done;
1664
0
  }
1665
1666
0
  if (value.dsize == 0) {
1667
0
    DEBUG(10, ("regdb_key_exists: subkeylist-record for key "
1668
0
        "[%s] is empty: Could be a deleted record in a "
1669
0
        "clustered (ctdb) environment?\n",
1670
0
        path));
1671
0
    goto done;
1672
0
  }
1673
1674
0
  len = tdb_unpack(value.dptr, value.dsize, "d", &num_items);
1675
0
  if (len == (int32_t)-1) {
1676
0
    DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key "
1677
0
        "[%s] is invalid: Could not parse initial 4-byte "
1678
0
        "counter. record data length is %u.\n",
1679
0
        path, (unsigned int)value.dsize));
1680
0
    goto done;
1681
0
  }
1682
1683
  /*
1684
   * Note: the tdb_unpack check above implies that len <= value.dsize
1685
   */
1686
0
  buflen = value.dsize - len;
1687
0
  buf = (const char *)value.dptr + len;
1688
1689
0
  for (i = 0; i < num_items; i++) {
1690
0
    if (buflen == 0) {
1691
0
      break;
1692
0
    }
1693
0
    len = strnlen(buf, buflen) + 1;
1694
0
    if (buflen < len) {
1695
0
      DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record "
1696
0
          "for key [%s] is corrupt: %u items expected, "
1697
0
          "item number %u is not zero terminated.\n",
1698
0
          path, num_items, i+1));
1699
0
      goto done;
1700
0
    }
1701
1702
0
    buf += len;
1703
0
    buflen -= len;
1704
0
  }
1705
1706
0
  if (buflen > 0) {
1707
0
    DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key "
1708
0
        "[%s] is corrupt: %u items expected and found, but "
1709
0
        "the record contains additional %u bytes\n",
1710
0
        path, num_items, buflen));
1711
0
    goto done;
1712
0
  }
1713
1714
0
  if (i < num_items) {
1715
0
    DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key "
1716
0
        "[%s] is corrupt: %u items expected, but only %u "
1717
0
        "items found.\n",
1718
0
        path, num_items, i+1));
1719
0
    goto done;
1720
0
  }
1721
1722
0
  ret = true;
1723
1724
0
done:
1725
0
  TALLOC_FREE(mem_ctx);
1726
0
  return ret;
1727
0
}
1728
1729
1730
/***********************************************************************
1731
 Retrieve an array of strings containing subkeys.  Memory should be
1732
 released by the caller.
1733
 ***********************************************************************/
1734
1735
static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
1736
          struct regsubkey_ctr *ctr)
1737
0
{
1738
0
  WERROR werr;
1739
0
  uint32_t num_items;
1740
0
  uint8_t *buf;
1741
0
  uint32_t buflen, len;
1742
0
  uint32_t i;
1743
0
  fstring subkeyname;
1744
0
  TALLOC_CTX *frame = talloc_stackframe();
1745
0
  TDB_DATA value;
1746
0
  int seqnum[2], count;
1747
1748
0
  DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL"));
1749
1750
0
  if (!regdb_key_exists(db, key)) {
1751
0
    DEBUG(10, ("key [%s] not found\n", key));
1752
0
    werr = WERR_NOT_FOUND;
1753
0
    goto done;
1754
0
  }
1755
1756
0
  werr = regsubkey_ctr_reinit(ctr);
1757
0
  W_ERROR_NOT_OK_GOTO_DONE(werr);
1758
1759
0
  count = 0;
1760
0
  ZERO_STRUCT(value);
1761
0
  seqnum[0] = dbwrap_get_seqnum(db);
1762
1763
0
  do {
1764
0
    count++;
1765
0
    TALLOC_FREE(value.dptr);
1766
0
    value = regdb_fetch_key_internal(db, frame, key);
1767
0
    seqnum[count % 2] = dbwrap_get_seqnum(db);
1768
1769
0
  } while (seqnum[0] != seqnum[1]);
1770
1771
0
  if (count > 1) {
1772
0
    DEBUG(5, ("regdb_fetch_keys_internal: it took %d attempts to "
1773
0
        "fetch key '%s' with constant seqnum\n",
1774
0
        count, key));
1775
0
  }
1776
1777
0
  werr = regsubkey_ctr_set_seqnum(ctr, seqnum[0]);
1778
0
  if (!W_ERROR_IS_OK(werr)) {
1779
0
    goto done;
1780
0
  }
1781
1782
0
  if (value.dsize == 0 || value.dptr == NULL) {
1783
0
    DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n",
1784
0
         key));
1785
0
    goto done;
1786
0
  }
1787
1788
0
  buf = value.dptr;
1789
0
  buflen = value.dsize;
1790
0
  len = tdb_unpack( buf, buflen, "d", &num_items);
1791
0
  if (len == (uint32_t)-1) {
1792
0
    werr = WERR_NOT_FOUND;
1793
0
    goto done;
1794
0
  }
1795
1796
0
  for (i=0; i<num_items; i++) {
1797
0
    int this_len;
1798
1799
0
    this_len = tdb_unpack(buf+len, buflen-len, "f", subkeyname);
1800
0
    if (this_len == -1) {
1801
0
      DBG_WARNING("Invalid registry data, "
1802
0
            "tdb_unpack failed\n");
1803
0
      werr = WERR_INTERNAL_DB_CORRUPTION;
1804
0
      goto done;
1805
0
    }
1806
0
    len += this_len;
1807
0
    if (len < this_len) {
1808
0
      DBG_WARNING("Invalid registry data, "
1809
0
            "integer overflow\n");
1810
0
      werr = WERR_INTERNAL_DB_CORRUPTION;
1811
0
      goto done;
1812
0
    }
1813
1814
0
    werr = regsubkey_ctr_addkey(ctr, subkeyname);
1815
0
    if (!W_ERROR_IS_OK(werr)) {
1816
0
      DEBUG(5, ("regdb_fetch_keys: regsubkey_ctr_addkey "
1817
0
          "failed: %s\n", win_errstr(werr)));
1818
0
      num_items = 0;
1819
0
      goto done;
1820
0
    }
1821
0
  }
1822
1823
0
  DEBUG(11,("regdb_fetch_keys: Exit [%d] items\n", num_items));
1824
1825
0
done:
1826
0
  TALLOC_FREE(frame);
1827
0
  return werr;
1828
0
}
1829
1830
static int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr)
1831
0
{
1832
0
  WERROR werr;
1833
1834
0
  werr = regdb_fetch_keys_internal(regdb, key, ctr);
1835
0
  if (!W_ERROR_IS_OK(werr)) {
1836
0
    return -1;
1837
0
  }
1838
1839
0
  return regsubkey_ctr_numkeys(ctr);
1840
0
}
1841
1842
/****************************************************************************
1843
 Unpack a list of registry values frem the TDB
1844
 ***************************************************************************/
1845
1846
static int regdb_unpack_values(struct regval_ctr *values,
1847
             uint8_t *buf,
1848
             size_t buflen)
1849
0
{
1850
0
  int this_len;
1851
0
  size_t    len = 0;
1852
0
  uint32_t  type;
1853
0
  fstring valuename;
1854
0
  uint32_t  size;
1855
0
  uint8_t   *data_p;
1856
0
  uint32_t  num_values = 0;
1857
0
  uint32_t  i;
1858
1859
  /* loop and unpack the rest of the registry values */
1860
1861
0
  this_len = tdb_unpack(buf, buflen, "d", &num_values);
1862
0
  if (this_len == -1) {
1863
0
    DBG_WARNING("Invalid registry data, "
1864
0
          "tdb_unpack failed\n");
1865
0
    return -1;
1866
0
  }
1867
0
  len = this_len;
1868
1869
0
  for ( i=0; i<num_values; i++ ) {
1870
    /* unpack the next regval */
1871
1872
0
    type = REG_NONE;
1873
0
    size = 0;
1874
0
    data_p = NULL;
1875
0
    valuename[0] = '\0';
1876
0
    this_len = tdb_unpack(buf+len, buflen-len, "fdB",
1877
0
              valuename,
1878
0
              &type,
1879
0
              &size,
1880
0
              &data_p);
1881
0
    if (this_len == -1) {
1882
0
      DBG_WARNING("Invalid registry data, "
1883
0
            "tdb_unpack failed\n");
1884
0
      return -1;
1885
0
    }
1886
0
    len += this_len;
1887
0
    if (len < (size_t)this_len) {
1888
0
      DBG_WARNING("Invalid registry data, "
1889
0
            "integer overflow\n");
1890
0
      return -1;
1891
0
    }
1892
1893
0
    regval_ctr_addvalue(values, valuename, type,
1894
0
        (uint8_t *)data_p, size);
1895
0
    SAFE_FREE(data_p); /* 'B' option to tdb_unpack does a malloc() */
1896
1897
0
    DEBUG(10, ("regdb_unpack_values: value[%d]: name[%s] len[%d]\n",
1898
0
         i, valuename, size));
1899
0
  }
1900
1901
0
  return len;
1902
0
}
1903
1904
/****************************************************************************
1905
 Pack all values in all printer keys
1906
 ***************************************************************************/
1907
1908
static int regdb_pack_values(struct regval_ctr *values, uint8_t *buf, int buflen)
1909
0
{
1910
0
  int     len = 0;
1911
0
  int     i;
1912
0
  struct regval_blob  *val;
1913
0
  int   num_values;
1914
1915
0
  if ( !values )
1916
0
    return 0;
1917
1918
0
  num_values = regval_ctr_numvals( values );
1919
1920
  /* pack the number of values first */
1921
1922
0
  len += tdb_pack( buf+len, buflen-len, "d", num_values );
1923
1924
  /* loop over all values */
1925
1926
0
  for ( i=0; i<num_values; i++ ) {
1927
0
    val = regval_ctr_specific_value( values, i );
1928
0
    len += tdb_pack(buf+len, buflen-len, "fdB",
1929
0
        regval_name(val),
1930
0
        regval_type(val),
1931
0
        regval_size(val),
1932
0
        regval_data_p(val) );
1933
0
  }
1934
1935
0
  return len;
1936
0
}
1937
1938
/***********************************************************************
1939
 Retrieve an array of strings containing subkeys.  Memory should be
1940
 released by the caller.
1941
 ***********************************************************************/
1942
1943
static int regdb_fetch_values_internal(struct db_context *db, const char* key,
1944
               struct regval_ctr *values)
1945
0
{
1946
0
  char *keystr = NULL;
1947
0
  TALLOC_CTX *ctx = talloc_stackframe();
1948
0
  int ret = 0;
1949
0
  TDB_DATA value;
1950
0
  WERROR werr;
1951
0
  int seqnum[2], count;
1952
1953
0
  DEBUG(10,("regdb_fetch_values: Looking for values of key [%s]\n", key));
1954
1955
0
  if (!regdb_key_exists(db, key)) {
1956
0
    DEBUG(10, ("regb_fetch_values: key [%s] does not exist\n",
1957
0
         key));
1958
0
    ret = -1;
1959
0
    goto done;
1960
0
  }
1961
1962
0
  keystr = talloc_asprintf(ctx, "%s\\%s", REG_VALUE_PREFIX, key);
1963
0
  if (!keystr) {
1964
0
    goto done;
1965
0
  }
1966
1967
0
  ZERO_STRUCT(value);
1968
0
  count = 0;
1969
0
  seqnum[0] = dbwrap_get_seqnum(db);
1970
1971
0
  do {
1972
0
    count++;
1973
0
    TALLOC_FREE(value.dptr);
1974
0
    value = regdb_fetch_key_internal(db, ctx, keystr);
1975
0
    seqnum[count % 2] = dbwrap_get_seqnum(db);
1976
0
  } while (seqnum[0] != seqnum[1]);
1977
1978
0
  if (count > 1) {
1979
0
    DEBUG(5, ("regdb_fetch_values_internal: it took %d attempts "
1980
0
        "to fetch key '%s' with constant seqnum\n",
1981
0
        count, key));
1982
0
  }
1983
1984
0
  werr = regval_ctr_set_seqnum(values, seqnum[0]);
1985
0
  if (!W_ERROR_IS_OK(werr)) {
1986
0
    goto done;
1987
0
  }
1988
1989
0
  if (!value.dptr) {
1990
    /* all keys have zero values by default */
1991
0
    goto done;
1992
0
  }
1993
1994
0
  ret = regdb_unpack_values(values, value.dptr, value.dsize);
1995
0
  if (ret == -1) {
1996
0
    DBG_WARNING("regdb_unpack_values failed\n");
1997
0
  }
1998
1999
0
  ret = regval_ctr_numvals(values);
2000
2001
0
done:
2002
0
  TALLOC_FREE(ctx);
2003
0
  return ret;
2004
0
}
2005
2006
static int regdb_fetch_values(const char* key, struct regval_ctr *values)
2007
0
{
2008
0
  return regdb_fetch_values_internal(regdb, key, values);
2009
0
}
2010
2011
static NTSTATUS regdb_store_values_internal(struct db_context *db,
2012
              const char *key,
2013
              struct regval_ctr *values)
2014
0
{
2015
0
  TDB_DATA old_data, data;
2016
0
  char *keystr = NULL;
2017
0
  TALLOC_CTX *ctx = talloc_stackframe();
2018
0
  int len;
2019
0
  NTSTATUS status;
2020
0
  WERROR werr;
2021
2022
0
  DEBUG(10,("regdb_store_values: Looking for values of key [%s]\n", key));
2023
2024
0
  if (!regdb_key_exists(db, key)) {
2025
0
    status = NT_STATUS_NOT_FOUND;
2026
0
    goto done;
2027
0
  }
2028
2029
0
  if (regval_ctr_numvals(values) == 0) {
2030
0
    werr = regdb_delete_values(db, key);
2031
0
    if (!W_ERROR_IS_OK(werr)) {
2032
0
      status = werror_to_ntstatus(werr);
2033
0
      goto done;
2034
0
    }
2035
2036
    /*
2037
     * update the seqnum in the cache to prevent the next read
2038
     * from going to disk
2039
     */
2040
0
    werr = regval_ctr_set_seqnum(values, dbwrap_get_seqnum(db));
2041
0
    status = werror_to_ntstatus(werr);
2042
0
    goto done;
2043
0
  }
2044
2045
0
  ZERO_STRUCT(data);
2046
2047
0
  len = regdb_pack_values(values, data.dptr, data.dsize);
2048
0
  if (len <= 0) {
2049
0
    DEBUG(0,("regdb_store_values: unable to pack values. len <= 0\n"));
2050
0
    status = NT_STATUS_UNSUCCESSFUL;
2051
0
    goto done;
2052
0
  }
2053
2054
0
  data.dptr = talloc_array(ctx, uint8_t, len);
2055
0
  data.dsize = len;
2056
2057
0
  len = regdb_pack_values(values, data.dptr, data.dsize);
2058
2059
0
  SMB_ASSERT( len == data.dsize );
2060
2061
0
  keystr = talloc_asprintf(ctx, "%s\\%s", REG_VALUE_PREFIX, key );
2062
0
  if (!keystr) {
2063
0
    status = NT_STATUS_NO_MEMORY;
2064
0
    goto done;
2065
0
  }
2066
0
  keystr = normalize_reg_path(ctx, keystr);
2067
0
  if (!keystr) {
2068
0
    status = NT_STATUS_NO_MEMORY;
2069
0
    goto done;
2070
0
  }
2071
2072
0
  status = dbwrap_fetch_bystring(db, ctx, keystr, &old_data);
2073
2074
0
  if (NT_STATUS_IS_OK(status)
2075
0
      && (old_data.dptr != NULL)
2076
0
      && (old_data.dsize == data.dsize)
2077
0
      && (memcmp(old_data.dptr, data.dptr, data.dsize) == 0))
2078
0
  {
2079
0
    status = NT_STATUS_OK;
2080
0
    goto done;
2081
0
  }
2082
2083
0
  status = dbwrap_trans_store_bystring(db, keystr, data, TDB_REPLACE);
2084
0
  if (!NT_STATUS_IS_OK(status)) {
2085
0
    DEBUG(0, ("regdb_store_values_internal: error storing: %s\n", nt_errstr(status)));
2086
0
    goto done;
2087
0
  }
2088
2089
  /*
2090
   * update the seqnum in the cache to prevent the next read
2091
   * from going to disk
2092
   */
2093
0
  werr = regval_ctr_set_seqnum(values, dbwrap_get_seqnum(db));
2094
0
  status = werror_to_ntstatus(werr);
2095
2096
0
done:
2097
0
  TALLOC_FREE(ctx);
2098
0
  return status;
2099
0
}
2100
2101
struct regdb_store_values_ctx {
2102
  const char *key;
2103
  struct regval_ctr *values;
2104
};
2105
2106
static NTSTATUS regdb_store_values_action(struct db_context *db,
2107
            void *private_data)
2108
0
{
2109
0
  NTSTATUS status;
2110
0
  struct regdb_store_values_ctx *ctx =
2111
0
    (struct regdb_store_values_ctx *)private_data;
2112
2113
0
  status = regdb_store_values_internal(db, ctx->key, ctx->values);
2114
2115
0
  return status;
2116
0
}
2117
2118
static bool regdb_store_values(const char *key, struct regval_ctr *values)
2119
0
{
2120
0
  WERROR werr;
2121
0
  struct regdb_store_values_ctx ctx;
2122
2123
0
  ctx.key = key;
2124
0
  ctx.values = values;
2125
2126
0
  werr = regdb_trans_do(regdb, regdb_store_values_action, &ctx);
2127
2128
0
  return W_ERROR_IS_OK(werr);
2129
0
}
2130
2131
static WERROR regdb_get_secdesc(TALLOC_CTX *mem_ctx, const char *key,
2132
        struct security_descriptor **psecdesc)
2133
0
{
2134
0
  char *tdbkey;
2135
0
  TDB_DATA data;
2136
0
  NTSTATUS status;
2137
0
  TALLOC_CTX *tmp_ctx = talloc_stackframe();
2138
0
  WERROR err = WERR_OK;
2139
2140
0
  DEBUG(10, ("regdb_get_secdesc: Getting secdesc of key [%s]\n", key));
2141
2142
0
  if (!regdb_key_exists(regdb, key)) {
2143
0
    err = WERR_FILE_NOT_FOUND;
2144
0
    goto done;
2145
0
  }
2146
2147
0
  tdbkey = talloc_asprintf(tmp_ctx, "%s\\%s", REG_SECDESC_PREFIX, key);
2148
0
  if (tdbkey == NULL) {
2149
0
    err = WERR_NOT_ENOUGH_MEMORY;
2150
0
    goto done;
2151
0
  }
2152
2153
0
  tdbkey = normalize_reg_path(tmp_ctx, tdbkey);
2154
0
  if (tdbkey == NULL) {
2155
0
    err = WERR_NOT_ENOUGH_MEMORY;
2156
0
    goto done;
2157
0
  }
2158
2159
0
  status = dbwrap_fetch_bystring(regdb, tmp_ctx, tdbkey, &data);
2160
0
  if (!NT_STATUS_IS_OK(status)) {
2161
0
    err = WERR_FILE_NOT_FOUND;
2162
0
    goto done;
2163
0
  }
2164
2165
0
  status = unmarshall_sec_desc(mem_ctx, (uint8_t *)data.dptr, data.dsize,
2166
0
             psecdesc);
2167
2168
0
  if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
2169
0
    err = WERR_NOT_ENOUGH_MEMORY;
2170
0
  } else if (!NT_STATUS_IS_OK(status)) {
2171
0
    err = WERR_REGISTRY_CORRUPT;
2172
0
  }
2173
2174
0
done:
2175
0
  TALLOC_FREE(tmp_ctx);
2176
0
  return err;
2177
0
}
2178
2179
struct regdb_set_secdesc_ctx {
2180
  const char *key;
2181
  struct security_descriptor *secdesc;
2182
};
2183
2184
static NTSTATUS regdb_set_secdesc_action(struct db_context *db,
2185
           void *private_data)
2186
0
{
2187
0
  char *tdbkey;
2188
0
  NTSTATUS status;
2189
0
  TDB_DATA tdbdata;
2190
0
  struct regdb_set_secdesc_ctx *ctx =
2191
0
    (struct regdb_set_secdesc_ctx *)private_data;
2192
0
  TALLOC_CTX *frame = talloc_stackframe();
2193
2194
0
  tdbkey = talloc_asprintf(frame, "%s\\%s", REG_SECDESC_PREFIX, ctx->key);
2195
0
  if (tdbkey == NULL) {
2196
0
    status = NT_STATUS_NO_MEMORY;
2197
0
    goto done;
2198
0
  }
2199
2200
0
  tdbkey = normalize_reg_path(frame, tdbkey);
2201
0
  if (tdbkey == NULL) {
2202
0
    status = NT_STATUS_NO_MEMORY;
2203
0
    goto done;
2204
0
  }
2205
2206
0
  if (ctx->secdesc == NULL) {
2207
    /* assuming a delete */
2208
0
    status = dbwrap_delete_bystring(db, tdbkey);
2209
0
    goto done;
2210
0
  }
2211
2212
0
  status = marshall_sec_desc(frame, ctx->secdesc, &tdbdata.dptr,
2213
0
           &tdbdata.dsize);
2214
0
  if (!NT_STATUS_IS_OK(status)) {
2215
0
    goto done;
2216
0
  }
2217
2218
0
  status = dbwrap_store_bystring(db, tdbkey, tdbdata, 0);
2219
2220
0
done:
2221
0
  TALLOC_FREE(frame);
2222
0
  return status;
2223
0
}
2224
2225
static WERROR regdb_set_secdesc(const char *key,
2226
        struct security_descriptor *secdesc)
2227
0
{
2228
0
  WERROR err;
2229
0
  struct regdb_set_secdesc_ctx ctx;
2230
2231
0
  if (!regdb_key_exists(regdb, key)) {
2232
0
    err = WERR_FILE_NOT_FOUND;
2233
0
    goto done;
2234
0
  }
2235
2236
0
  ctx.key = key;
2237
0
  ctx.secdesc = secdesc;
2238
2239
0
  err = regdb_trans_do(regdb, regdb_set_secdesc_action, &ctx);
2240
2241
0
done:
2242
0
  return err;
2243
0
}
2244
2245
static bool regdb_subkeys_need_update(struct regsubkey_ctr *subkeys)
2246
0
{
2247
0
  return (regdb_get_seqnum() != regsubkey_ctr_get_seqnum(subkeys));
2248
0
}
2249
2250
static bool regdb_values_need_update(struct regval_ctr *values)
2251
0
{
2252
0
  return (regdb_get_seqnum() != regval_ctr_get_seqnum(values));
2253
0
}
2254
2255
/*
2256
 * Table of function pointers for default access
2257
 */
2258
2259
struct registry_ops regdb_ops = {
2260
  .fetch_subkeys = regdb_fetch_keys,
2261
  .fetch_values = regdb_fetch_values,
2262
  .store_subkeys = regdb_store_keys,
2263
  .store_values = regdb_store_values,
2264
  .create_subkey = regdb_create_subkey,
2265
  .delete_subkey = regdb_delete_subkey,
2266
  .get_secdesc = regdb_get_secdesc,
2267
  .set_secdesc = regdb_set_secdesc,
2268
  .subkeys_need_update = regdb_subkeys_need_update,
2269
  .values_need_update = regdb_values_need_update
2270
};