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