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