diff options
| -rw-r--r-- | source3/utils/net_rpc_registry.c | 270 | 
1 files changed, 268 insertions, 2 deletions
diff --git a/source3/utils/net_rpc_registry.c b/source3/utils/net_rpc_registry.c index 76e8555a3f..d0d09481ed 100644 --- a/source3/utils/net_rpc_registry.c +++ b/source3/utils/net_rpc_registry.c @@ -26,6 +26,9 @@  #include "../librpc/gen_ndr/cli_winreg.h"  #include "registry/reg_objects.h"  #include "../librpc/gen_ndr/ndr_security.h" +#include "registry/reg_format.h" +#include <assert.h> +  /*******************************************************************   connect to a registry hive root (open a registry policy) @@ -378,6 +381,120 @@ static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,  	return status;  } +static NTSTATUS registry_enumvalues2(TALLOC_CTX *ctx, +				     struct rpc_pipe_client *pipe_hnd, +				     struct policy_handle *key_hnd, +				     uint32 *pnum_values, char ***pvalnames, +				     struct regval_blob ***pvalues) +{ +	TALLOC_CTX *mem_ctx; +	NTSTATUS status; +	uint32 num_subkeys, max_subkeylen, max_classlen; +	uint32 num_values, max_valnamelen, max_valbufsize; +	uint32 i; +	NTTIME last_changed_time; +	uint32 secdescsize; +	struct winreg_String classname; +	struct regval_blob **values; +	char **names; + +	if (!(mem_ctx = talloc_new(ctx))) { +		return NT_STATUS_NO_MEMORY; +	} + +	ZERO_STRUCT(classname); +	status = rpccli_winreg_QueryInfoKey( +		pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys, +		&max_subkeylen, &max_classlen, &num_values, &max_valnamelen, +		&max_valbufsize, &secdescsize, &last_changed_time, NULL ); + +	if (!NT_STATUS_IS_OK(status)) { +		goto error; +	} + +	if (num_values == 0) { +		*pnum_values = 0; +		TALLOC_FREE(mem_ctx); +		return NT_STATUS_OK; +	} + +	if ((!(names = TALLOC_ARRAY(mem_ctx, char *, num_values))) || +	    (!(values = TALLOC_ARRAY(mem_ctx, struct regval_blob *, +				     num_values)))) { +		status = NT_STATUS_NO_MEMORY; +		goto error; +	} + +	for (i=0; i<num_values; i++) { +		enum winreg_Type type = REG_NONE; +		uint8 *data = NULL; +		uint32 data_size; +		uint32 value_length; + +		char n; +		struct winreg_ValNameBuf name_buf; +		WERROR err; + +		n = '\0'; +		name_buf.name = &n; +		name_buf.size = max_valnamelen + 2; + +		data_size = max_valbufsize; +		data = (uint8 *)TALLOC(mem_ctx, data_size); +		value_length = 0; + +		status = rpccli_winreg_EnumValue(pipe_hnd, mem_ctx, key_hnd, +						 i, &name_buf, &type, +						 data, &data_size, +						 &value_length, &err); + +		if ( W_ERROR_EQUAL(err, WERR_NO_MORE_ITEMS) ) { +			status = NT_STATUS_OK; +			break; +		} + +		if (!(NT_STATUS_IS_OK(status))) { +			goto error; +		} + +		if (name_buf.name == NULL) { +			status = NT_STATUS_INVALID_PARAMETER; +			goto error; +		} + +		if (!(names[i] = talloc_strdup(names, name_buf.name))) { +			status = NT_STATUS_NO_MEMORY; +			goto error; +		} + +		assert(value_length<=data_size); //??? + +		values[i] = regval_compose(values, +					   name_buf.name, +					   type, +					   data, value_length); +		if (!values[i]) { +			status = NT_STATUS_NO_MEMORY; +			goto error; +		} +	} + +	*pnum_values = num_values; + +	if (pvalnames) { +		*pvalnames = talloc_move(ctx, &names); +	} +	if (pvalues) { +		*pvalues = talloc_move(ctx, &values); +	} + +	status = NT_STATUS_OK; + + error: +	TALLOC_FREE(mem_ctx); +	return status; +} +  static NTSTATUS registry_getsd(TALLOC_CTX *mem_ctx,  			       struct rpc_pipe_client *pipe_hnd,  			       struct policy_handle *key_hnd, @@ -1273,7 +1390,150 @@ static int rpc_registry_getsd(struct net_context *c, int argc, const char **argv  }  /******************************************************************** -********************************************************************/ + ********************************************************************/ +/** + * @defgroup net_rpc_registry net rpc registry + */ + +/** + * @defgroup net_rpc_registry_export Export + * @ingroup net_rpc_registry + * @{ + */ + +static NTSTATUS registry_export(struct rpc_pipe_client* pipe_hnd, +				TALLOC_CTX* ctx, +				struct policy_handle* key_hnd, +				struct reg_format* f, +				const char* parentfullname, +				const char* name) +{ +	NTSTATUS status; +	uint32 num_subkeys = 0; +	uint32 num_values = 0; +	char **names = NULL, **classes = NULL; +	NTTIME **modtimes = NULL; +	struct regval_blob **values = NULL; +	uint32 i; + +	TALLOC_CTX* mem_ctx = talloc_new(ctx); + + +	const char* fullname = name +		? talloc_asprintf(mem_ctx, "%s\\%s", parentfullname, name) +		: parentfullname; +	reg_format_key(f, &fullname, 1, false); + +	status = registry_enumvalues2(mem_ctx, pipe_hnd, key_hnd, &num_values, +				      &names, &values); +	if (!NT_STATUS_IS_OK(status)) { +		d_fprintf(stderr, _("enumerating values failed: %s\n"), +			  nt_errstr(status)); +		goto done; +	} + +	for (i=0; i<num_values; i++) { +		reg_format_regval_blob(f, names[i], values[i]); +	} + + +	status = registry_enumkeys(mem_ctx, pipe_hnd, key_hnd, &num_subkeys, +				   &names, &classes, &modtimes); +	if (!NT_STATUS_IS_OK(status)) { +		d_fprintf(stderr, _("enumerating keys failed: %s\n"), +			  nt_errstr(status)); +		goto done; +	} + +	for (i=0; i<num_subkeys; i++) { +		struct policy_handle subkey_hnd; +		struct winreg_String key; +		ZERO_STRUCT(key); +		/* key.name = talloc_strdup(mem_ctx, names[i]); ??? */ +		key.name = names[i]; + +		status = rpccli_winreg_OpenKey(pipe_hnd, mem_ctx, key_hnd, key, +					       0, REG_KEY_READ, +					       &subkey_hnd, NULL); +		if (NT_STATUS_IS_OK(status)) { +			status = registry_export(pipe_hnd, mem_ctx, &subkey_hnd, +						 f, fullname, names[i]); +			if (!(NT_STATUS_IS_OK(status))) +				d_fprintf(stderr, +					  _("export key failed: %s %s\n"), +					  names[i], nt_errstr(status)); + +			rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, +					       &subkey_hnd, NULL); +		} else { +			d_fprintf(stderr, +				  _("rpccli_winreg_OpenKey failed: %s %s\n"), +				  names[i], nt_errstr(status)); +		} +	} +done: +	talloc_free(mem_ctx); +	return status; +} + +static NTSTATUS rpc_registry_export_internal(struct net_context *c, +					     const struct dom_sid *domain_sid, +					     const char *domain_name, +					     struct cli_state *cli, +					     struct rpc_pipe_client *pipe_hnd, +					     TALLOC_CTX *mem_ctx, +					     int argc, +					     const char **argv ) +{ +	struct policy_handle pol_hive, pol_key; +	NTSTATUS status; +	struct reg_format* f; + +	if (argc < 2 || argc > 3 || c->display_usage) { +		d_printf("%s\n%s", +			 _("Usage:"), +			 _("net rpc registry export <path> <file> [opt]\n")); +		d_printf("%s  net rpc registry export " +			 "'HKLM\\Software\\Samba' samba.reg\n", _("Example:")); +		return NT_STATUS_INVALID_PARAMETER; +	} + +	status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ, +				  &pol_hive, &pol_key); +	if (!NT_STATUS_IS_OK(status)) { +		d_fprintf(stderr, _("registry_openkey failed: %s\n"), +			  nt_errstr(status)); +		return status; +	} + +	f = reg_format_file(mem_ctx, argv[1], (argc > 2) ? argv[2] : NULL); +	if (f == NULL) { +		d_fprintf(stderr, _("open file failed: %s\n"), strerror(errno)); +		return map_nt_error_from_unix(errno); +	} + +	status = registry_export(pipe_hnd, mem_ctx, &pol_key, +				 f, argv[0], NULL ); +	if (!NT_STATUS_IS_OK(status)) +		return status; + +	rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL); +	rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL); + +	return status; +} +/******************************************************************** + ********************************************************************/ + +static int rpc_registry_export(struct net_context *c, int argc, +			       const char **argv ) +{ +	return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, +			       rpc_registry_export_internal, argc, argv ); +} + +/**@}*/ +  int net_rpc_registry(struct net_context *c, int argc, const char **argv)  { @@ -1366,8 +1626,14 @@ int net_rpc_registry(struct net_context *c, int argc, const char **argv)  			N_("net rpc registry getsd\n"  			   "    Get security descriptior")  		}, +		{ +			"export", +			rpc_registry_export, +			NET_TRANSPORT_RPC, +			N_("net registry export\n" +			   "    Export .reg file") +		},  		{NULL, NULL, 0, NULL, NULL}  	}; -  	return net_run_function(c, argc, argv, "net rpc registry", func);  }  | 
