Line data Source code
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 : #define DBGC_CLASS DBGC_REGISTRY
40 :
41 : #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 23931 : static NTSTATUS regdb_trans_do_action(struct db_context *db, void *private_data)
70 : {
71 131 : NTSTATUS status;
72 131 : int32_t version_id;
73 23931 : struct regdb_trans_ctx *ctx = (struct regdb_trans_ctx *)private_data;
74 :
75 23931 : status = dbwrap_fetch_int32_bystring(db, REGDB_VERSION_KEYNAME,
76 : &version_id);
77 :
78 23931 : if (!NT_STATUS_IS_OK(status)) {
79 0 : DEBUG(0, ("ERROR: could not fetch registry db version: %s. "
80 : "Denying access.\n", nt_errstr(status)));
81 0 : return NT_STATUS_ACCESS_DENIED;
82 : }
83 :
84 23931 : if (version_id != REGDB_CODE_VERSION) {
85 0 : DEBUG(0, ("ERROR: changed registry version %d found while "
86 : "trying to write to the registry. Version %d "
87 : "expected. Denying access.\n",
88 : version_id, REGDB_CODE_VERSION));
89 0 : return NT_STATUS_ACCESS_DENIED;
90 : }
91 :
92 23931 : status = ctx->action(db, ctx->private_data);
93 23931 : return status;
94 : }
95 :
96 23931 : static WERROR regdb_trans_do(struct db_context *db,
97 : NTSTATUS (*action)(struct db_context *, void *),
98 : void *private_data)
99 : {
100 131 : NTSTATUS status;
101 131 : struct regdb_trans_ctx ctx;
102 :
103 :
104 23931 : ctx.action = action;
105 23931 : ctx.private_data = private_data;
106 :
107 23931 : status = dbwrap_trans_do(db, regdb_trans_do_action, &ctx);
108 :
109 23931 : return ntstatus_to_werror(status);
110 : }
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 318 : static WERROR create_key_recursive(struct db_context *db,
178 : char *path,
179 : const char *subkey)
180 : {
181 152 : WERROR werr;
182 152 : char *p;
183 :
184 318 : if (subkey == NULL) {
185 0 : return WERR_INVALID_PARAMETER;
186 : }
187 :
188 318 : if (path == NULL) {
189 90 : return regdb_create_basekey(db, subkey);
190 : }
191 :
192 258 : p = strrchr_m(path, '\\');
193 :
194 258 : if (p == NULL) {
195 53 : werr = create_key_recursive(db, NULL, path);
196 : } else {
197 205 : *p = '\0';
198 205 : werr = create_key_recursive(db, path, p+1);
199 205 : *p = '\\';
200 : }
201 :
202 258 : if (!W_ERROR_IS_OK(werr)) {
203 0 : goto done;
204 : }
205 :
206 258 : werr = regdb_create_subkey_internal(db, path, subkey);
207 :
208 258 : done:
209 258 : return werr;
210 : }
211 :
212 : /**
213 : * Initialize a key in the registry:
214 : * create each component key of the specified path.
215 : */
216 60 : static WERROR init_registry_key_internal(struct db_context *db,
217 : const char *add_path)
218 : {
219 30 : char *subkey, *key;
220 30 : WERROR werr;
221 60 : TALLOC_CTX *frame = talloc_stackframe();
222 :
223 60 : if (add_path == NULL) {
224 0 : werr = WERR_INVALID_PARAMETER;
225 0 : goto done;
226 : }
227 :
228 60 : key = talloc_strdup(frame, add_path);
229 :
230 60 : subkey = strrchr_m(key, '\\');
231 60 : if (subkey == NULL) {
232 2 : subkey = key;
233 2 : key = NULL;
234 : } else {
235 53 : *subkey = '\0';
236 53 : subkey++;
237 : }
238 :
239 60 : werr = create_key_recursive(db, key, subkey);
240 :
241 60 : done:
242 60 : talloc_free(frame);
243 60 : return werr;
244 : }
245 :
246 : struct init_registry_key_context {
247 : const char *add_path;
248 : };
249 :
250 0 : static NTSTATUS init_registry_key_action(struct db_context *db,
251 : void *private_data)
252 : {
253 0 : struct init_registry_key_context *init_ctx =
254 : (struct init_registry_key_context *)private_data;
255 :
256 0 : return werror_to_ntstatus(init_registry_key_internal(
257 : db, init_ctx->add_path));
258 : }
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 1053 : WERROR init_registry_key(const char *add_path)
266 : {
267 12 : struct init_registry_key_context init_ctx;
268 :
269 1053 : if (regdb_key_exists(regdb, add_path)) {
270 1053 : return WERR_OK;
271 : }
272 :
273 0 : init_ctx.add_path = add_path;
274 :
275 0 : return regdb_trans_do(regdb,
276 : init_registry_key_action,
277 : &init_ctx);
278 : }
279 :
280 : /***********************************************************************
281 : Open the registry data in the tdb
282 : ***********************************************************************/
283 :
284 4 : static void regdb_ctr_add_value(struct regval_ctr *ctr,
285 : struct builtin_regkey_value *value)
286 : {
287 4 : switch(value->type) {
288 1 : case REG_DWORD:
289 1 : regval_ctr_addvalue(ctr, value->valuename, REG_DWORD,
290 1 : (uint8_t *)&value->data.dw_value,
291 : sizeof(uint32_t));
292 1 : break;
293 :
294 3 : case REG_SZ:
295 3 : regval_ctr_addvalue_sz(ctr, value->valuename,
296 : value->data.string);
297 3 : break;
298 :
299 0 : default:
300 0 : DEBUG(0, ("regdb_ctr_add_value: invalid value type in "
301 : "registry values [%d]\n", value->type));
302 : }
303 4 : }
304 :
305 3 : static NTSTATUS init_registry_data_action(struct db_context *db,
306 : void *private_data)
307 : {
308 1 : NTSTATUS status;
309 3 : TALLOC_CTX *frame = talloc_stackframe();
310 1 : struct regval_ctr *values;
311 1 : int i;
312 :
313 : /* loop over all of the predefined paths and add each component */
314 :
315 94 : for (i=0; builtin_registry_paths[i] != NULL; i++) {
316 90 : if (regdb_key_exists(db, builtin_registry_paths[i])) {
317 30 : continue;
318 : }
319 60 : status = werror_to_ntstatus(init_registry_key_internal(db,
320 : builtin_registry_paths[i]));
321 60 : if (!NT_STATUS_IS_OK(status)) {
322 0 : goto done;
323 : }
324 : }
325 :
326 : /* loop over all of the predefined values and add each component */
327 :
328 15 : for (i=0; builtin_registry_values[i].path != NULL; i++) {
329 4 : WERROR werr;
330 :
331 12 : werr = regval_ctr_init(frame, &values);
332 12 : if (!W_ERROR_IS_OK(werr)) {
333 0 : status = werror_to_ntstatus(werr);
334 0 : goto done;
335 : }
336 :
337 12 : regdb_fetch_values_internal(db,
338 : builtin_registry_values[i].path,
339 : values);
340 :
341 : /* preserve existing values across restarts. Only add new ones */
342 :
343 12 : if (!regval_ctr_value_exists(values,
344 : builtin_registry_values[i].valuename))
345 : {
346 4 : regdb_ctr_add_value(values,
347 : &builtin_registry_values[i]);
348 4 : status = regdb_store_values_internal(db,
349 : builtin_registry_values[i].path,
350 : values);
351 4 : if (!NT_STATUS_IS_OK(status)) {
352 0 : goto done;
353 : }
354 : }
355 12 : TALLOC_FREE(values);
356 : }
357 :
358 2 : status = NT_STATUS_OK;
359 :
360 3 : done:
361 :
362 3 : TALLOC_FREE(frame);
363 3 : return status;
364 : }
365 :
366 1363 : WERROR init_registry_data(void)
367 : {
368 12 : WERROR werr;
369 1363 : TALLOC_CTX *frame = talloc_stackframe();
370 12 : struct regval_ctr *values;
371 12 : 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 42177 : for (i=0; builtin_registry_paths[i] != NULL; i++) {
378 40805 : if (!regdb_key_exists(regdb, builtin_registry_paths[i])) {
379 3 : goto do_init;
380 : }
381 : }
382 :
383 6800 : for (i=0; builtin_registry_values[i].path != NULL; i++) {
384 5440 : werr = regval_ctr_init(frame, &values);
385 5440 : W_ERROR_NOT_OK_GOTO_DONE(werr);
386 :
387 5440 : regdb_fetch_values_internal(regdb,
388 : builtin_registry_values[i].path,
389 : values);
390 5440 : if (!regval_ctr_value_exists(values,
391 : builtin_registry_values[i].valuename))
392 : {
393 0 : TALLOC_FREE(values);
394 0 : goto do_init;
395 : }
396 :
397 5440 : TALLOC_FREE(values);
398 : }
399 :
400 1360 : werr = WERR_OK;
401 1360 : goto done;
402 :
403 3 : 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 3 : werr = regdb_trans_do(regdb,
414 : init_registry_data_action,
415 : NULL);
416 :
417 1363 : done:
418 1363 : TALLOC_FREE(frame);
419 1363 : return werr;
420 : }
421 :
422 208 : static int regdb_normalize_keynames_fn(struct db_record *rec,
423 : void *private_data)
424 : {
425 208 : 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 208 : struct db_context *db = (struct db_context *)private_data;
431 :
432 208 : key = dbwrap_record_get_key(rec);
433 208 : if (key.dptr == NULL || key.dsize == 0) {
434 0 : return 0;
435 : }
436 :
437 208 : value = dbwrap_record_get_value(rec);
438 :
439 208 : if (db == NULL) {
440 0 : DEBUG(0, ("regdb_normalize_keynames_fn: ERROR: "
441 : "NULL db context handed in via private_data\n"));
442 0 : return 1;
443 : }
444 :
445 208 : if (strncmp((const char *)key.dptr, REGDB_VERSION_KEYNAME,
446 : strlen(REGDB_VERSION_KEYNAME)) == 0)
447 : {
448 4 : return 0;
449 : }
450 :
451 204 : keyname = strchr((const char *)key.dptr, '/');
452 204 : if (keyname) {
453 52 : keyname = talloc_string_sub(mem_ctx,
454 52 : (const char *)key.dptr,
455 : "/",
456 : "\\");
457 :
458 52 : DEBUG(2, ("regdb_normalize_keynames_fn: Convert %s to %s\n",
459 : (const char *)key.dptr,
460 : keyname));
461 :
462 : /* Delete the original record and store the normalized key */
463 52 : status = dbwrap_record_delete(rec);
464 52 : if (!NT_STATUS_IS_OK(status)) {
465 0 : DEBUG(0,("regdb_normalize_keynames_fn: "
466 : "tdb_delete for [%s] failed!\n",
467 : (const char *)key.dptr));
468 0 : return 1;
469 : }
470 :
471 52 : status = dbwrap_store_bystring(db, keyname, value, TDB_REPLACE);
472 52 : if (!NT_STATUS_IS_OK(status)) {
473 0 : DEBUG(0,("regdb_normalize_keynames_fn: "
474 : "failed to store new record for [%s]!\n",
475 : keyname));
476 0 : return 1;
477 : }
478 : }
479 :
480 204 : return 0;
481 : }
482 :
483 15 : static WERROR regdb_store_regdb_version(struct db_context *db, uint32_t version)
484 : {
485 1 : NTSTATUS status;
486 15 : if (db == NULL) {
487 0 : return WERR_CAN_NOT_COMPLETE;
488 : }
489 :
490 15 : status = dbwrap_trans_store_int32_bystring(db, REGDB_VERSION_KEYNAME,
491 : version);
492 15 : if (!NT_STATUS_IS_OK(status)) {
493 0 : DEBUG(1, ("regdb_store_regdb_version: error storing %s = %d: %s\n",
494 : REGDB_VERSION_KEYNAME, version, nt_errstr(status)));
495 0 : return ntstatus_to_werror(status);
496 : } else {
497 15 : DEBUG(10, ("regdb_store_regdb_version: stored %s = %d\n",
498 : REGDB_VERSION_KEYNAME, version));
499 15 : return WERR_OK;
500 : }
501 : }
502 :
503 4 : static WERROR regdb_upgrade_v1_to_v2(struct db_context *db)
504 : {
505 0 : TALLOC_CTX *mem_ctx;
506 0 : NTSTATUS status;
507 0 : WERROR werr;
508 :
509 4 : mem_ctx = talloc_stackframe();
510 :
511 4 : status = dbwrap_traverse(db, regdb_normalize_keynames_fn, db, NULL);
512 4 : if (!NT_STATUS_IS_OK(status)) {
513 0 : werr = WERR_REGISTRY_IO_FAILED;
514 0 : goto done;
515 : }
516 :
517 4 : werr = regdb_store_regdb_version(db, REGDB_VERSION_V2);
518 :
519 4 : done:
520 4 : talloc_free(mem_ctx);
521 4 : return werr;
522 : }
523 :
524 284 : static bool tdb_data_read_uint32(TDB_DATA *buf, uint32_t *result)
525 : {
526 284 : const size_t len = sizeof(uint32_t);
527 284 : if (buf->dsize >= len) {
528 284 : *result = IVAL(buf->dptr, 0);
529 284 : buf->dptr += len;
530 284 : buf->dsize -= len;
531 284 : return true;
532 : }
533 0 : return false;
534 : }
535 :
536 534 : static bool tdb_data_read_cstr(TDB_DATA *buf, char **result)
537 : {
538 534 : const size_t len = strnlen((char*)buf->dptr, buf->dsize) + 1;
539 534 : if (buf->dsize >= len) {
540 250 : *result = (char*)buf->dptr;
541 250 : buf->dptr += len;
542 250 : buf->dsize -= len;
543 250 : return true;
544 : }
545 284 : return false;
546 : }
547 :
548 284 : static bool tdb_data_is_cstr(TDB_DATA d) {
549 284 : if (tdb_data_is_empty(d) || (d.dptr[d.dsize-1] != '\0')) {
550 0 : return false;
551 : }
552 284 : return strlen((char *)d.dptr) == (d.dsize-1);
553 : }
554 :
555 250 : static bool upgrade_v2_to_v3_check_subkeylist(struct db_context *db,
556 : const char *key,
557 : const char *subkey)
558 : {
559 0 : static uint32_t zero = 0;
560 0 : static TDB_DATA empty_subkey_list = {
561 : .dptr = (unsigned char*)&zero,
562 : .dsize = sizeof(uint32_t),
563 : };
564 250 : bool success = false;
565 250 : char *path = talloc_asprintf(talloc_tos(), "%s\\%s", key, subkey);
566 250 : if (!strupper_m(path)) {
567 0 : goto done;
568 : }
569 :
570 250 : 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 : path));
575 :
576 0 : status = dbwrap_store_bystring(db, path, empty_subkey_list,
577 : TDB_INSERT);
578 0 : if (!NT_STATUS_IS_OK(status)) {
579 0 : DEBUG(0, ("regdb_upgrade_v2_to_v3: writing subkey list "
580 : "[%s] failed\n", path));
581 0 : goto done;
582 : }
583 : }
584 250 : success = true;
585 250 : done:
586 250 : talloc_free(path);
587 250 : return success;
588 : }
589 :
590 250 : static bool upgrade_v2_to_v3_check_parent(struct db_context *db,
591 : const char *key)
592 : {
593 250 : const char *sep = strrchr_m(key, '\\');
594 250 : if (sep != NULL) {
595 234 : char *pkey = talloc_strndup(talloc_tos(), key, sep-key);
596 234 : if (!dbwrap_exists(db, string_term_tdb_data(pkey))) {
597 0 : DEBUG(0, ("regdb_upgrade_v2_to_v3: missing subkey list "
598 : "[%s]\nrun \"net registry check\"\n", pkey));
599 : }
600 234 : talloc_free(pkey);
601 : }
602 250 : return true;
603 : }
604 :
605 :
606 : #define IS_EQUAL(d,s) (((d).dsize == strlen(s)+1) && \
607 : (strcmp((char*)(d).dptr, (s)) == 0))
608 : #define STARTS_WITH(d,s) (((d).dsize > strlen(s)) && \
609 : (strncmp((char*)(d).dptr, (s), strlen(s)) == 0))
610 : #define SSTR(d) (int)(d).dsize , (char*)(d).dptr
611 :
612 :
613 308 : static int regdb_upgrade_v2_to_v3_fn(struct db_record *rec, void *private_data)
614 : {
615 308 : struct db_context *db = (struct db_context *)private_data;
616 308 : TDB_DATA key = dbwrap_record_get_key(rec);
617 308 : TDB_DATA val = dbwrap_record_get_value(rec);
618 :
619 308 : if (tdb_data_is_empty(key)) {
620 0 : return 0;
621 : }
622 :
623 308 : if (db == NULL) {
624 0 : DEBUG(0, ("regdb_upgrade_v2_to_v3_fn: ERROR: "
625 : "NULL db context handed in via private_data\n"));
626 0 : return 1;
627 : }
628 :
629 308 : if (IS_EQUAL(key, REGDB_VERSION_KEYNAME) ||
630 302 : STARTS_WITH(key, REG_VALUE_PREFIX) ||
631 284 : STARTS_WITH(key, REG_SECDESC_PREFIX))
632 : {
633 24 : DEBUG(10, ("regdb_upgrade_v2_to_v3: skipping [%.*s]\n",
634 : SSTR(key)));
635 24 : return 0;
636 : }
637 :
638 284 : 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 : 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 : "failed!\n", SSTR(key)));
649 0 : return 1;
650 : }
651 :
652 0 : return 0;
653 : }
654 :
655 568 : if ( tdb_data_is_cstr(key) &&
656 284 : hive_info((char*)key.dptr) != NULL )
657 284 : {
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 284 : TDB_DATA pos = val;
664 284 : char *subkey, *path = (char*)key.dptr;
665 284 : uint32_t num_items, found_items = 0;
666 :
667 :
668 284 : DEBUG(10, ("regdb_upgrade_v2_to_v3: scanning subkeylist of "
669 : "[%s]\n", path));
670 :
671 284 : if (!tdb_data_read_uint32(&pos, &num_items)) {
672 : /* invalid or empty - skip */
673 0 : return 0;
674 : }
675 :
676 534 : while (tdb_data_read_cstr(&pos, &subkey)) {
677 250 : found_items++;
678 :
679 250 : if (!upgrade_v2_to_v3_check_subkeylist(db, path, subkey))
680 : {
681 0 : return 1;
682 : }
683 :
684 250 : if (!upgrade_v2_to_v3_check_parent(db, path)) {
685 0 : return 1;
686 : }
687 : }
688 284 : if (found_items != num_items) {
689 0 : DEBUG(0, ("regdb_upgrade_v2_to_v3: inconsistent subkey "
690 : "list [%s]\nrun \"net registry check\"\n",
691 : path));
692 : }
693 : } else {
694 0 : DEBUG(10, ("regdb_upgrade_v2_to_v3: skipping invalid [%.*s]\n"
695 : "run \"net registry check\"\n", SSTR(key)));
696 : }
697 :
698 284 : return 0;
699 : }
700 :
701 6 : static WERROR regdb_upgrade_v2_to_v3(struct db_context *db)
702 : {
703 0 : NTSTATUS status;
704 0 : WERROR werr;
705 :
706 6 : status = dbwrap_traverse(db, regdb_upgrade_v2_to_v3_fn, db, NULL);
707 6 : if (!NT_STATUS_IS_OK(status)) {
708 0 : werr = WERR_REGISTRY_IO_FAILED;
709 0 : goto done;
710 : }
711 :
712 6 : werr = regdb_store_regdb_version(db, REGDB_VERSION_V3);
713 :
714 6 : done:
715 6 : return werr;
716 : }
717 :
718 : /***********************************************************************
719 : Open the registry database
720 : ***********************************************************************/
721 :
722 1363 : WERROR regdb_init(void)
723 : {
724 12 : int32_t vers_id;
725 12 : WERROR werr;
726 12 : NTSTATUS status;
727 12 : char *db_path;
728 :
729 1363 : if (regdb) {
730 24 : DEBUG(10, ("regdb_init: incrementing refcount (%d->%d)\n",
731 : regdb_refcount, regdb_refcount+1));
732 24 : regdb_refcount++;
733 24 : return WERR_OK;
734 : }
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 1339 : 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 : }
744 :
745 1339 : db_path = state_path(talloc_tos(), "registry.tdb");
746 1339 : if (db_path == NULL) {
747 0 : return WERR_NOT_ENOUGH_MEMORY;
748 : }
749 :
750 1339 : regdb = db_open(NULL, db_path, 0,
751 : REG_TDB_FLAGS, O_RDWR, 0600,
752 : DBWRAP_LOCK_ORDER_1, REG_DBWRAP_FLAGS);
753 1339 : if (!regdb) {
754 1 : regdb = db_open(NULL, db_path, 0,
755 : REG_TDB_FLAGS, O_RDWR|O_CREAT, 0600,
756 : DBWRAP_LOCK_ORDER_1, REG_DBWRAP_FLAGS);
757 1 : 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 : db_path, strerror(errno) ));
761 0 : TALLOC_FREE(db_path);
762 0 : return werr;
763 : }
764 :
765 1 : werr = regdb_store_regdb_version(regdb, REGDB_CODE_VERSION);
766 1 : if (!W_ERROR_IS_OK(werr)) {
767 0 : DEBUG(1, ("regdb_init: Failed to store version: %s\n",
768 : win_errstr(werr)));
769 0 : TALLOC_FREE(db_path);
770 0 : return werr;
771 : }
772 :
773 1 : DEBUG(10,("regdb_init: Successfully created registry tdb\n"));
774 : }
775 1339 : TALLOC_FREE(db_path);
776 :
777 1339 : regdb_refcount = 1;
778 1339 : DEBUG(10, ("regdb_init: registry db opened. refcount reset (%d)\n",
779 : regdb_refcount));
780 :
781 1339 : status = dbwrap_fetch_int32_bystring(regdb, REGDB_VERSION_KEYNAME,
782 : &vers_id);
783 1339 : if (!NT_STATUS_IS_OK(status)) {
784 4 : DBG_DEBUG("Reading registry version failed: %s, "
785 : "initializing to version %d\n",
786 : 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 4 : werr = regdb_store_regdb_version(regdb, REGDB_VERSION_V1);
800 4 : if (!W_ERROR_IS_OK(werr)) {
801 0 : return werr;
802 : }
803 4 : vers_id = REGDB_VERSION_V1;
804 : }
805 :
806 1339 : if (vers_id == REGDB_CODE_VERSION) {
807 1333 : return WERR_OK;
808 : }
809 :
810 6 : if (vers_id > REGDB_CODE_VERSION || vers_id == 0) {
811 0 : DEBUG(0, ("regdb_init: unknown registry version %d "
812 : "(code version = %d), refusing initialization\n",
813 : vers_id, REGDB_CODE_VERSION));
814 0 : return WERR_CAN_NOT_COMPLETE;
815 : }
816 :
817 6 : if (dbwrap_transaction_start(regdb) != 0) {
818 0 : return WERR_REGISTRY_IO_FAILED;
819 : }
820 :
821 6 : if (vers_id == REGDB_VERSION_V1) {
822 4 : DEBUG(10, ("regdb_init: upgrading registry from version %d "
823 : "to %d\n", REGDB_VERSION_V1, REGDB_VERSION_V2));
824 :
825 4 : werr = regdb_upgrade_v1_to_v2(regdb);
826 4 : if (!W_ERROR_IS_OK(werr)) {
827 0 : dbwrap_transaction_cancel(regdb);
828 0 : return werr;
829 : }
830 :
831 4 : vers_id = REGDB_VERSION_V2;
832 : }
833 :
834 6 : if (vers_id == REGDB_VERSION_V2) {
835 6 : DEBUG(10, ("regdb_init: upgrading registry from version %d "
836 : "to %d\n", REGDB_VERSION_V2, REGDB_VERSION_V3));
837 :
838 6 : werr = regdb_upgrade_v2_to_v3(regdb);
839 6 : if (!W_ERROR_IS_OK(werr)) {
840 0 : dbwrap_transaction_cancel(regdb);
841 0 : return werr;
842 : }
843 :
844 6 : vers_id = REGDB_VERSION_V3;
845 : }
846 :
847 : /* future upgrade code should go here */
848 :
849 6 : if (dbwrap_transaction_commit(regdb) != 0) {
850 0 : return WERR_REGISTRY_IO_FAILED;
851 : }
852 :
853 6 : return WERR_OK;
854 : }
855 :
856 : /***********************************************************************
857 : Open the registry. Must already have been initialized by regdb_init()
858 : ***********************************************************************/
859 :
860 3319914 : WERROR regdb_open( void )
861 : {
862 232 : WERROR result;
863 3319914 : char *db_path = NULL;
864 232 : int saved_errno;
865 :
866 3319914 : if ( regdb ) {
867 3302410 : DEBUG(10, ("regdb_open: incrementing refcount (%d->%d)\n",
868 : regdb_refcount, regdb_refcount+1));
869 3302410 : regdb_refcount++;
870 3302410 : result = WERR_OK;
871 3302410 : goto done;
872 : }
873 :
874 17504 : db_path = state_path(talloc_tos(), "registry.tdb");
875 17504 : if (db_path == NULL) {
876 0 : result = WERR_NOT_ENOUGH_MEMORY;
877 0 : goto done;
878 : }
879 :
880 17504 : become_root();
881 :
882 17504 : regdb = db_open(NULL, db_path, 0,
883 : REG_TDB_FLAGS, O_RDWR, 0600,
884 : DBWRAP_LOCK_ORDER_1, REG_DBWRAP_FLAGS);
885 17504 : saved_errno = errno;
886 17504 : unbecome_root();
887 17504 : 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 : db_path, strerror(saved_errno)));
891 0 : goto done;
892 : }
893 :
894 17504 : regdb_refcount = 1;
895 17504 : DEBUG(10, ("regdb_open: registry db opened. refcount reset (%d)\n",
896 : regdb_refcount));
897 :
898 17492 : result = WERR_OK;
899 3319694 : done:
900 3319914 : TALLOC_FREE(db_path);
901 3319914 : return result;
902 : }
903 :
904 : /***********************************************************************
905 : ***********************************************************************/
906 :
907 3320385 : int regdb_close( void )
908 : {
909 3320385 : if (regdb_refcount == 0) {
910 0 : return 0;
911 : }
912 :
913 3320385 : regdb_refcount--;
914 :
915 3320385 : DEBUG(10, ("regdb_close: decrementing refcount (%d->%d)\n",
916 : regdb_refcount+1, regdb_refcount));
917 :
918 3320385 : if ( regdb_refcount > 0 )
919 3301768 : return 0;
920 :
921 18397 : SMB_ASSERT( regdb_refcount >= 0 );
922 :
923 18397 : TALLOC_FREE(regdb);
924 18373 : return 0;
925 : }
926 :
927 63099 : WERROR regdb_transaction_start(void)
928 : {
929 63099 : return (dbwrap_transaction_start(regdb) == 0) ?
930 63099 : WERR_OK : WERR_REGISTRY_IO_FAILED;
931 : }
932 :
933 62925 : WERROR regdb_transaction_commit(void)
934 : {
935 62925 : return (dbwrap_transaction_commit(regdb) == 0) ?
936 62925 : WERR_OK : WERR_REGISTRY_IO_FAILED;
937 : }
938 :
939 174 : WERROR regdb_transaction_cancel(void)
940 : {
941 174 : return (dbwrap_transaction_cancel(regdb) == 0) ?
942 174 : WERR_OK : WERR_REGISTRY_IO_FAILED;
943 : }
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 571309 : int regdb_get_seqnum(void)
951 : {
952 571309 : return dbwrap_get_seqnum(regdb);
953 : }
954 :
955 :
956 7667 : static WERROR regdb_delete_key_with_prefix(struct db_context *db,
957 : const char *keyname,
958 : const char *prefix)
959 : {
960 33 : char *path;
961 7667 : WERROR werr = WERR_NOT_ENOUGH_MEMORY;
962 7667 : TALLOC_CTX *mem_ctx = talloc_stackframe();
963 :
964 7667 : if (keyname == NULL) {
965 0 : werr = WERR_INVALID_PARAMETER;
966 0 : goto done;
967 : }
968 :
969 7667 : if (prefix == NULL) {
970 1583 : path = discard_const_p(char, keyname);
971 : } else {
972 6073 : path = talloc_asprintf(mem_ctx, "%s\\%s", prefix, keyname);
973 6073 : if (path == NULL) {
974 0 : goto done;
975 : }
976 : }
977 :
978 7667 : path = normalize_reg_path(mem_ctx, path);
979 7667 : if (path == NULL) {
980 0 : goto done;
981 : }
982 :
983 7667 : werr = ntstatus_to_werror(dbwrap_purge_bystring(db, path));
984 :
985 7667 : done:
986 7667 : talloc_free(mem_ctx);
987 7667 : return werr;
988 : }
989 :
990 :
991 4479 : static WERROR regdb_delete_values(struct db_context *db, const char *keyname)
992 : {
993 4479 : return regdb_delete_key_with_prefix(db, keyname, REG_VALUE_PREFIX);
994 : }
995 :
996 1594 : static WERROR regdb_delete_secdesc(struct db_context *db, const char *keyname)
997 : {
998 1594 : return regdb_delete_key_with_prefix(db, keyname, REG_SECDESC_PREFIX);
999 : }
1000 :
1001 1594 : static WERROR regdb_delete_subkeylist(struct db_context *db, const char *keyname)
1002 : {
1003 1594 : return regdb_delete_key_with_prefix(db, keyname, NULL);
1004 : }
1005 :
1006 :
1007 1594 : static WERROR regdb_delete_key_lists(struct db_context *db, const char *keyname)
1008 : {
1009 11 : WERROR werr;
1010 :
1011 1594 : werr = regdb_delete_values(db, keyname);
1012 1594 : if (!W_ERROR_IS_OK(werr)) {
1013 0 : DEBUG(1, (__location__ " Deleting %s\\%s failed: %s\n",
1014 : REG_VALUE_PREFIX, keyname, win_errstr(werr)));
1015 0 : goto done;
1016 : }
1017 :
1018 1594 : werr = regdb_delete_secdesc(db, keyname);
1019 1594 : if (!W_ERROR_IS_OK(werr)) {
1020 0 : DEBUG(1, (__location__ " Deleting %s\\%s failed: %s\n",
1021 : REG_SECDESC_PREFIX, keyname, win_errstr(werr)));
1022 0 : goto done;
1023 : }
1024 :
1025 1594 : werr = regdb_delete_subkeylist(db, keyname);
1026 1594 : if (!W_ERROR_IS_OK(werr)) {
1027 0 : DEBUG(1, (__location__ " Deleting %s failed: %s\n",
1028 : keyname, win_errstr(werr)));
1029 0 : goto done;
1030 : }
1031 :
1032 1594 : done:
1033 1594 : return werr;
1034 : }
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 6870 : static WERROR regdb_store_keys_internal2(struct db_context *db,
1043 : const char *key,
1044 : struct regsubkey_ctr *ctr)
1045 : {
1046 147 : TDB_DATA dbuf;
1047 6870 : uint8_t *buffer = NULL;
1048 6870 : uint32_t i = 0;
1049 147 : uint32_t len, buflen;
1050 6870 : uint32_t num_subkeys = regsubkey_ctr_numkeys(ctr);
1051 6870 : char *keyname = NULL;
1052 6870 : TALLOC_CTX *ctx = talloc_stackframe();
1053 147 : WERROR werr;
1054 :
1055 6870 : if (!key) {
1056 0 : werr = WERR_INVALID_PARAMETER;
1057 0 : goto done;
1058 : }
1059 :
1060 6870 : keyname = talloc_strdup(ctx, key);
1061 6870 : if (!keyname) {
1062 0 : werr = WERR_NOT_ENOUGH_MEMORY;
1063 0 : goto done;
1064 : }
1065 :
1066 6870 : keyname = normalize_reg_path(ctx, keyname);
1067 6870 : if (!keyname) {
1068 0 : werr = WERR_NOT_ENOUGH_MEMORY;
1069 0 : goto done;
1070 : }
1071 :
1072 : /* allocate some initial memory */
1073 :
1074 6870 : buffer = (uint8_t *)SMB_MALLOC(1024);
1075 6870 : if (buffer == NULL) {
1076 0 : werr = WERR_NOT_ENOUGH_MEMORY;
1077 0 : goto done;
1078 : }
1079 6870 : buflen = 1024;
1080 6870 : len = 0;
1081 :
1082 : /* store the number of subkeys */
1083 :
1084 6870 : len += tdb_pack(buffer+len, buflen-len, "d", num_subkeys);
1085 :
1086 : /* pack all the strings */
1087 :
1088 130655 : for (i=0; i<num_subkeys; i++) {
1089 107 : size_t thistime;
1090 :
1091 123785 : thistime = tdb_pack(buffer+len, buflen-len, "f",
1092 : regsubkey_ctr_specific_key(ctr, i));
1093 123785 : 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 282 : buffer = SMB_REALLOC_ARRAY(buffer, uint8_t,
1100 : (len+thistime)*2);
1101 282 : if(buffer == NULL) {
1102 0 : DEBUG(0, ("regdb_store_keys: Failed to realloc "
1103 : "memory of size [%u]\n",
1104 : (unsigned int)(len+thistime)*2));
1105 0 : werr = WERR_NOT_ENOUGH_MEMORY;
1106 0 : goto done;
1107 : }
1108 282 : buflen = (len+thistime)*2;
1109 282 : thistime2 = tdb_pack(
1110 282 : buffer+len, buflen-len, "f",
1111 : regsubkey_ctr_specific_key(ctr, i));
1112 282 : if (thistime2 != thistime) {
1113 0 : DEBUG(0, ("tdb_pack failed\n"));
1114 0 : werr = WERR_CAN_NOT_COMPLETE;
1115 0 : goto done;
1116 : }
1117 : }
1118 123785 : len += thistime;
1119 : }
1120 :
1121 : /* finally write out the data */
1122 :
1123 6870 : dbuf.dptr = buffer;
1124 6870 : dbuf.dsize = len;
1125 6870 : werr = ntstatus_to_werror(dbwrap_store_bystring(db, keyname, dbuf,
1126 : TDB_REPLACE));
1127 :
1128 6870 : done:
1129 6870 : TALLOC_FREE(ctx);
1130 6870 : SAFE_FREE(buffer);
1131 6870 : return werr;
1132 : }
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 2694 : static WERROR regdb_store_subkey_list(struct db_context *db, const char *parent,
1145 : const char *key)
1146 : {
1147 95 : WERROR werr;
1148 2694 : char *path = NULL;
1149 2694 : struct regsubkey_ctr *subkeys = NULL;
1150 2694 : TALLOC_CTX *frame = talloc_stackframe();
1151 :
1152 2694 : if (parent == NULL) {
1153 60 : path = talloc_strdup(frame, key);
1154 : } else {
1155 2634 : path = talloc_asprintf(frame, "%s\\%s", parent, key);
1156 : }
1157 2694 : if (!path) {
1158 0 : werr = WERR_NOT_ENOUGH_MEMORY;
1159 0 : goto done;
1160 : }
1161 :
1162 2694 : werr = regsubkey_ctr_init(frame, &subkeys);
1163 2694 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1164 :
1165 2694 : werr = regdb_fetch_keys_internal(db, path, subkeys);
1166 2694 : if (W_ERROR_IS_OK(werr)) {
1167 : /* subkey list exists already - don't modify */
1168 52 : goto done;
1169 : }
1170 :
1171 2642 : werr = regsubkey_ctr_reinit(subkeys);
1172 2642 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1173 :
1174 : /* create a record with 0 subkeys */
1175 2642 : werr = regdb_store_keys_internal2(db, path, subkeys);
1176 2642 : if (!W_ERROR_IS_OK(werr)) {
1177 0 : DEBUG(0, ("regdb_store_keys: Failed to store new record for "
1178 : "key [%s]: %s\n", path, win_errstr(werr)));
1179 0 : goto done;
1180 : }
1181 :
1182 2642 : done:
1183 2694 : talloc_free(frame);
1184 2694 : return werr;
1185 : }
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 0 : static NTSTATUS regdb_store_keys_action(struct db_context *db,
1198 : void *private_data)
1199 : {
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 : {
1221 0 : goto done;
1222 : }
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 : }
1257 :
1258 0 : path = talloc_asprintf(mem_ctx, "%s\\%s", store_ctx->key,
1259 : oldkeyname);
1260 0 : if (!path) {
1261 0 : werr = WERR_NOT_ENOUGH_MEMORY;
1262 0 : goto done;
1263 : }
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 : }
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 : "for parent [%s]: %s\n", store_ctx->key,
1279 : win_errstr(werr)));
1280 0 : goto done;
1281 : }
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 : }
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 : }
1306 :
1307 0 : static bool regdb_store_keys_internal(struct db_context *db, const char *key,
1308 : struct regsubkey_ctr *ctr)
1309 : {
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 : }
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 : }
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 : {
1336 0 : goto done;
1337 : }
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 : (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)
1348 : {
1349 0 : break;
1350 : }
1351 : }
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 : }
1361 : }
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 : regdb_store_keys_action,
1370 : &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 : }
1379 :
1380 0 : static bool regdb_store_keys(const char *key, struct regsubkey_ctr *ctr)
1381 : {
1382 0 : return regdb_store_keys_internal(regdb, key, ctr);
1383 : }
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 2634 : static NTSTATUS regdb_create_subkey_action(struct db_context *db,
1395 : void *private_data)
1396 : {
1397 65 : WERROR werr;
1398 65 : struct regdb_create_subkey_context *create_ctx;
1399 65 : struct regsubkey_ctr *subkeys;
1400 2634 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1401 :
1402 2634 : create_ctx = (struct regdb_create_subkey_context *)private_data;
1403 :
1404 2634 : werr = regsubkey_ctr_init(mem_ctx, &subkeys);
1405 2634 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1406 :
1407 2634 : werr = regdb_fetch_keys_internal(db, create_ctx->key, subkeys);
1408 2634 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1409 :
1410 2634 : werr = regsubkey_ctr_addkey(subkeys, create_ctx->subkey);
1411 2634 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1412 :
1413 2634 : werr = regdb_store_keys_internal2(db, create_ctx->key, subkeys);
1414 2634 : if (!W_ERROR_IS_OK(werr)) {
1415 0 : DEBUG(0, (__location__ " failed to store new subkey list for "
1416 : "parent key %s: %s\n", create_ctx->key,
1417 : win_errstr(werr)));
1418 : }
1419 :
1420 2634 : werr = regdb_store_subkey_list(db, create_ctx->key, create_ctx->subkey);
1421 :
1422 2634 : done:
1423 2634 : talloc_free(mem_ctx);
1424 2634 : return werror_to_ntstatus(werr);
1425 : }
1426 :
1427 2785 : static WERROR regdb_create_subkey_internal(struct db_context *db,
1428 : const char *key,
1429 : const char *subkey)
1430 : {
1431 136 : WERROR werr;
1432 136 : struct regsubkey_ctr *subkeys;
1433 2785 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1434 136 : struct regdb_create_subkey_context create_ctx;
1435 :
1436 2785 : if (!regdb_key_exists(db, key)) {
1437 0 : werr = WERR_NOT_FOUND;
1438 0 : goto done;
1439 : }
1440 :
1441 2785 : werr = regsubkey_ctr_init(mem_ctx, &subkeys);
1442 2785 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1443 :
1444 2785 : werr = regdb_fetch_keys_internal(db, key, subkeys);
1445 2785 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1446 :
1447 2785 : if (regsubkey_ctr_key_exists(subkeys, subkey)) {
1448 71 : char *newkey;
1449 :
1450 151 : newkey = talloc_asprintf(mem_ctx, "%s\\%s", key, subkey);
1451 151 : if (newkey == NULL) {
1452 0 : werr = WERR_NOT_ENOUGH_MEMORY;
1453 0 : goto done;
1454 : }
1455 :
1456 151 : if (regdb_key_exists(db, newkey)) {
1457 151 : werr = WERR_OK;
1458 151 : goto done;
1459 : }
1460 : }
1461 :
1462 2634 : talloc_free(subkeys);
1463 :
1464 2634 : create_ctx.key = key;
1465 2634 : create_ctx.subkey = subkey;
1466 :
1467 2634 : werr = regdb_trans_do(db,
1468 : regdb_create_subkey_action,
1469 : &create_ctx);
1470 :
1471 2785 : done:
1472 2785 : talloc_free(mem_ctx);
1473 2785 : return werr;
1474 : }
1475 :
1476 2527 : static WERROR regdb_create_subkey(const char *key, const char *subkey)
1477 : {
1478 2527 : return regdb_create_subkey_internal(regdb, key, subkey);
1479 : }
1480 :
1481 : /**
1482 : * create a base key
1483 : */
1484 :
1485 : struct regdb_create_basekey_context {
1486 : const char *key;
1487 : };
1488 :
1489 60 : static NTSTATUS regdb_create_basekey_action(struct db_context *db,
1490 : void *private_data)
1491 : {
1492 30 : WERROR werr;
1493 30 : struct regdb_create_basekey_context *create_ctx;
1494 :
1495 60 : create_ctx = (struct regdb_create_basekey_context *)private_data;
1496 :
1497 60 : werr = regdb_store_subkey_list(db, NULL, create_ctx->key);
1498 :
1499 60 : return werror_to_ntstatus(werr);
1500 : }
1501 :
1502 60 : static WERROR regdb_create_basekey(struct db_context *db, const char *key)
1503 : {
1504 30 : WERROR werr;
1505 30 : struct regdb_create_subkey_context create_ctx;
1506 :
1507 60 : create_ctx.key = key;
1508 :
1509 60 : werr = regdb_trans_do(db,
1510 : regdb_create_basekey_action,
1511 : &create_ctx);
1512 :
1513 60 : return werr;
1514 : }
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 1594 : static NTSTATUS regdb_delete_subkey_action(struct db_context *db,
1528 : void *private_data)
1529 : {
1530 11 : WERROR werr;
1531 11 : struct regdb_delete_subkey_context *delete_ctx;
1532 11 : struct regsubkey_ctr *subkeys;
1533 1594 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1534 :
1535 1594 : delete_ctx = (struct regdb_delete_subkey_context *)private_data;
1536 :
1537 1594 : werr = regdb_delete_key_lists(db, delete_ctx->path);
1538 1594 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1539 :
1540 1594 : if (delete_ctx->lazy) {
1541 0 : goto done;
1542 : }
1543 :
1544 1594 : werr = regsubkey_ctr_init(mem_ctx, &subkeys);
1545 1594 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1546 :
1547 1594 : werr = regdb_fetch_keys_internal(db, delete_ctx->key, subkeys);
1548 1594 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1549 :
1550 1594 : werr = regsubkey_ctr_delkey(subkeys, delete_ctx->subkey);
1551 1594 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1552 :
1553 1594 : werr = regdb_store_keys_internal2(db, delete_ctx->key, subkeys);
1554 1594 : if (!W_ERROR_IS_OK(werr)) {
1555 0 : DEBUG(0, (__location__ " failed to store new subkey_list for "
1556 : "parent key %s: %s\n", delete_ctx->key,
1557 : win_errstr(werr)));
1558 : }
1559 :
1560 1594 : done:
1561 1594 : talloc_free(mem_ctx);
1562 1594 : return werror_to_ntstatus(werr);
1563 : }
1564 :
1565 1594 : static WERROR regdb_delete_subkey(const char *key, const char *subkey, bool lazy)
1566 : {
1567 11 : WERROR werr;
1568 11 : char *path;
1569 11 : struct regdb_delete_subkey_context delete_ctx;
1570 1594 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1571 :
1572 1594 : if (!regdb_key_exists(regdb, key)) {
1573 0 : werr = WERR_NOT_FOUND;
1574 0 : goto done;
1575 : }
1576 :
1577 1594 : path = talloc_asprintf(mem_ctx, "%s\\%s", key, subkey);
1578 1594 : if (path == NULL) {
1579 0 : werr = WERR_NOT_ENOUGH_MEMORY;
1580 0 : goto done;
1581 : }
1582 :
1583 1594 : if (!regdb_key_exists(regdb, path)) {
1584 0 : werr = WERR_OK;
1585 0 : goto done;
1586 : }
1587 :
1588 1594 : delete_ctx.key = key;
1589 1594 : delete_ctx.subkey = subkey;
1590 1594 : delete_ctx.path = path;
1591 1594 : delete_ctx.lazy = lazy;
1592 :
1593 1594 : werr = regdb_trans_do(regdb,
1594 : regdb_delete_subkey_action,
1595 : &delete_ctx);
1596 :
1597 1594 : done:
1598 1594 : talloc_free(mem_ctx);
1599 1594 : return werr;
1600 : }
1601 :
1602 3938932 : static TDB_DATA regdb_fetch_key_internal(struct db_context *db,
1603 : TALLOC_CTX *mem_ctx, const char *key)
1604 : {
1605 3938932 : char *path = NULL;
1606 1841 : TDB_DATA data;
1607 1841 : NTSTATUS status;
1608 :
1609 3938932 : path = normalize_reg_path(mem_ctx, key);
1610 3938932 : if (!path) {
1611 0 : return make_tdb_data(NULL, 0);
1612 : }
1613 :
1614 3938932 : status = dbwrap_fetch_bystring(db, mem_ctx, path, &data);
1615 3938932 : if (!NT_STATUS_IS_OK(status)) {
1616 2931602 : data = tdb_null;
1617 : }
1618 :
1619 3938932 : TALLOC_FREE(path);
1620 3938932 : return data;
1621 : }
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 3475630 : static bool regdb_key_exists(struct db_context *db, const char *key)
1637 : {
1638 3475630 : TALLOC_CTX *mem_ctx = talloc_stackframe();
1639 1326 : TDB_DATA value;
1640 3475630 : bool ret = false;
1641 1326 : char *path;
1642 1326 : uint32_t buflen;
1643 1326 : const char *buf;
1644 1326 : uint32_t num_items, i;
1645 1326 : int32_t len;
1646 :
1647 3475630 : if (key == NULL) {
1648 0 : goto done;
1649 : }
1650 :
1651 3475630 : path = normalize_reg_path(mem_ctx, key);
1652 3475630 : if (path == NULL) {
1653 0 : DEBUG(0, ("out of memory! (talloc failed)\n"));
1654 0 : goto done;
1655 : }
1656 :
1657 3475630 : if (*path == '\0') {
1658 0 : goto done;
1659 : }
1660 :
1661 3475630 : value = regdb_fetch_key_internal(db, mem_ctx, path);
1662 3475630 : if (value.dptr == NULL) {
1663 2923720 : goto done;
1664 : }
1665 :
1666 551910 : if (value.dsize == 0) {
1667 0 : DEBUG(10, ("regdb_key_exists: subkeylist-record for key "
1668 : "[%s] is empty: Could be a deleted record in a "
1669 : "clustered (ctdb) environment?\n",
1670 : path));
1671 0 : goto done;
1672 : }
1673 :
1674 551910 : len = tdb_unpack(value.dptr, value.dsize, "d", &num_items);
1675 551910 : if (len == (int32_t)-1) {
1676 0 : DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key "
1677 : "[%s] is invalid: Could not parse initial 4-byte "
1678 : "counter. record data length is %u.\n",
1679 : path, (unsigned int)value.dsize));
1680 0 : goto done;
1681 : }
1682 :
1683 : /*
1684 : * Note: the tdb_unpack check above implies that len <= value.dsize
1685 : */
1686 551910 : buflen = value.dsize - len;
1687 551910 : buf = (const char *)value.dptr + len;
1688 :
1689 2415976 : for (i = 0; i < num_items; i++) {
1690 1864066 : if (buflen == 0) {
1691 0 : break;
1692 : }
1693 1864066 : len = strnlen(buf, buflen) + 1;
1694 1864066 : if (buflen < len) {
1695 0 : DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record "
1696 : "for key [%s] is corrupt: %u items expected, "
1697 : "item number %u is not zero terminated.\n",
1698 : path, num_items, i+1));
1699 0 : goto done;
1700 : }
1701 :
1702 1864066 : buf += len;
1703 1864066 : buflen -= len;
1704 : }
1705 :
1706 551910 : if (buflen > 0) {
1707 0 : DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key "
1708 : "[%s] is corrupt: %u items expected and found, but "
1709 : "the record contains additional %u bytes\n",
1710 : path, num_items, buflen));
1711 0 : goto done;
1712 : }
1713 :
1714 551910 : if (i < num_items) {
1715 0 : DEBUG(1, ("regdb_key_exists: ERROR: subkeylist-record for key "
1716 : "[%s] is corrupt: %u items expected, but only %u "
1717 : "items found.\n",
1718 : path, num_items, i+1));
1719 0 : goto done;
1720 : }
1721 :
1722 550727 : ret = true;
1723 :
1724 3475630 : done:
1725 3475630 : TALLOC_FREE(mem_ctx);
1726 3475630 : return ret;
1727 : }
1728 :
1729 :
1730 : /***********************************************************************
1731 : Retrieve an array of strings containing subkeys. Memory should be
1732 : released by the caller.
1733 : ***********************************************************************/
1734 :
1735 3328667 : static WERROR regdb_fetch_keys_internal(struct db_context *db, const char *key,
1736 : struct regsubkey_ctr *ctr)
1737 : {
1738 541 : WERROR werr;
1739 541 : uint32_t num_items;
1740 541 : uint8_t *buf;
1741 541 : uint32_t buflen, len;
1742 541 : uint32_t i;
1743 541 : fstring subkeyname;
1744 3328667 : TALLOC_CTX *frame = talloc_stackframe();
1745 541 : TDB_DATA value;
1746 541 : int seqnum[2], count;
1747 :
1748 3328667 : DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL"));
1749 :
1750 3328667 : if (!regdb_key_exists(db, key)) {
1751 2923657 : DEBUG(10, ("key [%s] not found\n", key));
1752 2923657 : werr = WERR_NOT_FOUND;
1753 2923657 : goto done;
1754 : }
1755 :
1756 405010 : werr = regsubkey_ctr_reinit(ctr);
1757 405010 : W_ERROR_NOT_OK_GOTO_DONE(werr);
1758 :
1759 405010 : count = 0;
1760 405010 : ZERO_STRUCT(value);
1761 405010 : seqnum[0] = dbwrap_get_seqnum(db);
1762 :
1763 429 : do {
1764 405010 : count++;
1765 405010 : TALLOC_FREE(value.dptr);
1766 405010 : value = regdb_fetch_key_internal(db, frame, key);
1767 405010 : seqnum[count % 2] = dbwrap_get_seqnum(db);
1768 :
1769 405010 : } while (seqnum[0] != seqnum[1]);
1770 :
1771 405010 : if (count > 1) {
1772 0 : DEBUG(5, ("regdb_fetch_keys_internal: it took %d attempts to "
1773 : "fetch key '%s' with constant seqnum\n",
1774 : count, key));
1775 : }
1776 :
1777 405010 : werr = regsubkey_ctr_set_seqnum(ctr, seqnum[0]);
1778 405010 : if (!W_ERROR_IS_OK(werr)) {
1779 0 : goto done;
1780 : }
1781 :
1782 405010 : if (value.dsize == 0 || value.dptr == NULL) {
1783 0 : DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n",
1784 : key));
1785 0 : goto done;
1786 : }
1787 :
1788 405010 : buf = value.dptr;
1789 405010 : buflen = value.dsize;
1790 405010 : len = tdb_unpack( buf, buflen, "d", &num_items);
1791 405010 : if (len == (uint32_t)-1) {
1792 0 : werr = WERR_NOT_FOUND;
1793 0 : goto done;
1794 : }
1795 :
1796 1840394 : for (i=0; i<num_items; i++) {
1797 440 : int this_len;
1798 :
1799 1435384 : this_len = tdb_unpack(buf+len, buflen-len, "f", subkeyname);
1800 1435384 : if (this_len == -1) {
1801 0 : DBG_WARNING("Invalid registry data, "
1802 : "tdb_unpack failed\n");
1803 0 : werr = WERR_INTERNAL_DB_CORRUPTION;
1804 0 : goto done;
1805 : }
1806 1435384 : len += this_len;
1807 1435384 : if (len < this_len) {
1808 0 : DBG_WARNING("Invalid registry data, "
1809 : "integer overflow\n");
1810 0 : werr = WERR_INTERNAL_DB_CORRUPTION;
1811 0 : goto done;
1812 : }
1813 :
1814 1435384 : werr = regsubkey_ctr_addkey(ctr, subkeyname);
1815 1435384 : if (!W_ERROR_IS_OK(werr)) {
1816 0 : DEBUG(5, ("regdb_fetch_keys: regsubkey_ctr_addkey "
1817 : "failed: %s\n", win_errstr(werr)));
1818 0 : num_items = 0;
1819 0 : goto done;
1820 : }
1821 : }
1822 :
1823 405010 : DEBUG(11,("regdb_fetch_keys: Exit [%d] items\n", num_items));
1824 :
1825 3328667 : done:
1826 3328667 : TALLOC_FREE(frame);
1827 3328667 : return werr;
1828 : }
1829 :
1830 3318960 : static int regdb_fetch_keys(const char *key, struct regsubkey_ctr *ctr)
1831 : {
1832 234 : WERROR werr;
1833 :
1834 3318960 : werr = regdb_fetch_keys_internal(regdb, key, ctr);
1835 3318960 : if (!W_ERROR_IS_OK(werr)) {
1836 2920974 : return -1;
1837 : }
1838 :
1839 397945 : return regsubkey_ctr_numkeys(ctr);
1840 : }
1841 :
1842 : /****************************************************************************
1843 : Unpack a list of registry values frem the TDB
1844 : ***************************************************************************/
1845 :
1846 50410 : static int regdb_unpack_values(struct regval_ctr *values,
1847 : uint8_t *buf,
1848 : size_t buflen)
1849 : {
1850 74 : int this_len;
1851 50410 : size_t len = 0;
1852 74 : uint32_t type;
1853 74 : fstring valuename;
1854 74 : uint32_t size;
1855 74 : uint8_t *data_p;
1856 50410 : uint32_t num_values = 0;
1857 74 : uint32_t i;
1858 :
1859 : /* loop and unpack the rest of the registry values */
1860 :
1861 50410 : this_len = tdb_unpack(buf, buflen, "d", &num_values);
1862 50410 : if (this_len == -1) {
1863 0 : DBG_WARNING("Invalid registry data, "
1864 : "tdb_unpack failed\n");
1865 0 : return -1;
1866 : }
1867 50410 : len = this_len;
1868 :
1869 588760 : for ( i=0; i<num_values; i++ ) {
1870 : /* unpack the next regval */
1871 :
1872 538350 : type = REG_NONE;
1873 538350 : size = 0;
1874 538350 : data_p = NULL;
1875 538350 : valuename[0] = '\0';
1876 538350 : this_len = tdb_unpack(buf+len, buflen-len, "fdB",
1877 : valuename,
1878 : &type,
1879 : &size,
1880 : &data_p);
1881 538350 : if (this_len == -1) {
1882 0 : DBG_WARNING("Invalid registry data, "
1883 : "tdb_unpack failed\n");
1884 0 : return -1;
1885 : }
1886 538350 : len += this_len;
1887 538350 : if (len < (size_t)this_len) {
1888 0 : DBG_WARNING("Invalid registry data, "
1889 : "integer overflow\n");
1890 0 : return -1;
1891 : }
1892 :
1893 538350 : regval_ctr_addvalue(values, valuename, type,
1894 : (uint8_t *)data_p, size);
1895 538350 : SAFE_FREE(data_p); /* 'B' option to tdb_unpack does a malloc() */
1896 :
1897 538350 : DEBUG(10, ("regdb_unpack_values: value[%d]: name[%s] len[%d]\n",
1898 : i, valuename, size));
1899 : }
1900 :
1901 50410 : return len;
1902 : }
1903 :
1904 : /****************************************************************************
1905 : Pack all values in all printer keys
1906 : ***************************************************************************/
1907 :
1908 33518 : static int regdb_pack_values(struct regval_ctr *values, uint8_t *buf, int buflen)
1909 : {
1910 33518 : int len = 0;
1911 56 : int i;
1912 56 : struct regval_blob *val;
1913 56 : int num_values;
1914 :
1915 33518 : if ( !values )
1916 0 : return 0;
1917 :
1918 33518 : num_values = regval_ctr_numvals( values );
1919 :
1920 : /* pack the number of values first */
1921 :
1922 33518 : len += tdb_pack( buf+len, buflen-len, "d", num_values );
1923 :
1924 : /* loop over all values */
1925 :
1926 312608 : for ( i=0; i<num_values; i++ ) {
1927 279090 : val = regval_ctr_specific_value( values, i );
1928 279090 : len += tdb_pack(buf+len, buflen-len, "fdB",
1929 : regval_name(val),
1930 : regval_type(val),
1931 : regval_size(val),
1932 : regval_data_p(val) );
1933 : }
1934 :
1935 33462 : return len;
1936 : }
1937 :
1938 : /***********************************************************************
1939 : Retrieve an array of strings containing subkeys. Memory should be
1940 : released by the caller.
1941 : ***********************************************************************/
1942 :
1943 58292 : static int regdb_fetch_values_internal(struct db_context *db, const char* key,
1944 : struct regval_ctr *values)
1945 : {
1946 58292 : char *keystr = NULL;
1947 58292 : TALLOC_CTX *ctx = talloc_stackframe();
1948 58292 : int ret = 0;
1949 86 : TDB_DATA value;
1950 86 : WERROR werr;
1951 86 : int seqnum[2], count;
1952 :
1953 58292 : DEBUG(10,("regdb_fetch_values: Looking for values of key [%s]\n", key));
1954 :
1955 58292 : if (!regdb_key_exists(db, key)) {
1956 0 : DEBUG(10, ("regb_fetch_values: key [%s] does not exist\n",
1957 : key));
1958 0 : ret = -1;
1959 0 : goto done;
1960 : }
1961 :
1962 58292 : keystr = talloc_asprintf(ctx, "%s\\%s", REG_VALUE_PREFIX, key);
1963 58292 : if (!keystr) {
1964 0 : goto done;
1965 : }
1966 :
1967 58292 : ZERO_STRUCT(value);
1968 58292 : count = 0;
1969 58292 : seqnum[0] = dbwrap_get_seqnum(db);
1970 :
1971 86 : do {
1972 58292 : count++;
1973 58292 : TALLOC_FREE(value.dptr);
1974 58292 : value = regdb_fetch_key_internal(db, ctx, keystr);
1975 58292 : seqnum[count % 2] = dbwrap_get_seqnum(db);
1976 58292 : } while (seqnum[0] != seqnum[1]);
1977 :
1978 58292 : if (count > 1) {
1979 0 : DEBUG(5, ("regdb_fetch_values_internal: it took %d attempts "
1980 : "to fetch key '%s' with constant seqnum\n",
1981 : count, key));
1982 : }
1983 :
1984 58292 : werr = regval_ctr_set_seqnum(values, seqnum[0]);
1985 58292 : if (!W_ERROR_IS_OK(werr)) {
1986 0 : goto done;
1987 : }
1988 :
1989 58292 : if (!value.dptr) {
1990 : /* all keys have zero values by default */
1991 7882 : goto done;
1992 : }
1993 :
1994 50410 : ret = regdb_unpack_values(values, value.dptr, value.dsize);
1995 50410 : if (ret == -1) {
1996 0 : DBG_WARNING("regdb_unpack_values failed\n");
1997 : }
1998 :
1999 50410 : ret = regval_ctr_numvals(values);
2000 :
2001 58292 : done:
2002 58292 : TALLOC_FREE(ctx);
2003 58292 : return ret;
2004 : }
2005 :
2006 52840 : static int regdb_fetch_values(const char* key, struct regval_ctr *values)
2007 : {
2008 52840 : return regdb_fetch_values_internal(regdb, key, values);
2009 : }
2010 :
2011 19644 : static NTSTATUS regdb_store_values_internal(struct db_context *db,
2012 : const char *key,
2013 : struct regval_ctr *values)
2014 : {
2015 28 : TDB_DATA old_data, data;
2016 19644 : char *keystr = NULL;
2017 19644 : TALLOC_CTX *ctx = talloc_stackframe();
2018 28 : int len;
2019 28 : NTSTATUS status;
2020 28 : WERROR werr;
2021 :
2022 19644 : DEBUG(10,("regdb_store_values: Looking for values of key [%s]\n", key));
2023 :
2024 19644 : if (!regdb_key_exists(db, key)) {
2025 0 : status = NT_STATUS_NOT_FOUND;
2026 0 : goto done;
2027 : }
2028 :
2029 19644 : if (regval_ctr_numvals(values) == 0) {
2030 2885 : werr = regdb_delete_values(db, key);
2031 2885 : if (!W_ERROR_IS_OK(werr)) {
2032 0 : status = werror_to_ntstatus(werr);
2033 0 : goto done;
2034 : }
2035 :
2036 : /*
2037 : * update the seqnum in the cache to prevent the next read
2038 : * from going to disk
2039 : */
2040 2885 : werr = regval_ctr_set_seqnum(values, dbwrap_get_seqnum(db));
2041 2885 : status = werror_to_ntstatus(werr);
2042 2885 : goto done;
2043 : }
2044 :
2045 16759 : ZERO_STRUCT(data);
2046 :
2047 16759 : len = regdb_pack_values(values, data.dptr, data.dsize);
2048 16759 : 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 : }
2053 :
2054 16759 : data.dptr = talloc_array(ctx, uint8_t, len);
2055 16759 : data.dsize = len;
2056 :
2057 16759 : len = regdb_pack_values(values, data.dptr, data.dsize);
2058 :
2059 16759 : SMB_ASSERT( len == data.dsize );
2060 :
2061 16759 : keystr = talloc_asprintf(ctx, "%s\\%s", REG_VALUE_PREFIX, key );
2062 16759 : if (!keystr) {
2063 0 : status = NT_STATUS_NO_MEMORY;
2064 0 : goto done;
2065 : }
2066 16759 : keystr = normalize_reg_path(ctx, keystr);
2067 16759 : if (!keystr) {
2068 0 : status = NT_STATUS_NO_MEMORY;
2069 0 : goto done;
2070 : }
2071 :
2072 16759 : status = dbwrap_fetch_bystring(db, ctx, keystr, &old_data);
2073 :
2074 16759 : if (NT_STATUS_IS_OK(status)
2075 11895 : && (old_data.dptr != NULL)
2076 11895 : && (old_data.dsize == data.dsize)
2077 3790 : && (memcmp(old_data.dptr, data.dptr, data.dsize) == 0))
2078 : {
2079 0 : status = NT_STATUS_OK;
2080 0 : goto done;
2081 : }
2082 :
2083 16759 : status = dbwrap_trans_store_bystring(db, keystr, data, TDB_REPLACE);
2084 16759 : 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 : }
2088 :
2089 : /*
2090 : * update the seqnum in the cache to prevent the next read
2091 : * from going to disk
2092 : */
2093 16759 : werr = regval_ctr_set_seqnum(values, dbwrap_get_seqnum(db));
2094 16759 : status = werror_to_ntstatus(werr);
2095 :
2096 19644 : done:
2097 19644 : TALLOC_FREE(ctx);
2098 19644 : return status;
2099 : }
2100 :
2101 : struct regdb_store_values_ctx {
2102 : const char *key;
2103 : struct regval_ctr *values;
2104 : };
2105 :
2106 19640 : static NTSTATUS regdb_store_values_action(struct db_context *db,
2107 : void *private_data)
2108 : {
2109 24 : NTSTATUS status;
2110 19640 : struct regdb_store_values_ctx *ctx =
2111 : (struct regdb_store_values_ctx *)private_data;
2112 :
2113 19640 : status = regdb_store_values_internal(db, ctx->key, ctx->values);
2114 :
2115 19640 : return status;
2116 : }
2117 :
2118 19640 : static bool regdb_store_values(const char *key, struct regval_ctr *values)
2119 : {
2120 24 : WERROR werr;
2121 24 : struct regdb_store_values_ctx ctx;
2122 :
2123 19640 : ctx.key = key;
2124 19640 : ctx.values = values;
2125 :
2126 19640 : werr = regdb_trans_do(regdb, regdb_store_values_action, &ctx);
2127 :
2128 19640 : return W_ERROR_IS_OK(werr);
2129 : }
2130 :
2131 20955 : static WERROR regdb_get_secdesc(TALLOC_CTX *mem_ctx, const char *key,
2132 : struct security_descriptor **psecdesc)
2133 : {
2134 69 : char *tdbkey;
2135 69 : TDB_DATA data;
2136 69 : NTSTATUS status;
2137 20955 : TALLOC_CTX *tmp_ctx = talloc_stackframe();
2138 20955 : WERROR err = WERR_OK;
2139 :
2140 20955 : DEBUG(10, ("regdb_get_secdesc: Getting secdesc of key [%s]\n", key));
2141 :
2142 20955 : if (!regdb_key_exists(regdb, key)) {
2143 0 : err = WERR_FILE_NOT_FOUND;
2144 0 : goto done;
2145 : }
2146 :
2147 20955 : tdbkey = talloc_asprintf(tmp_ctx, "%s\\%s", REG_SECDESC_PREFIX, key);
2148 20955 : if (tdbkey == NULL) {
2149 0 : err = WERR_NOT_ENOUGH_MEMORY;
2150 0 : goto done;
2151 : }
2152 :
2153 20955 : tdbkey = normalize_reg_path(tmp_ctx, tdbkey);
2154 20955 : if (tdbkey == NULL) {
2155 0 : err = WERR_NOT_ENOUGH_MEMORY;
2156 0 : goto done;
2157 : }
2158 :
2159 20955 : status = dbwrap_fetch_bystring(regdb, tmp_ctx, tdbkey, &data);
2160 20955 : if (!NT_STATUS_IS_OK(status)) {
2161 20955 : err = WERR_FILE_NOT_FOUND;
2162 20955 : goto done;
2163 : }
2164 :
2165 0 : status = unmarshall_sec_desc(mem_ctx, (uint8_t *)data.dptr, data.dsize,
2166 : 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 : }
2173 :
2174 20955 : done:
2175 20955 : TALLOC_FREE(tmp_ctx);
2176 20955 : return err;
2177 : }
2178 :
2179 : struct regdb_set_secdesc_ctx {
2180 : const char *key;
2181 : struct security_descriptor *secdesc;
2182 : };
2183 :
2184 0 : static NTSTATUS regdb_set_secdesc_action(struct db_context *db,
2185 : void *private_data)
2186 : {
2187 0 : char *tdbkey;
2188 0 : NTSTATUS status;
2189 0 : TDB_DATA tdbdata;
2190 0 : struct regdb_set_secdesc_ctx *ctx =
2191 : (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 : }
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 : }
2205 :
2206 0 : if (ctx->secdesc == NULL) {
2207 : /* assuming a delete */
2208 0 : status = dbwrap_delete_bystring(db, tdbkey);
2209 0 : goto done;
2210 : }
2211 :
2212 0 : status = marshall_sec_desc(frame, ctx->secdesc, &tdbdata.dptr,
2213 : &tdbdata.dsize);
2214 0 : if (!NT_STATUS_IS_OK(status)) {
2215 0 : goto done;
2216 : }
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 : }
2224 :
2225 0 : static WERROR regdb_set_secdesc(const char *key,
2226 : struct security_descriptor *secdesc)
2227 : {
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 : }
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 : }
2244 :
2245 311764 : static bool regdb_subkeys_need_update(struct regsubkey_ctr *subkeys)
2246 : {
2247 311764 : return (regdb_get_seqnum() != regsubkey_ctr_get_seqnum(subkeys));
2248 : }
2249 :
2250 258484 : static bool regdb_values_need_update(struct regval_ctr *values)
2251 : {
2252 258484 : return (regdb_get_seqnum() != regval_ctr_get_seqnum(values));
2253 : }
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 : };
|