[SCM] Samba Shared Repository - branch master updated

Michael Adam obnox at samba.org
Fri Jun 25 09:49:39 MDT 2010


The branch, master has been updated
       via  36b95fe... s3:net [rpc] registry: be as user-friendly as possible wrt to the normalization change
       via  8e4f812... s3:registry: improve logic of upgrade code in regdb_init()
       via  3703b79... s3:registry: fix some debug messages in regdb_ini()
       via  15bacaf... s3-registry: Convert registry key delimiter from slash to backslash.
       via  f540833... s3-registry: Added a db upgrade function to normalize the key delimiter.
      from  175d947... s3: In make_server_info_info3, check the result of copy_netr_SamInfo3

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 36b95fee152d348926fad1bcdc9f05312bb2aad5
Author: Michael Adam <obnox at samba.org>
Date:   Fri Jun 25 17:26:34 2010 +0200

    s3:net [rpc] registry: be as user-friendly as possible wrt to the normalization change
    
    The registry has been changed to use '\' as a key delimiter instead of '/'.
    Originally, one could mix both characters in the specification of registry
    key for net [rpc] registry. Now this can not work any more, since '/' is
    generally treated as a valid character of a key name.
    
    Now, to be as user-friendly as possible, the net [rpc] registry code has
    been changed to still support '/' as a key name delimiter if no '\' character
    is found in the given registry path string. In that case, all '/' characters
    are converted to '\' characters before proceeding. If on the other hand,
    a '\' character is found in the path string, then no conversion is assumed,
    and it is hence assumed that the path is already in the correct form and
    '/' characters are supposed to be part of the key names.

commit 8e4f8128234f0015c9d63bb18821487bb3e7b06e
Author: Michael Adam <obnox at samba.org>
Date:   Fri Jun 25 14:34:04 2010 +0200

    s3:registry: improve logic of upgrade code in regdb_init()
    
    Don't overwrite unknown versions (0 or > 2) of the registry.

commit 3703b79b11eecf3d8f2232b400bb8a2dd5b55876
Author: Michael Adam <obnox at samba.org>
Date:   Fri Jun 25 12:32:22 2010 +0200

    s3:registry: fix some debug messages in regdb_ini()

commit 15bacaf3c594ac24cf26b0329723e873a5cae43d
Author: Andreas Schneider <asn at samba.org>
Date:   Thu Jun 24 16:33:37 2010 +0200

    s3-registry: Convert registry key delimiter from slash to backslash.
    
    This is needed to support keynames containing a '/' like TCP/IP. Which
    is used in serveral standard paths.
    
    Signed-off-by: Michael Adam <obnox at samba.org>

commit f540833632ffe2c743e90ef9df1627e69b7a0c7b
Author: Andreas Schneider <asn at samba.org>
Date:   Thu Jun 24 15:26:04 2010 +0200

    s3-registry: Added a db upgrade function to normalize the key delimiter.
    
    This converts the key delimiter from a slash to a blackslash. We need to
    support keynames with a backslash.
    
    Signed-off-by: Michael Adam <obnox at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 source3/include/reg_db.h             |    1 +
 source3/lib/adt_tree.c               |   12 ++--
 source3/registry/reg_api.c           |   10 --
 source3/registry/reg_backend_db.c    |  163 +++++++++++++++++++++++++++++-----
 source3/registry/reg_cachehook.c     |    6 --
 source3/registry/reg_util_internal.c |   23 ++---
 source3/utils/net_registry_util.c    |   11 ++-
 7 files changed, 164 insertions(+), 62 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/reg_db.h b/source3/include/reg_db.h
index 5cafa0a..774093d 100644
--- a/source3/include/reg_db.h
+++ b/source3/include/reg_db.h
@@ -23,6 +23,7 @@
 #define REG_TDB_FLAGS   TDB_SEQNUM
 
 #define REGVER_V1       1       /* first db version with write support */
