diff options
Diffstat (limited to 'source/registry/reg_backend_db.c')
-rw-r--r-- | source/registry/reg_backend_db.c | 362 |
1 files changed, 76 insertions, 286 deletions
diff --git a/source/registry/reg_backend_db.c b/source/registry/reg_backend_db.c index 6f4c614b9a..52a01507c0 100644 --- a/source/registry/reg_backend_db.c +++ b/source/registry/reg_backend_db.c @@ -27,9 +27,6 @@ static struct db_context *regdb = NULL; static int regdb_refcount; -static bool regdb_key_exists(const char *key); -static bool regdb_key_is_base_key(const char *key); - /* List the deepest path into the registry. All part components will be created.*/ /* If you want to have a part of the path controlled by the tdb and part by @@ -49,14 +46,6 @@ static const char *builtin_registry_paths[] = { KEY_SMBCONF, KEY_PERFLIB, KEY_PERFLIB_009, - KEY_GROUP_POLICY, - KEY_SAMBA_GROUP_POLICY, - KEY_GP_MACHINE_POLICY, - KEY_GP_MACHINE_WIN_POLICY, - KEY_HKCU, - KEY_GP_USER_POLICY, - KEY_GP_USER_WIN_POLICY, - KEY_WINLOGON_GPEXT_PATH, "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors", KEY_PROD_OPTIONS, "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\DefaultUserConfiguration", @@ -202,10 +191,6 @@ WERROR init_registry_key(const char *add_path) { WERROR werr; - if (regdb_key_exists(add_path)) { - return WERR_OK; - } - if (regdb->transaction_start(regdb) != 0) { DEBUG(0, ("init_registry_key: transaction_start failed\n")); return WERR_REG_IO_FAILURE; @@ -238,45 +223,12 @@ fail: WERROR init_registry_data(void) { WERROR werr; - TALLOC_CTX *frame = talloc_stackframe(); + TALLOC_CTX *frame = NULL; REGVAL_CTR *values; int i; UNISTR2 data; /* - * First, check for the existence of the needed keys and values. - * If all do already exist, we can save the writes. - */ - for (i=0; builtin_registry_paths[i] != NULL; i++) { - if (!regdb_key_exists(builtin_registry_paths[i])) { - goto do_init; - } - } - - for (i=0; builtin_registry_values[i].path != NULL; i++) { - values = TALLOC_ZERO_P(frame, REGVAL_CTR); - if (values == NULL) { - werr = WERR_NOMEM; - goto done; - } - - regdb_fetch_values(builtin_registry_values[i].path, values); - if (!regval_ctr_key_exists(values, - builtin_registry_values[i].valuename)) - { - TALLOC_FREE(values); - goto do_init; - } - - TALLOC_FREE(values); - } - - werr = WERR_OK; - goto done; - -do_init: - - /* * There are potentially quite a few store operations which are all * indiviually wrapped in tdb transactions. Wrapping them in a single * transaction gives just a single transaction_commit() to actually do @@ -287,16 +239,12 @@ do_init: if (regdb->transaction_start(regdb) != 0) { DEBUG(0, ("init_registry_data: tdb_transaction_start " "failed\n")); - werr = WERR_REG_IO_FAILURE; - goto done; + return WERR_REG_IO_FAILURE; } /* loop over all of the predefined paths and add each component */ for (i=0; builtin_registry_paths[i] != NULL; i++) { - if (regdb_key_exists(builtin_registry_paths[i])) { - continue; - } werr = init_registry_key_internal(builtin_registry_paths[i]); if (!W_ERROR_IS_OK(werr)) { goto fail; @@ -305,6 +253,8 @@ do_init: /* loop over all of the predefined values and add each component */ + frame = talloc_stackframe(); + for (i=0; builtin_registry_values[i].path != NULL; i++) { values = TALLOC_ZERO_P(frame, REGVAL_CTR); @@ -352,24 +302,25 @@ do_init: TALLOC_FREE(values); } + TALLOC_FREE(frame); + if (regdb->transaction_commit(regdb) != 0) { DEBUG(0, ("init_registry_data: Could not commit " "transaction\n")); - werr = WERR_REG_IO_FAILURE; - } else { - werr = WERR_OK; + return WERR_REG_IO_FAILURE; } - goto done; + return WERR_OK; + + fail: + + TALLOC_FREE(frame); -fail: if (regdb->transaction_cancel(regdb) != 0) { smb_panic("init_registry_data: tdb_transaction_cancel " "failed\n"); } -done: - TALLOC_FREE(frame); return werr; } @@ -390,14 +341,14 @@ WERROR regdb_init(void) return WERR_OK; } - regdb = db_open(NULL, state_path("registry.tdb"), 0, + regdb = db_open_trans(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR, 0600); if (!regdb) { - regdb = db_open(NULL, state_path("registry.tdb"), 0, + regdb = db_open_trans(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR|O_CREAT, 0600); if (!regdb) { werr = ntstatus_to_werror(map_nt_error_from_unix(errno)); - DEBUG(1,("regdb_init: Failed to open registry %s (%s)\n", + DEBUG(0,("regdb_init: Failed to open registry %s (%s)\n", state_path("registry.tdb"), strerror(errno) )); return werr; } @@ -416,7 +367,7 @@ WERROR regdb_init(void) vers_id, REGVER_V1)); status = dbwrap_trans_store_int32(regdb, vstring, REGVER_V1); if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("regdb_init: error storing %s = %d: %s\n", + DEBUG(0, ("regdb_init: error storing %s = %d: %s\n", vstring, REGVER_V1, nt_errstr(status))); return ntstatus_to_werror(status); } else { @@ -444,7 +395,7 @@ WERROR regdb_open( void ) become_root(); - regdb = db_open(NULL, state_path("registry.tdb"), 0, + regdb = db_open_trans(NULL, state_path("registry.tdb"), 0, REG_TDB_FLAGS, O_RDWR, 0600); if ( !regdb ) { result = ntstatus_to_werror( map_nt_error_from_unix( errno ) ); @@ -583,10 +534,6 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr) TALLOC_CTX *ctx = talloc_stackframe(); NTSTATUS status; - if (!regdb_key_is_base_key(key) && !regdb_key_exists(key)) { - goto fail; - } - /* * fetch a list of the old subkeys so we can determine if anything has * changed @@ -636,28 +583,15 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr) regdb_fetch_keys(key, old_subkeys); - /* - * Make the store operation as safe as possible without transactions: - * - * (1) For each subkey removed from ctr compared with old_subkeys: - * - * (a) First delete the value db entry. - * - * (b) Next delete the secdesc db record. - * - * (c) Then delete the subkey list entry. - * - * (2) Now write the list of subkeys of the parent key, - * deleting removed entries and adding new ones. - * - * (3) Finally create the subkey list entries for the added keys. - * - * This way if we crash half-way in between deleting the subkeys - * and storing the parent's list of subkeys, no old data can pop up - * out of the blue when re-adding keys later on. - */ + /* store the subkey list for the parent */ - /* (1) delete removed keys' lists (values/secdesc/subkeys) */ + if (!regdb_store_keys_internal(key, ctr) ) { + DEBUG(0,("regdb_store_keys: Failed to store new subkey list " + "for parent [%s]\n", key)); + goto cancel; + } + + /* now delete removed keys */ num_subkeys = regsubkey_ctr_numkeys(old_subkeys); for (i=0; i<num_subkeys; i++) { @@ -671,12 +605,7 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr) continue; } - /* (a) Delete the value list for this key */ - - path = talloc_asprintf(ctx, "%s/%s/%s", - REG_VALUE_PREFIX, - key, - oldkeyname ); + path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname); if (!path) { goto cancel; } @@ -684,14 +613,15 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr) if (!path) { goto cancel; } - /* Ignore errors here, we might have no values around */ - dbwrap_delete_bystring(regdb, path); - TALLOC_FREE(path); - - /* (b) Delete the secdesc for this key */ + status = dbwrap_delete_bystring(regdb, path); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Deleting %s failed\n", path)); + goto cancel; + } + TALLOC_FREE(path); path = talloc_asprintf(ctx, "%s/%s/%s", - REG_SECDESC_PREFIX, + REG_VALUE_PREFIX, key, oldkeyname ); if (!path) { @@ -701,50 +631,17 @@ bool regdb_store_keys(const char *key, REGSUBKEY_CTR *ctr) if (!path) { goto cancel; } - status = dbwrap_delete_bystring(regdb, path); - /* Don't fail if there are no values around. */ - if (!NT_STATUS_IS_OK(status) && - !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) - { - DEBUG(1, ("Deleting %s failed: %s\n", path, - nt_errstr(status))); - goto cancel; - } - TALLOC_FREE(path); - - /* (c) Delete the list of subkeys of this key */ - path = talloc_asprintf(ctx, "%s/%s", key, oldkeyname); - if (!path) { - goto cancel; - } - path = normalize_reg_path(ctx, path); - if (!path) { - goto cancel; - } - status = dbwrap_delete_bystring(regdb, path); - /* Don't fail if the subkey record was not found. */ - if (!NT_STATUS_IS_OK(status) && - !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) - { - DEBUG(1, ("Deleting %s failed: %s\n", path, - nt_errstr(status))); - goto cancel; - } + /* + * Ignore errors here, we might have no values around + */ + dbwrap_delete_bystring(regdb, path); TALLOC_FREE(path); } TALLOC_FREE(old_subkeys); - /* (2) store the subkey list for the parent */ - - if (!regdb_store_keys_internal(key, ctr) ) { - DEBUG(0,("regdb_store_keys: Failed to store new subkey list " - "for parent [%s]\n", key)); - goto cancel; - } - - /* (3) now create records for any subkeys that don't already exist */ + /* now create records for any subkeys that don't already exist */ num_subkeys = regsubkey_ctr_numkeys(ctr); @@ -808,118 +705,6 @@ fail: } -static TDB_DATA regdb_fetch_key_internal(TALLOC_CTX *mem_ctx, const char *key) -{ - char *path = NULL; - TDB_DATA data; - - path = normalize_reg_path(mem_ctx, key); - if (!path) { - return make_tdb_data(NULL, 0); - } - - data = dbwrap_fetch_bystring(regdb, mem_ctx, path); - - TALLOC_FREE(path); - return data; -} - - -/** - * check whether a given key name represents a base key, - * i.e one without a subkey separator ('/' or '\'). - */ -static bool regdb_key_is_base_key(const char *key) -{ - TALLOC_CTX *mem_ctx = talloc_stackframe(); - bool ret = false; - char *path; - - if (key == NULL) { - goto done; - } - - path = normalize_reg_path(mem_ctx, key); - if (path == NULL) { - DEBUG(0, ("out of memory! (talloc failed)\n")); - goto done; - } - - if (*path == '\0') { - goto done; - } - - ret = (strrchr(path, '/') == NULL); - -done: - TALLOC_FREE(mem_ctx); - return ret; -} - - -/** - * Check for the existence of a key. - * - * Existence of a key is authoritatively defined by its - * existence in the list of subkeys of its parent key. - * The exeption of this are keys without a parent key, - * i.e. the "base" keys (HKLM, HKCU, ...). - */ -static bool regdb_key_exists(const char *key) -{ - TALLOC_CTX *mem_ctx = talloc_stackframe(); - TDB_DATA value; - bool ret = false; - char *path, *p; - - if (key == NULL) { - goto done; - } - - path = normalize_reg_path(mem_ctx, key); - if (path == NULL) { - DEBUG(0, ("out of memory! (talloc failed)\n")); - goto done; - } - - if (*path == '\0') { - goto done; - } - - p = strrchr(path, '/'); - if (p == NULL) { - /* this is a base key */ - value = regdb_fetch_key_internal(mem_ctx, path); - ret = (value.dptr != NULL); - } else { - /* get the list of subkeys of the parent key */ - uint32 num_items, len, i; - fstring subkeyname; - - *p = '\0'; - p++; - value = regdb_fetch_key_internal(mem_ctx, path); - if (value.dptr == NULL) { - goto done; - } - - len = tdb_unpack(value.dptr, value.dsize, "d", &num_items); - for (i = 0; i < num_items; i++) { - len += tdb_unpack(value.dptr +len, value.dsize -len, - "f", &subkeyname); - if (strequal(subkeyname, p)) { - ret = true; - goto done; - } - } - } - -done: - TALLOC_FREE(mem_ctx); - return ret; -} - - /*********************************************************************** Retrieve an array of strings containing subkeys. Memory should be released by the caller. @@ -928,34 +713,46 @@ done: int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr) { WERROR werr; + char *path = NULL; uint32 num_items; uint8 *buf; uint32 buflen, len; int i; fstring subkeyname; int ret = -1; + int dbret = -1; TALLOC_CTX *frame = talloc_stackframe(); TDB_DATA value; DEBUG(11,("regdb_fetch_keys: Enter key => [%s]\n", key ? key : "NULL")); - if (!regdb_key_exists(key)) { - goto done; + path = talloc_strdup(frame, key); + if (!path) { + goto fail; } - ctr->seqnum = regdb_get_seqnum(); + /* convert to key format */ + path = talloc_string_sub(frame, path, "\\", "/"); + if (!path) { + goto fail; + } + strupper_m(path); - value = regdb_fetch_key_internal(frame, key); + ctr->seqnum = regdb_get_seqnum(); - if (value.dptr == NULL) { - DEBUG(10, ("regdb_fetch_keys: no subkeys found for key [%s]\n", - key)); - ret = 0; - goto done; + dbret = regdb->fetch(regdb, frame, string_term_tdb_data(path), &value); + if (dbret != 0) { + goto fail; } buf = value.dptr; buflen = value.dsize; + + if ( !buf ) { + DEBUG(5,("regdb_fetch_keys: tdb lookup failed to locate key [%s]\n", key)); + goto fail; + } + len = tdb_unpack( buf, buflen, "d", &num_items); for (i=0; i<num_items; i++) { @@ -964,14 +761,14 @@ int regdb_fetch_keys(const char *key, REGSUBKEY_CTR *ctr) if (!W_ERROR_IS_OK(werr)) { DEBUG(5, ("regdb_fetch_keys: regsubkey_ctr_addkey " "failed: %s\n", dos_errstr(werr))); - goto done; + goto fail; } } DEBUG(11,("regdb_fetch_keys: Exit [%d] items\n", num_items)); ret = num_items; -done: + fail: TALLOC_FREE(frame); return ret; } @@ -1065,22 +862,26 @@ int regdb_fetch_values( const char* key, REGVAL_CTR *values ) char *keystr = NULL; TALLOC_CTX *ctx = talloc_stackframe(); int ret = 0; + int dbret = -1; TDB_DATA value; DEBUG(10,("regdb_fetch_values: Looking for value of key [%s] \n", key)); - if (!regdb_key_exists(key)) { - goto done; - } - keystr = talloc_asprintf(ctx, "%s/%s", REG_VALUE_PREFIX, key); if (!keystr) { + return 0; + } + keystr = normalize_reg_path(ctx, keystr); + if (!keystr) { goto done; } values->seqnum = regdb_get_seqnum(); - value = regdb_fetch_key_internal(ctx, keystr); + dbret = regdb->fetch(regdb, ctx, string_term_tdb_data(keystr), &value); + if (dbret != 0) { + goto done; + } if (!value.dptr) { /* all keys have zero values by default */ @@ -1106,10 +907,6 @@ bool regdb_store_values( const char *key, REGVAL_CTR *values ) DEBUG(10,("regdb_store_values: Looking for value of key [%s] \n", key)); - if (!regdb_key_exists(key)) { - goto done; - } - ZERO_STRUCT(data); len = regdb_pack_values(values, data.dptr, data.dsize); @@ -1144,7 +941,8 @@ bool regdb_store_values( const char *key, REGVAL_CTR *values ) goto done; } - status = dbwrap_trans_store_bystring(regdb, keystr, data, TDB_REPLACE); + status = dbwrap_trans_store(regdb, string_term_tdb_data(keystr), data, + TDB_REPLACE); result = NT_STATUS_IS_OK(status); @@ -1164,11 +962,6 @@ static WERROR regdb_get_secdesc(TALLOC_CTX *mem_ctx, const char *key, DEBUG(10, ("regdb_get_secdesc: Getting secdesc of key [%s]\n", key)); - if (!regdb_key_exists(key)) { - err = WERR_BADFILE; - goto done; - } - tdbkey = talloc_asprintf(tmp_ctx, "%s/%s", REG_SECDESC_PREFIX, key); if (tdbkey == NULL) { err = WERR_NOMEM; @@ -1205,11 +998,6 @@ static WERROR regdb_set_secdesc(const char *key, WERROR err = WERR_NOMEM; TDB_DATA tdbdata; - if (!regdb_key_exists(key)) { - err = WERR_BADFILE; - goto done; - } - tdbkey = talloc_asprintf(mem_ctx, "%s/%s", REG_SECDESC_PREFIX, key); if (tdbkey == NULL) { goto done; @@ -1218,7 +1006,8 @@ static WERROR regdb_set_secdesc(const char *key, if (secdesc == NULL) { /* assuming a delete */ - status = dbwrap_trans_delete_bystring(regdb, tdbkey); + status = dbwrap_trans_delete(regdb, + string_term_tdb_data(tdbkey)); if (NT_STATUS_IS_OK(status)) { err = WERR_OK; } else { @@ -1234,7 +1023,8 @@ static WERROR regdb_set_secdesc(const char *key, goto done; } - status = dbwrap_trans_store_bystring(regdb, tdbkey, tdbdata, 0); + status = dbwrap_trans_store(regdb, string_term_tdb_data(tdbkey), + tdbdata, 0); if (!NT_STATUS_IS_OK(status)) { err = ntstatus_to_werror(status); goto done; |