diff options
author | Vicentiu Ciorbaru <cvicentiu@gmail.com> | 2011-08-03 23:19:21 +0300 |
---|---|---|
committer | Michael Adam <obnox@samba.org> | 2011-08-22 13:59:28 +0200 |
commit | 57b7fb7256e0d4e09c29e48950820f80d5c613dc (patch) | |
tree | 88c441b68813042f5886d897f47eaed830586f27 /source3 | |
parent | a00851f33767f466e9d95b4bcac6fecaf26b0fbf (diff) | |
download | samba-57b7fb7256e0d4e09c29e48950820f80d5c613dc.tar.gz samba-57b7fb7256e0d4e09c29e48950820f80d5c613dc.tar.bz2 samba-57b7fb7256e0d4e09c29e48950820f80d5c613dc.zip |
s3-net: Implemented net rpc conf import command
The function takes a local file in smb.conf format,
uses calls to smbconf to create smbconf_service structs,
which are then placed in the remote registry.
The function also provides a test module to only print
the changes that it would make.
Signed-off-by: Michael Adam <obnox@samba.org>
Diffstat (limited to 'source3')
-rw-r--r-- | source3/utils/net_rpc_conf.c | 350 |
1 files changed, 347 insertions, 3 deletions
diff --git a/source3/utils/net_rpc_conf.c b/source3/utils/net_rpc_conf.c index 02cfc33490..d33b2bca15 100644 --- a/source3/utils/net_rpc_conf.c +++ b/source3/utils/net_rpc_conf.c @@ -34,7 +34,12 @@ #include "../librpc/gen_ndr/ndr_winreg_c.h" #include "../libcli/registry/util_reg.h" #include "rpc_client/cli_winreg.h" -#include "../lib/smbconf/smbconf.h" +#include "lib/smbconf/smbconf.h" +#include "lib/smbconf/smbconf_init.h" +#include "lib/smbconf/smbconf_reg.h" +#include "lib/param/loadparm.h" + + /* internal functions */ /********************************************************** @@ -84,6 +89,21 @@ static int rpc_conf_addshare_usage(struct net_context *c, int argc, return -1; } + +static int rpc_conf_import_usage(struct net_context *c, int argc, + const char**argv) +{ + d_printf("%s\n%s", + _("Usage:"), + _(" net rpc conf import [--test|-T] <filename> " + "[<servicename>]\n" + "\t[--test|-T] testmode - do not act, just print " + "what would be done\n" + "\t<servicename> only import service <servicename>, " + "ignore the rest\n")); + return -1; +} + static int rpc_conf_showshare_usage(struct net_context *c, int argc, const char **argv) { @@ -239,6 +259,149 @@ error: return status;; } +static NTSTATUS rpc_conf_set_share(TALLOC_CTX *mem_ctx, + struct dcerpc_binding_handle *b, + struct policy_handle *parent_hnd, + struct smbconf_service *service, + WERROR *werr) +{ + TALLOC_CTX *frame = talloc_stackframe(); + + NTSTATUS status = NT_STATUS_OK; + WERROR result = WERR_OK; + WERROR _werr; + enum winreg_CreateAction action; + uint32_t i, j; + + const char **includes; + + struct winreg_String wkey, wkeyclass; + struct policy_handle share_hnd; + + ZERO_STRUCT(share_hnd); + ZERO_STRUCT(wkey); + ZERO_STRUCT(wkeyclass); + + wkey.name = service->name; + wkeyclass.name = ""; + action = REG_ACTION_NONE; + + status = dcerpc_winreg_CreateKey(b, + frame, + parent_hnd, + wkey, + wkeyclass, + 0, + REG_KEY_ALL, + NULL, + &share_hnd, + &action, + &result); + + if (!NT_STATUS_IS_OK(status)) { + d_printf("winreg_CreateKey: Could not create smbconf key\n"); + goto error; + } + + if (!W_ERROR_IS_OK(result)) { + d_printf("winreg_CreateKey: Could not create smbconf key\n"); + goto error; + } + + for (i = 0; i < service->num_params; i++) { + if (strequal(service->param_names[i], "include") == 0) + { + + status = dcerpc_winreg_set_sz(frame, b, &share_hnd, + service->param_names[i], + service->param_values[i], + &result); + + if (!(NT_STATUS_IS_OK(status))) { + d_fprintf(stderr, + "ERROR: Share: '%s'\n" + "Could not set parameter '%s'" + " with value %s\n %s\n", + service->name, + service->param_names[i], + service->param_values[i], + nt_errstr(status)); + goto error; + } + + if (!(W_ERROR_IS_OK(result))) { + d_fprintf(stderr, + "ERROR: Share: '%s'\n" + "Could not set parameter '%s'" + " with value %s\n %s\n", + service->name, + service->param_names[i], + service->param_values[i], + win_errstr(result)); + goto error; + } + } else { + + includes = talloc_zero_array(frame, + const char *, + service->num_params + 1); + if (includes == NULL) { + result = WERR_NOMEM; + d_fprintf(stderr, "ERROR: out of memory\n"); + goto error; + } + + for (j = i; j < service->num_params; j++) { + + includes[j - i] = talloc_strdup( + frame, + service->param_values[j]); + + if (includes[j-i] == NULL) { + result = WERR_NOMEM; + d_fprintf(stderr, "ERROR: out of memory\n"); + goto error; + } + } + + status = dcerpc_winreg_set_multi_sz(frame, b, &share_hnd, + "includes", + includes, + &result); + + if (!(NT_STATUS_IS_OK(status))) { + d_fprintf(stderr, "ERROR: Share: '%s'\n" + "Could not set includes\n %s\n", + service->name, + nt_errstr(status)); + goto error; + } + + if (!(W_ERROR_IS_OK(result))) { + d_fprintf(stderr, "ERROR: Share: '%s'\n" + "Could not set includes\n %s\n", + service->name, + win_errstr(result)); + goto error; + } + + i = service->num_params; + } + } + +error: + /* in case of error, should it delete the created key? */ + if (!(W_ERROR_IS_OK(result))) { + status = werror_to_ntstatus(result); + + } + + dcerpc_winreg_CloseKey(b, frame, &share_hnd, &_werr); + + TALLOC_FREE(frame); + return status; + +} static NTSTATUS rpc_conf_get_share(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *b, @@ -924,6 +1087,187 @@ error: return status; } +static NTSTATUS rpc_conf_import_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 dcerpc_binding_handle *b = pipe_hnd->binding_handle; + + struct policy_handle hive_hnd, key_hnd; + + const char *filename = NULL; + const char *servicename = NULL; + char *conf_source = NULL; + TALLOC_CTX *frame; + struct smbconf_ctx *txt_ctx; + struct smbconf_service *service = NULL; + struct smbconf_service **services = NULL; + uint32_t num_shares, i; + sbcErr err; + + WERROR werr = WERR_OK; + NTSTATUS status = NT_STATUS_OK; + + ZERO_STRUCT(hive_hnd); + ZERO_STRUCT(key_hnd); + + frame = talloc_stackframe(); + + if (c->display_usage) { + rpc_conf_import_usage(c, argc, argv); + status = NT_STATUS_INVALID_PARAMETER; + goto error; + } + + switch (argc) { + case 0: + default: + rpc_conf_import_usage(c, argc, argv); + status = NT_STATUS_INVALID_PARAMETER; + goto error; + case 2: + servicename = talloc_strdup(frame, argv[1]); + if (servicename == NULL) { + d_printf(_("error: out of memory!\n")); + goto error; + } + case 1: + filename = argv[0]; + break; + } + + DEBUG(3,("rpc_conf_import: reading configuration from file %s.\n", + filename)); + + conf_source = talloc_asprintf(frame, "file:%s", filename); + if (conf_source == NULL) { + d_fprintf(stderr, _("error: out of memory!\n")); + goto error; + } + + err = smbconf_init(frame, &txt_ctx, conf_source); + if (!SBC_ERROR_IS_OK(err)) { + d_fprintf(stderr, _("error loading file '%s': %s\n"), filename, + sbcErrorString(err)); + goto error; + } + + if (c->opt_testmode) { + d_printf(_("\nTEST MODE - " + "would import the following configuration:\n\n")); + } + + if (servicename != NULL) { + err = smbconf_get_share(txt_ctx, frame, + servicename, + &service); + if (!SBC_ERROR_IS_OK(err)) { + goto error; + } + + num_shares = 1; + + } else { + + err = smbconf_get_config(txt_ctx, frame, + &num_shares, + &services); + if (!SBC_ERROR_IS_OK(err)) { + goto error; + } + } + + if (c->opt_testmode) { + if (servicename != NULL) { + rpc_conf_print_shares(1, service); + } + for (i = 0; i < num_shares; i++) { + rpc_conf_print_shares(1, services[i]); + } + goto error; + } + + status = rpc_conf_drop_internal(c, + domain_sid, + domain_name, + cli, + pipe_hnd, + frame, + 0, + NULL ); + + if (!(NT_STATUS_IS_OK(status))) { + goto error; + } + + status = rpc_conf_open_conf(frame, + b, + REG_KEY_READ, + &hive_hnd, + &key_hnd, + &werr); + + if (!(NT_STATUS_IS_OK(status))) { + goto error; + } + + if (!(W_ERROR_IS_OK(werr))) { + goto error; + } + + if (servicename != NULL) { + status = rpc_conf_set_share(frame, + b, + &key_hnd, + service, + &werr); + + if (!(NT_STATUS_IS_OK(status))) { + goto error; + } + + if (!(W_ERROR_IS_OK(werr))) { + goto error; + } + + } else { + + for (i = 0; i < num_shares; i++) { + status = rpc_conf_set_share(frame, + b, + &key_hnd, + services[i], + &werr); + + if (!(NT_STATUS_IS_OK(status))) { + goto error; + } + + if (!(W_ERROR_IS_OK(werr))) { + goto error; + } + + } + } + +error: + if (!SBC_ERROR_IS_OK(err)) { + d_fprintf(stderr, "ERROR: %s\n", sbcErrorString(err)); + } + + if (!(W_ERROR_IS_OK(werr))) { + status = werror_to_ntstatus(werr); + } + TALLOC_FREE(frame); + return status; +} + static NTSTATUS rpc_conf_showshare_internal(struct net_context *c, const struct dom_sid *domain_sid, const char *domain_name, @@ -1918,8 +2262,8 @@ static int rpc_conf_list(struct net_context *c, int argc, static int rpc_conf_import(struct net_context *c, int argc, const char **argv) { - d_printf("Function not yet implemented\n"); - return 0; + return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, + rpc_conf_import_internal, argc, argv ); } static int rpc_conf_delshare(struct net_context *c, int argc, const char **argv) |