LCOV - code coverage report
Current view: top level - source3/registry - reg_backend_db.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 714 1037 68.9 %
Date: 2024-02-28 12:06:22 Functions: 53 59 89.8 %

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

Generated by: LCOV version 1.14