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