+#define REGVER_V2       2       /* version 2 with normalized keys */
 
 #define REG_VALUE_PREFIX    "SAMBA_REGVAL"
 #define REG_SECDESC_PREFIX  "SAMBA_SECDESC"
diff --git a/source3/lib/adt_tree.c b/source3/lib/adt_tree.c
index 7f4a39d..6d48161 100644
--- a/source3/lib/adt_tree.c
+++ b/source3/lib/adt_tree.c
@@ -46,7 +46,7 @@ static bool trim_tree_keypath( char *path, char **base, char **new_path )
 
 	*base = path;
 
-	p = strchr( path, '/' );
+	p = strchr( path, '\\' );
 
 	if ( p ) {
 		*p = '\0';
@@ -214,7 +214,7 @@ WERROR pathtree_add(struct sorted_tree *tree, const char *path, void *data_p)
 
 	DEBUG(8,("pathtree_add: Enter\n"));
 
-	if ( !path || *path != '/' ) {
+	if ( !path || *path != '\\' ) {
 		DEBUG(0,("pathtree_add: Attempt to add a node with a bad path [%s]\n",
 			path ? path : "NULL" ));
 		return WERR_INVALID_PARAM;
@@ -225,7 +225,7 @@ WERROR pathtree_add(struct sorted_tree *tree, const char *path, void *data_p)
 		return WERR_INVALID_PARAM;
 	}
 
-	/* move past the first '/' */
+	/* move past the first '\\' */
 
 	path++;	
 	path2 = SMB_STRDUP( path );
@@ -248,7 +248,7 @@ WERROR pathtree_add(struct sorted_tree *tree, const char *path, void *data_p)
 	do {
 		/* break off the remaining part of the path */
 
-		str = strchr( str, '/' );
+		str = strchr( str, '\\' );
 		if ( str )
 			*str = '\0';
 
@@ -269,7 +269,7 @@ WERROR pathtree_add(struct sorted_tree *tree, const char *path, void *data_p)
 
 		base = str;
 		if ( base ) {
-			*base = '/';
+			*base = '\\';
 			base++;
 			str = base;
 		}
@@ -384,7 +384,7 @@ void* pathtree_find(struct sorted_tree *tree, char *key )
 
 	/* make a copy to play with */
 
-	if ( *key == '/' )
+	if ( *key == '\\' )
 		keystr = SMB_STRDUP( key+1 );
 	else
 		keystr = SMB_STRDUP( key );
diff --git a/source3/registry/reg_api.c b/source3/registry/reg_api.c
index e380a0d..79b9a1e 100644
--- a/source3/registry/reg_api.c
+++ b/source3/registry/reg_api.c
@@ -475,16 +475,6 @@ WERROR reg_createkey(TALLOC_CTX *ctx, struct registry_key *parent,
 	char *path, *end;
 	WERROR err;
 
-	/*
-	 * We must refuse to handle subkey-paths containing
-	 * a '/' character because at a lower level, after
-	 * normalization, '/' is treated as a key separator
-	 * just like '\\'.
-	 */
-	if (strchr(subkeypath, '/') != NULL) {
-		return WERR_INVALID_PARAM;
-	}
-
 	if (!(mem_ctx = talloc_new(ctx))) return WERR_NOMEM;
 
 	if (!(path = talloc_strdup(mem_ctx, subkeypath))) {
diff --git a/source3/registry/reg_backend_db.c b/source3/registry/reg_backend_db.c
index 4e7f855..9a0e632 100644
--- a/source3/registry/reg_backend_db.c
+++ b/source3/registry/reg_backend_db.c
@@ -21,6 +21,7 @@
 /* Implementation of internal registry database functions. */
 
 #include "includes.h"
+
 #include "registry.h"
 #include "reg_db.h"
 #include "reg_util_internal.h"
@@ -387,14 +388,81 @@ done:
 	return werr;
 }
 
+static int regdb_normalize_keynames_fn(struct db_record *rec,
+				       void *private_data)
+{
+	TALLOC_CTX *mem_ctx = talloc_tos();
+	const char *keyname;
+	NTSTATUS status;
+
+	if (rec->key.dptr == NULL || rec->key.dsize == 0) {
+		return 0;
+	}
+
+	keyname = strchr((const char *) rec->key.dptr, '/');
+	if (keyname) {
+		struct db_record new_rec;
+
+		keyname = talloc_string_sub(mem_ctx,
+					    (const char *) rec->key.dptr,
+					    "/",
+					    "\\");
+
+		DEBUG(2, ("regdb_normalize_keynames_fn: Convert %s to %s\n",
+			  (const char *) rec->key.dptr,
+			  keyname));
+
+		new_rec.value.dptr = rec->value.dptr;
+		new_rec.value.dsize = rec->value.dsize;
+		new_rec.key.dptr = (unsigned char *) keyname;
+		new_rec.key.dsize = strlen(keyname);
+		new_rec.private_data = rec->private_data;
+
+		/* Delete the original record and store the normalized key */
+		status = rec->delete_rec(rec);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(0,("regdb_normalize_keynames_fn: "
+				 "tdb_delete for [%s] failed!\n",
+				 rec->key.dptr));
+			return 1;
+		}
+
+		status = rec->store(&new_rec, new_rec.value, TDB_REPLACE);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(0,("regdb_normalize_keynames_fn: "
+				 "failed to store new record for [%s]!\n",
+				 keyname));
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static WERROR regdb_upgrade_to_version_2(void)
+{
+	TALLOC_CTX *mem_ctx;
+	int rc;
+
+	mem_ctx = talloc_stackframe();
+	if (mem_ctx == NULL) {
+		return WERR_NOMEM;
+	}
+
+	rc = regdb->traverse(regdb, regdb_normalize_keynames_fn, mem_ctx);
+
+	talloc_destroy(mem_ctx);
+	return (rc == -1 ? WERR_REG_IO_FAILURE : WERR_OK);
+}
+
 /***********************************************************************
  Open the registry database
  ***********************************************************************/
- 
+
 WERROR regdb_init(void)
 {
 	const char *vstring = "INFO/version";
-	uint32 vers_id;
+	uint32 vers_id, expected_version;
 	WERROR werr;
 
 	if (regdb) {
@@ -421,24 +489,71 @@ WERROR regdb_init(void)
 
 	regdb_refcount = 1;
 
+	expected_version = REGVER_V2;
+
 	vers_id = dbwrap_fetch_int32(regdb, vstring);
+	if (vers_id == -1) {
+		NTSTATUS status;
+
+		DEBUG(10, ("regdb_init: registry version uninitialized "
+			   "(got %d), initializing to version %d\n",
+			   vers_id, expected_version));
+
+		status = dbwrap_trans_store_int32(regdb, vstring, REGVER_V2);
+		if (!NT_STATUS_IS_OK(status)) {
+			DEBUG(1, ("regdb_init: error storing %s = %d: %s\n",
+				  vstring, expected_version, nt_errstr(status)));
+			return ntstatus_to_werror(status);
+		} else {
+			DEBUG(10, ("regdb_init: stored %s = %d\n",
+				  vstring, expected_version));
+		}
+
+		return WERR_OK;
+	}
+
+	if (vers_id > expected_version || vers_id == 0) {
+		DEBUG(1, ("regdb_init: unknown registry version %d "
+			  "(code version = %d), refusing initialization\n",
+			  vers_id, expected_version));
+		return WERR_CAN_NOT_COMPLETE;
+	}
 
-	if ( vers_id != REGVER_V1 ) {
+	if (vers_id == REGVER_V1) {
 		NTSTATUS status;
-		/* any upgrade code here if needed */
-		DEBUG(10, ("regdb_init: got %s = %d != %d\n", vstring,
-			   vers_id, REGVER_V1));
-		status = dbwrap_trans_store_int32(regdb, vstring, REGVER_V1);
+
+		DEBUG(10, ("regdb_init: got registry db version %d, upgrading "
+			   "to version %d\n", REGVER_V1, REGVER_V2));
+
+		if (regdb->transaction_start(regdb) != 0) {
+			return WERR_REG_IO_FAILURE;
+		}
+
+		werr = regdb_upgrade_to_version_2();
+		if (!W_ERROR_IS_OK(werr)) {
+			regdb->transaction_cancel(regdb);
+			return werr;
+		}
+
+		status = dbwrap_trans_store_int32(regdb, vstring, REGVER_V2);
 		if (!NT_STATUS_IS_OK(status)) {
 			DEBUG(1, ("regdb_init: error storing %s = %d: %s\n",
-				  vstring, REGVER_V1, nt_errstr(status)));
+				  vstring, REGVER_V2, nt_errstr(status)));
+			regdb->transaction_cancel(regdb);
 			return ntstatus_to_werror(status);
 		} else {
 			DEBUG(10, ("regdb_init: stored %s = %d\n",
-				  vstring, REGVER_V1));
+				  vstring, REGVER_V2));
 		}
+		if (regdb->transaction_commit(regdb) != 0) {
+			return WERR_REG_IO_FAILURE;
+		}
+
+		vers_id = REGVER_V2;
 	}
 
+	/* future upgrade code should go here */
+
 	return WERR_OK;
 }
 
@@ -541,7 +656,7 @@ static WERROR regdb_delete_key_with_prefix(struct db_context *db,
 	if (prefix == NULL) {
 		path = discard_const_p(char, keyname);
 	} else {
-		path = talloc_asprintf(mem_ctx, "%s/%s", prefix, keyname);
+		path = talloc_asprintf(mem_ctx, "%s\\%s", prefix, keyname);
 		if (path == NULL) {
 			goto done;
 		}
@@ -586,14 +701,14 @@ static WERROR regdb_delete_key_lists(struct db_context *db, const char *keyname)
 
 	werr = regdb_delete_values(db, keyname);
 	if (!W_ERROR_IS_OK(werr)) {
-		DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
+		DEBUG(1, (__location__ " Deleting %s\\%s failed: %s\n",
 			  REG_VALUE_PREFIX, keyname, win_errstr(werr)));
 		goto done;
 	}
 
 	werr = regdb_delete_secdesc(db, keyname);
 	if (!W_ERROR_IS_OK(werr)) {
-		DEBUG(1, (__location__ " Deleting %s/%s failed: %s\n",
+		DEBUG(1, (__location__ " Deleting %s\\%s failed: %s\n",
 			  REG_SECDESC_PREFIX, keyname, win_errstr(werr)));
 		goto done;
 	}
@@ -706,7 +821,7 @@ static WERROR regdb_store_keys_internal2(struct db_context *db,
 	 * Delete a sorted subkey cache for regdb_key_exists, will be
 	 * recreated automatically
 	 */
-	keyname = talloc_asprintf(ctx, "%s/%s", REG_SORTED_SUBKEYS_PREFIX,
+	keyname = talloc_asprintf(ctx, "%s\\%s", REG_SORTED_SUBKEYS_PREFIX,
 				  keyname);
 	if (keyname == NULL) {
 		werr = WERR_NOMEM;
@@ -797,7 +912,7 @@ static NTSTATUS regdb_store_keys_action(struct db_context *db,
 			continue;
 		}
 
-		path = talloc_asprintf(mem_ctx, "%s/%s", store_ctx->key,
+		path = talloc_asprintf(mem_ctx, "%s\\%s", store_ctx->key,
 				       oldkeyname);
 		if (!path) {
 			werr = WERR_NOMEM;
@@ -841,7 +956,7 @@ static NTSTATUS regdb_store_keys_action(struct db_context *db,
 	}
 
 	for (i=0; i<num_subkeys; i++) {
-		path = talloc_asprintf(mem_ctx, "%s/%s", store_ctx->key,
+		path = talloc_asprintf(mem_ctx, "%s\\%s", store_ctx->key,
 				regsubkey_ctr_specific_key(store_ctx->ctr, i));
 		if (!path) {
 			werr = WERR_NOMEM;
@@ -1084,7 +1199,7 @@ static WERROR regdb_delete_subkey(const char *key, const char *subkey)
 		goto done;
 	}
 
-	path = talloc_asprintf(mem_ctx, "%s/%s", key, subkey);
+	path = talloc_asprintf(mem_ctx, "%s\\%s", key, subkey);
 	if (path == NULL) {
 		werr = WERR_NOMEM;
 		goto done;
@@ -1128,7 +1243,7 @@ static TDB_DATA regdb_fetch_key_internal(struct db_context *db,
 
 /**
  * check whether a given key name represents a base key,
- * i.e one without a subkey separator ('/' or '\').
+ * i.e one without a subkey separator ('\').
  */
 static bool regdb_key_is_base_key(const char *key)
 {
@@ -1150,7 +1265,7 @@ static bool regdb_key_is_base_key(const char *key)
 		goto done;
 	}
 
-	ret = (strrchr(path, '/') == NULL);
+	ret = (strrchr(path, '\\') == NULL);
 
 done:
 	TALLOC_FREE(mem_ctx);
@@ -1353,7 +1468,7 @@ static bool scan_parent_subkeys(struct db_context *db, const char *parent,
 		goto fail;
 	}
 
-	key = talloc_asprintf(talloc_tos(), "%s/%s",
+	key = talloc_asprintf(talloc_tos(), "%s\\%s",
 			      REG_SORTED_SUBKEYS_PREFIX, path);
 	if (key == NULL) {
 		goto fail;
@@ -1433,7 +1548,7 @@ static bool regdb_key_exists(struct db_context *db, const char *key)
 		goto done;
 	}
 
-	p = strrchr(path, '/');
+	p = strrchr(path, '\\');
 	if (p == NULL) {
 		/* this is a base key */
 		value = regdb_fetch_key_internal(db, mem_ctx, path);
@@ -1627,7 +1742,7 @@ static int regdb_fetch_values_internal(struct db_context *db, const char* key,
 		goto done;
 	}
 
-	keystr = talloc_asprintf(ctx, "%s/%s", REG_VALUE_PREFIX, key);
+	keystr = talloc_asprintf(ctx, "%s\\%s", REG_VALUE_PREFIX, key);
 	if (!keystr) {
 		goto done;
 	}
@@ -1686,7 +1801,7 @@ static bool regdb_store_values_internal(struct db_context *db, const char *key,
 
 	SMB_ASSERT( len == data.dsize );
 
-	keystr = talloc_asprintf(ctx, "%s/%s", REG_VALUE_PREFIX, key );
+	keystr = talloc_asprintf(ctx, "%s\\%s", REG_VALUE_PREFIX, key );
 	if (!keystr) {
 		goto done;
 	}
@@ -1735,7 +1850,7 @@ static WERROR regdb_get_secdesc(TALLOC_CTX *mem_ctx, const char *key,
 		goto done;
 	}
 
-	tdbkey = talloc_asprintf(tmp_ctx, "%s/%s", REG_SECDESC_PREFIX, key);
+	tdbkey = talloc_asprintf(tmp_ctx, "%s\\%s", REG_SECDESC_PREFIX, key);
 	if (tdbkey == NULL) {
 		err = WERR_NOMEM;
 		goto done;
@@ -1780,7 +1895,7 @@ static WERROR regdb_set_secdesc(const char *key,
 		goto done;
 	}
 
-	tdbkey = talloc_asprintf(mem_ctx, "%s/%s", REG_SECDESC_PREFIX, key);
+	tdbkey = talloc_asprintf(mem_ctx, "%s\\%s", REG_SECDESC_PREFIX, key);
 	if (tdbkey == NULL) {
 		goto done;
 	}
diff --git a/source3/registry/reg_cachehook.c b/source3/registry/reg_cachehook.c
index 6b00ab4..dc07b51 100644
--- a/source3/registry/reg_cachehook.c
+++ b/source3/registry/reg_cachehook.c
@@ -46,12 +46,6 @@ static WERROR keyname_to_path(TALLOC_CTX *mem_ctx, const char *keyname,
 		return WERR_NOMEM;
 	}
 
-	tmp_path = talloc_string_sub(mem_ctx, tmp_path, "\\", "/");
-	if (tmp_path == NULL) {
-		DEBUG(0, ("talloc_string_sub_failed!\n"));
-		return WERR_NOMEM;
-	}
-
 	*path = tmp_path;
 
 	return WERR_OK;
diff --git a/source3/registry/reg_util_internal.c b/source3/registry/reg_util_internal.c
index 47e2ce5..a1aeaa4 100644
--- a/source3/registry/reg_util_internal.c
+++ b/source3/registry/reg_util_internal.c
@@ -86,9 +86,8 @@ bool reg_split_key(char *path, char **base, char **key)
 }
 
 /**
- * The full path to the registry key is used as database key
- * after the \'s are converted to /'s.
- * Leading and trailing '/' and '\' characters are stripped.
+ * The full path to the registry key is used as database key.
+ * Leading and trailing '\' characters are stripped.
  * Key string is also normalized to UPPER case.
  */
 
@@ -97,22 +96,22 @@ char *normalize_reg_path(TALLOC_CTX *ctx, const char *keyname )
 	char *p;
 	char *nkeyname;
 
-	/* skip leading '/' and '\' chars */
+	/* skip leading '\' chars */
 	p = (char *)keyname;
-	while ((*p == '/') || (*p == '\\')) {
+	while (*p == '\\') {
 		p++;
 	}
 
-	nkeyname = talloc_string_sub(ctx, p, "\\", "/");
+	nkeyname = talloc_strdup(ctx, p);
 	if (nkeyname == NULL) {
 		return NULL;
 	}
 
-	/* strip trailing '/' chars */
-	p = strrchr(nkeyname, '/');
+	/* strip trailing '\' chars */
+	p = strrchr(nkeyname, '\\');
 	while ((p != NULL) && (p[1] == '\0')) {
 		*p = '\0';
-		p = strrchr(nkeyname, '/');
+		p = strrchr(nkeyname, '\\');
 	}
 
 	strupper_m(nkeyname);
@@ -139,11 +138,7 @@ char *reg_remaining_path(TALLOC_CTX *ctx, const char *key)
 	}
 	/* normalize_reg_path( new_path ); */
 	if (!(p = strchr(new_path, '\\')) ) {
-		if (!(p = strchr( new_path, '/'))) {
-			p = new_path;
-		} else {
-			p++;
-		}
+		p = new_path;
 	} else {
 		p++;
 	}
diff --git a/source3/utils/net_registry_util.c b/source3/utils/net_registry_util.c
index 5bb2893..a3b84a3 100644
--- a/source3/utils/net_registry_util.c
+++ b/source3/utils/net_registry_util.c
@@ -98,7 +98,9 @@ void print_registry_value_with_name(const char *valname,
 /**
  * Split path into hive name and subkeyname
  * normalizations performed:
- *  - convert '/' to '\\'
+ *  - if the path contains no '\\' characters,
+ *    assume that the legacy format of using '/'
+ *    as a separator is used and  convert '/' to '\\'
  *  - strip trailing '\\' chars
  */
 WERROR split_hive_key(TALLOC_CTX *ctx, const char *path, char **hivename,
@@ -115,7 +117,12 @@ WERROR split_hive_key(TALLOC_CTX *ctx, const char *path, char **hivename,
 		return WERR_INVALID_PARAM;
 	}
 
-	*hivename = talloc_string_sub(ctx, path, "/", "\\");
+	if (strchr(path, '\\') == NULL) {
+		*hivename = talloc_string_sub(ctx, path, "/", "\\");
+	} else {
+		*hivename = talloc_strdup(ctx, path);
+	}


-- 
Samba Shared Repository


More information about the samba-cvs mailing list