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