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