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