/* * Samba Unix/Linux SMB client library * Distributed SMB/CIFS Server Management Utility * Local configuration interface * Copyright (C) Vicentiu Ciorbaru 2011 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ /* * This is an interface to Samba's configuration. * * This tool supports local as well as remote interaction via rpc * with the configuration stored in the registry. */ #include "includes.h" #include "utils/net.h" #include "rpc_client/cli_pipe.h" #include "../librpc/gen_ndr/ndr_samr_c.h" #include "rpc_client/init_samr.h" #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" /* internal functions */ /********************************************************** * * usage functions * **********************************************************/ const char confpath[100] = "Software\\Samba\\smbconf"; static int rpc_conf_list_usage(struct net_context *c, int argc, const char **argv) { d_printf("%s net rpc conf list\n", _("Usage:")); return -1; } static int rpc_conf_listshares_usage(struct net_context *c, int argc, const char **argv) { d_printf("%s net rpc conf listshares\n", _("Usage:")); return -1; } static int rpc_conf_delshare_usage(struct net_context *c, int argc, const char **argv) { d_printf("%s\n%s", _("Usage:"), _("net rpc conf delshare \n")); return -1; } static int rpc_conf_showshare_usage(struct net_context *c, int argc, const char **argv) { d_printf("%s\n%s", _("Usage:"), _("net rpc conf showshare \n")); return -1; } static int rpc_conf_drop_usage(struct net_context *c, int argc, const char **argv) { d_printf("%s\nnet rpc conf drop\n", _("Usage:")); return -1; } static int rpc_conf_getparm_usage(struct net_context *c, int argc, const char **argv) { d_printf("%s\nnet rpc conf getparm \n", _("Usage:")); return -1; } static int rpc_conf_setparm_usage(struct net_context *c, int argc, const char **argv) { d_printf("%s\n%s", _("Usage:"), _(" net rpc conf setparm
\n")); return -1; } static int rpc_conf_delparm_usage(struct net_context *c, int argc, const char **argv) { d_printf("%s\nnet rpc conf delparm \n", _("Usage:")); return -1; } static int rpc_conf_getincludes_usage(struct net_context *c, int argc, const char **argv) { d_printf("%s\nnet rpc conf getincludes \n", _("Usage:")); return -1; } static int rpc_conf_delincludes_usage(struct net_context *c, int argc, const char **argv) { d_printf("%s\nnet rpc conf delincludes \n", _("Usage:")); return -1; } static bool rpc_conf_reg_valname_forbidden(const char * valname) { const char *forbidden_valnames[] = { "lock directory", "lock dir", "config backend", "include", "includes", /* this has a special meaning internally */ NULL }; const char **forbidden = NULL; for (forbidden = forbidden_valnames; *forbidden != NULL; forbidden++) { if (strwicmp(valname, *forbidden) == 0) { return true; } } return false; } static NTSTATUS rpc_conf_del_value(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *b, struct policy_handle *parent_hnd, const char *share_name, const char *value, WERROR *werr) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR result = WERR_OK; WERROR _werr; struct winreg_String keyname, valuename; struct policy_handle child_hnd; ZERO_STRUCT(child_hnd); ZERO_STRUCT(keyname); ZERO_STRUCT(valuename); keyname.name = share_name; valuename.name = value; status = dcerpc_winreg_OpenKey(b, frame, parent_hnd, keyname, 0, REG_KEY_WRITE, &child_hnd, &result); if (!(NT_STATUS_IS_OK(status))) { d_fprintf(stderr, _("Failed to open key '%s': %s\n"), keyname.name, nt_errstr(status)); goto error; } if (!(W_ERROR_IS_OK(result))) { d_fprintf(stderr, _("Failed to open key '%s': %s\n"), keyname.name, win_errstr(result)); goto error; } status = dcerpc_winreg_DeleteValue(b, frame, &child_hnd, valuename, &result); if (!(NT_STATUS_IS_OK(status))) { d_fprintf(stderr, _("Failed to delete value %s\n"), nt_errstr(status)); goto error; } if (!(W_ERROR_IS_OK(result))) { if (W_ERROR_EQUAL(result, WERR_BADFILE)){ result = WERR_OK; goto error; } d_fprintf(stderr, _("Failed to delete value %s\n"), win_errstr(result)); goto error; } error: *werr = result; dcerpc_winreg_CloseKey(b, frame, &child_hnd, &_werr); TALLOC_FREE(frame); return status;; } static NTSTATUS rpc_conf_get_share(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *b, struct policy_handle *parent_hnd, const char *share_name, struct smbconf_service *share, WERROR *werr) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR result = WERR_OK; WERROR _werr; struct policy_handle child_hnd; int32_t includes_cnt, includes_idx = -1; uint32_t num_vals, i, param_cnt = 0; const char **val_names; enum winreg_Type *types; DATA_BLOB *data; struct winreg_String key; const char **multi_s = NULL; const char *s = NULL; struct smbconf_service tmp_share; ZERO_STRUCT(tmp_share); key.name = share_name; status = dcerpc_winreg_OpenKey(b, frame, parent_hnd, key, 0, REG_KEY_READ, &child_hnd, &result); if (!(NT_STATUS_IS_OK(status))) { d_fprintf(stderr, _("Failed to open subkey: %s\n"), nt_errstr(status)); goto error; } if (!(W_ERROR_IS_OK(result))) { d_fprintf(stderr, _("Failed to open subkey: %s\n"), win_errstr(result)); goto error; } /* get all the info from the share key */ status = dcerpc_winreg_enumvals(frame, b, &child_hnd, &num_vals, &val_names, &types, &data, &result); if (!(NT_STATUS_IS_OK(status))) { d_fprintf(stderr, _("Failed to enumerate values: %s\n"), nt_errstr(status)); goto error; } if (!(W_ERROR_IS_OK(result))) { d_fprintf(stderr, _("Failed to enumerate values: %s\n"), win_errstr(result)); goto error; } /* check for includes */ for (i = 0; i < num_vals; i++) { if (strcmp(val_names[i], "includes") == 0){ if (!pull_reg_multi_sz(frame, &data[i], &multi_s)) { result = WERR_NOMEM; d_fprintf(stderr, _("Failed to enumerate values: %s\n"), win_errstr(result)); goto error; } includes_idx = i; } } /* count the number of includes */ includes_cnt = 0; if (includes_idx != -1) { for (includes_cnt = 0; multi_s[includes_cnt] != NULL; includes_cnt ++); } /* place the name of the share in the smbconf_service struct */ tmp_share.name = talloc_strdup(frame, share_name); if (tmp_share.name == NULL) { result = WERR_NOMEM; d_fprintf(stderr, _("Failed to create share: %s\n"), win_errstr(result)); goto error; } /* place the number of parameters in the smbconf_service struct */ tmp_share.num_params = num_vals; if (includes_idx != -1) { tmp_share.num_params = num_vals + includes_cnt - 1; } /* allocate memory for the param_names and param_values lists */ tmp_share.param_names = talloc_zero_array(frame, char *, tmp_share.num_params); if (tmp_share.param_names == NULL) { result = WERR_NOMEM; d_fprintf(stderr, _("Failed to create share: %s\n"), win_errstr(result)); goto error; } tmp_share.param_values = talloc_zero_array(frame, char *, tmp_share.num_params); if (tmp_share.param_values == NULL) { result = WERR_NOMEM; d_fprintf(stderr, _("Failed to create share: %s\n"), win_errstr(result)); goto error; } /* place all params except includes */ for (i = 0; i < num_vals; i++) { if (strcmp(val_names[i], "includes") != 0) { if (!pull_reg_sz(frame, &data[i], &s)) { result = WERR_NOMEM; d_fprintf(stderr, _("Failed to enumerate values: %s\n"), win_errstr(result)); goto error; } /* place param_names */ tmp_share.param_names[param_cnt] = talloc_strdup(frame, val_names[i]); if (tmp_share.param_names[param_cnt] == NULL) { result = WERR_NOMEM; d_fprintf(stderr, _("Failed to create share: %s\n"), win_errstr(result)); goto error; } /* place param_values */ tmp_share.param_values[param_cnt++] = talloc_strdup(frame, s); if (tmp_share.param_values[param_cnt - 1] == NULL) { result = WERR_NOMEM; d_fprintf(stderr, _("Failed to create share: %s\n"), win_errstr(result)); goto error; } } } /* place the includes last */ for (i = 0; i < includes_cnt; i++) { tmp_share.param_names[param_cnt] = talloc_strdup(frame, "include"); if (tmp_share.param_names[param_cnt] == NULL) { result = WERR_NOMEM; d_fprintf(stderr, _("Failed to create share: %s\n"), win_errstr(result)); goto error; } tmp_share.param_values[param_cnt++] = talloc_strdup(frame, multi_s[i]); if (tmp_share.param_values[param_cnt - 1] == NULL) { result = WERR_NOMEM; d_fprintf(stderr, _("Failed to create share: %s\n"), win_errstr(result)); goto error; } } /* move everything to the main memory ctx */ for (i = 0; i < param_cnt; i++) { tmp_share.param_names[i] = talloc_move(mem_ctx, &tmp_share.param_names[i]); tmp_share.param_values[i] = talloc_move(mem_ctx, &tmp_share.param_values[i]); } tmp_share.name = talloc_move(mem_ctx, &tmp_share.name); tmp_share.param_names = talloc_move(mem_ctx, &tmp_share.param_names); tmp_share.param_values = talloc_move(mem_ctx, &tmp_share.param_values); /* out parameter */ *share = tmp_share; error: /* close child */ dcerpc_winreg_CloseKey(b, frame, &child_hnd, &_werr); *werr = result; TALLOC_FREE(frame); return status; } static int rpc_conf_print_shares(uint32_t num_shares, struct smbconf_service *shares) { uint32_t share_count, param_count; const char *indent = "\t"; if (num_shares == 0) { return 0; } for (share_count = 0; share_count < num_shares; share_count++) { d_printf("\n"); if (shares[share_count].name != NULL) { d_printf("[%s]\n", shares[share_count].name); } for (param_count = 0; param_count < shares[share_count].num_params; param_count++) { d_printf("%s%s = %s\n", indent, shares[share_count].param_names[param_count], shares[share_count].param_values[param_count]); } } d_printf("\n"); return 0; } static NTSTATUS rpc_conf_open_conf(TALLOC_CTX *mem_ctx, struct dcerpc_binding_handle *b, uint32_t access_mask, struct policy_handle *hive_hnd, struct policy_handle *key_hnd, WERROR *werr) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR result = WERR_OK; WERROR _werr; struct policy_handle tmp_hive_hnd, tmp_key_hnd; struct winreg_String key; ZERO_STRUCT(key); status = dcerpc_winreg_OpenHKLM(b, frame, NULL, access_mask, &tmp_hive_hnd, &result); /* * print no error messages if it is a read only open * and key does not exist * error still gets returned */ if (access_mask == REG_KEY_READ && W_ERROR_EQUAL(result, WERR_BADFILE)) { goto error; } if (!(NT_STATUS_IS_OK(status))) { d_fprintf(stderr, _("Failed to open hive: %s\n"), nt_errstr(status)); goto error; } if (!W_ERROR_IS_OK(result)) { d_fprintf(stderr, _("Failed to open hive: %s\n"), win_errstr(result)); goto error; } key.name = confpath; status = dcerpc_winreg_OpenKey(b, frame, &tmp_hive_hnd, key, 0, access_mask, &tmp_key_hnd, &result); /* * print no error messages if it is a read only open * and key does not exist * error still gets returned */ if (access_mask == REG_KEY_READ && W_ERROR_EQUAL(result, WERR_BADFILE)) { goto error; } if (!(NT_STATUS_IS_OK(status))) { d_fprintf(stderr, _("Failed to open smbconf key: %s\n"), nt_errstr(status)); dcerpc_winreg_CloseKey(b, frame, &tmp_hive_hnd, &_werr); goto error; } if (!(W_ERROR_IS_OK(result))) { d_fprintf(stderr, _("Failed to open smbconf key: %s\n"), win_errstr(result)); dcerpc_winreg_CloseKey(b, frame, &tmp_hive_hnd, &_werr); goto error; } *hive_hnd = tmp_hive_hnd; *key_hnd = tmp_key_hnd; error: TALLOC_FREE(frame); *werr = result; return status; } static NTSTATUS rpc_conf_listshares_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 ) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR werr = WERR_OK; WERROR _werr; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* key info */ struct policy_handle hive_hnd, key_hnd; uint32_t num_subkeys; uint32_t i; const char **subkeys = NULL; ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); if (argc != 0 || c->display_usage) { rpc_conf_listshares_usage(c, argc, argv); status = NT_STATUS_INVALID_PARAMETER; 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; } status = dcerpc_winreg_enum_keys(frame, b, &key_hnd, &num_subkeys, &subkeys, &werr); if (!(NT_STATUS_IS_OK(status))) { d_fprintf(stderr, _("Failed to enumerate keys: %s\n"), nt_errstr(status)); goto error; } if (!(W_ERROR_IS_OK(werr))) { d_fprintf(stderr, _("Failed to enumerate keys: %s\n"), win_errstr(werr)); goto error; } for (i = 0; i < num_subkeys; i++) { d_printf("%s\n", subkeys[i]); } error: if (!(W_ERROR_IS_OK(werr))) { status = werror_to_ntstatus(werr); } dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr); TALLOC_FREE(frame); return status;; } static NTSTATUS rpc_conf_delshare_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 ) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR werr = WERR_OK; WERROR _werr; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* key info */ struct policy_handle hive_hnd, key_hnd; ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); if (argc != 1 || c->display_usage) { rpc_conf_delshare_usage(c, argc, argv); status = NT_STATUS_INVALID_PARAMETER; goto error; } status = rpc_conf_open_conf(frame, b, REG_KEY_ALL, &hive_hnd, &key_hnd, &werr); if (!(NT_STATUS_IS_OK(status))) { goto error; } if (!(W_ERROR_IS_OK(werr))) { goto error; } status = dcerpc_winreg_delete_subkeys_recursive(frame, b, &key_hnd, REG_KEY_ALL, argv[0], &werr); if (!NT_STATUS_IS_OK(status)) { d_fprintf(stderr, "winreg_delete_subkeys: Could not delete key %s: %s\n", argv[0], nt_errstr(status)); goto error; } if (W_ERROR_EQUAL(werr, WERR_BADFILE)){ d_fprintf(stderr, _("ERROR: Key does not exist\n")); } if (!W_ERROR_IS_OK(werr)) { d_fprintf(stderr, "winreg_delete_subkeys: Could not delete key %s: %s\n", argv[0], win_errstr(werr)); goto error; } error: if (!(W_ERROR_IS_OK(werr))) { status = werror_to_ntstatus(werr); } dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr); TALLOC_FREE(frame); return status; } static NTSTATUS rpc_conf_list_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 ) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR werr = WERR_OK; WERROR _werr; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* key info */ struct policy_handle hive_hnd, key_hnd; uint32_t num_subkeys; uint32_t i; struct smbconf_service *shares; const char **subkeys = NULL; ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); if (argc != 0 || c->display_usage) { rpc_conf_list_usage(c, argc, argv); status = NT_STATUS_INVALID_PARAMETER; 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; } status = dcerpc_winreg_enum_keys(frame, b, &key_hnd, &num_subkeys, &subkeys, &werr); if (!(NT_STATUS_IS_OK(status))) { d_fprintf(stderr, _("Failed to enumerate keys: %s\n"), nt_errstr(status)); goto error; } if (!(W_ERROR_IS_OK(werr))) { d_fprintf(stderr, _("Failed to enumerate keys: %s\n"), win_errstr(werr)); goto error; } if (num_subkeys == 0) { dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr); TALLOC_FREE(frame); return NT_STATUS_OK; } /* get info from each subkey */ shares = talloc_zero_array(frame, struct smbconf_service, num_subkeys); if (shares == NULL) { werr = WERR_NOMEM; d_fprintf(stderr, _("Failed to create shares: %s\n"), win_errstr(werr)); goto error; } for (i = 0; i < num_subkeys; i++) { /* get each share and place it in the shares array */ status = rpc_conf_get_share(frame, b, &key_hnd, subkeys[i], &shares[i], &werr); if (!(NT_STATUS_IS_OK(status))) { goto error; } if (!(W_ERROR_IS_OK(werr))) { goto error; } } /* print the shares array */ rpc_conf_print_shares(num_subkeys, shares); error: if (!(W_ERROR_IS_OK(werr))) { status = werror_to_ntstatus(werr); } dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr); TALLOC_FREE(frame); return status; } static NTSTATUS rpc_conf_drop_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 ) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR werr = WERR_OK; WERROR _werr; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* key info */ struct policy_handle hive_hnd, key_hnd; const char *keyname = confpath; struct winreg_String wkey, wkeyclass; enum winreg_CreateAction action = REG_ACTION_NONE; ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); if (argc != 0 || c->display_usage) { rpc_conf_drop_usage(c, argc, argv); status = NT_STATUS_INVALID_PARAMETER; goto error; } status = rpc_conf_open_conf(frame, b, REG_KEY_ALL, &hive_hnd, &key_hnd, &werr); if (!(NT_STATUS_IS_OK(status))) { goto error; } if (!(W_ERROR_IS_OK(werr))) { goto error; } status = dcerpc_winreg_delete_subkeys_recursive(frame, b, &hive_hnd, REG_KEY_ALL, keyname, &werr); if (!NT_STATUS_IS_OK(status)) { d_printf("winreg_delete_subkeys: Could not delete key %s: %s\n", keyname, nt_errstr(status)); goto error; } if (!W_ERROR_IS_OK(werr)) { d_printf("winreg_delete_subkeys: Could not delete key %s: %s\n", keyname, win_errstr(werr)); goto error; } wkey.name = keyname; ZERO_STRUCT(wkeyclass); wkeyclass.name = ""; action = REG_ACTION_NONE; status = dcerpc_winreg_CreateKey(b, frame, &hive_hnd, wkey, wkeyclass, 0, REG_KEY_ALL, NULL, &key_hnd, &action, &werr); if (!NT_STATUS_IS_OK(status)) { d_printf("winreg_CreateKey: Could not create smbconf key\n"); goto error; } if (!W_ERROR_IS_OK(werr)) { d_printf("winreg_CreateKey: Could not create smbconf key\n"); goto error; } error: if (!(W_ERROR_IS_OK(werr))) { status = werror_to_ntstatus(werr); } dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_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, struct cli_state *cli, struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, int argc, const char **argv ) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR werr = WERR_OK; WERROR _werr; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* key info */ struct policy_handle hive_hnd, key_hnd; struct smbconf_service *service = NULL; const char *sharename = NULL; ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); if (argc != 1 || c->display_usage) { rpc_conf_showshare_usage(c, argc, argv); status = NT_STATUS_INVALID_PARAMETER; 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; } sharename = talloc_strdup(frame, argv[0]); if (sharename == NULL) { werr = WERR_NOMEM; d_fprintf(stderr, _("Failed to create share: %s\n"), win_errstr(werr)); goto error; } service = talloc(frame, struct smbconf_service); if (service == NULL) { werr = WERR_NOMEM; d_fprintf(stderr, _("Failed to create share: %s\n"), win_errstr(werr)); goto error; } status = rpc_conf_get_share(frame, b, &key_hnd, sharename, service, &werr); if (!(NT_STATUS_IS_OK(status))) { goto error; } if (!(W_ERROR_IS_OK(werr))) { goto error; } rpc_conf_print_shares(1, service); error: if (!(W_ERROR_IS_OK(werr))) { status = werror_to_ntstatus(werr); } dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr); TALLOC_FREE(frame); return status; } static NTSTATUS rpc_conf_getparm_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 ) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR werr = WERR_OK; WERROR _werr; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* key info */ struct policy_handle hive_hnd, key_hnd; struct smbconf_service *service = NULL; bool param_is_set = false; uint32_t param_count; ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); if (argc != 2 || c->display_usage) { rpc_conf_getparm_usage(c, argc, argv); status = NT_STATUS_INVALID_PARAMETER; 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; } service = talloc(frame, struct smbconf_service); status = rpc_conf_get_share(frame, b, &key_hnd, argv[0], service, &werr); if (!(NT_STATUS_IS_OK(status))) { goto error; } if (W_ERROR_EQUAL(werr, WERR_BADFILE)) { d_fprintf(stderr, _("ERROR: Share %s does not exist\n"), argv[0]); goto error; } if (!(W_ERROR_IS_OK(werr))) { goto error; } for (param_count = 0; param_count < service->num_params; param_count++) { /* should includes also be printed? */ if (strcmp(service->param_names[param_count], argv[1]) == 0) { d_printf(_("%s\n"), service->param_values[param_count]); param_is_set = true; } } if (!param_is_set) { d_fprintf(stderr, _("ERROR: Given parameter '%s' has not been set\n"), argv[1]); werr = WERR_BADFILE; goto error; } error: if (!(W_ERROR_IS_OK(werr))) { status = werror_to_ntstatus(werr); } dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr); TALLOC_FREE(frame); return status; } static NTSTATUS rpc_conf_setparm_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 ) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR werr = WERR_OK; WERROR _werr; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* key info */ struct policy_handle hive_hnd, key_hnd, share_hnd; struct winreg_String key, keyclass; enum winreg_CreateAction action = 0; ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); ZERO_STRUCT(share_hnd); ZERO_STRUCT(key); ZERO_STRUCT(keyclass); if (argc != 3 || c->display_usage) { rpc_conf_setparm_usage(c, argc, argv); status = NT_STATUS_INVALID_PARAMETER; 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; } key.name = argv[0]; keyclass.name = ""; status = dcerpc_winreg_CreateKey(b, frame, &key_hnd, key, keyclass, 0, REG_KEY_READ, NULL, &share_hnd, &action, &werr); if (!(NT_STATUS_IS_OK(status))) { d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"), argv[0], nt_errstr(status)); goto error; } if (!W_ERROR_IS_OK(werr)) { d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"), argv[0], win_errstr(werr)); goto error; } switch (action) { case REG_ACTION_NONE: werr = WERR_CREATE_FAILED; d_fprintf(stderr, _("ERROR: Could not create share key '%s'\n%s\n"), argv[0], win_errstr(werr)); goto error; case REG_CREATED_NEW_KEY: DEBUG(5, ("net rpc conf setparm:" "createkey created %s\n", argv[0])); break; case REG_OPENED_EXISTING_KEY: DEBUG(5, ("net rpc conf setparm:" "createkey opened existing %s\n", argv[0])); /* delete posibly existing value */ status = rpc_conf_del_value(frame, b, &key_hnd, argv[0], argv[1], &werr); if (!(NT_STATUS_IS_OK(status))) { goto error; } if (!(W_ERROR_IS_OK(werr))) { goto error; } break; } const char *canon_valname; const char *canon_valstr; /* check if parameter is valid for writing */ if (!lp_canonicalize_parameter_with_value(argv[1], argv[2], &canon_valname, &canon_valstr)) { if (canon_valname == NULL) { d_fprintf(stderr, "invalid parameter '%s' given\n", argv[1]); } else { d_fprintf(stderr, "invalid value '%s' given for " "parameter '%s'\n", argv[1], argv[2]); } werr = WERR_INVALID_PARAM; goto error; } if (rpc_conf_reg_valname_forbidden(canon_valname)) { d_fprintf(stderr, "Parameter '%s' not allowed in registry.\n", canon_valname); werr = WERR_INVALID_PARAM; goto error; } if (!strequal(argv[0], "global") && lp_parameter_is_global(argv[1])) { d_fprintf(stderr, "Global parameter '%s' not allowed in " "service definition ('%s').\n", canon_valname, argv[0]); werr = WERR_INVALID_PARAM; goto error; } /* set the parameter */ status = dcerpc_winreg_set_sz(frame, b, &share_hnd, argv[1], argv[2], &werr); if (!(NT_STATUS_IS_OK(status))) { d_fprintf(stderr, "ERROR: Could not set parameter '%s'" " with value %s\n %s\n", argv[1], argv[2], nt_errstr(status)); goto error; } if (!(W_ERROR_IS_OK(werr))) { d_fprintf(stderr, "ERROR: Could not set parameter '%s'" " with value %s\n %s\n", argv[1], argv[2], win_errstr(werr)); goto error; } error: if (!(W_ERROR_IS_OK(werr))) { status = werror_to_ntstatus(werr); } dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &share_hnd, &_werr); TALLOC_FREE(frame); return status; } static NTSTATUS rpc_conf_delparm_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 ) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR werr = WERR_OK; WERROR _werr; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* key info */ struct policy_handle hive_hnd, key_hnd; ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); if (argc != 2 || c->display_usage) { rpc_conf_delparm_usage(c, argc, argv); status = NT_STATUS_INVALID_PARAMETER; 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; } status = rpc_conf_del_value(frame, b, &key_hnd, argv[0], argv[1], &werr); error: if (!(W_ERROR_IS_OK(werr))) { status = werror_to_ntstatus(werr); } dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr); TALLOC_FREE(frame); return status; } static NTSTATUS rpc_conf_getincludes_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 ) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR werr = WERR_OK; WERROR _werr; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* key info */ struct policy_handle hive_hnd, key_hnd; struct smbconf_service *service = NULL; uint32_t param_count; ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); if (argc != 1 || c->display_usage) { rpc_conf_getincludes_usage(c, argc, argv); status = NT_STATUS_INVALID_PARAMETER; 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; } service = talloc(frame, struct smbconf_service); status = rpc_conf_get_share(frame, b, &key_hnd, argv[0], service, &werr); if (!(NT_STATUS_IS_OK(status))) { goto error; } if (!(W_ERROR_IS_OK(werr))) { goto error; } for (param_count = 0; param_count < service->num_params; param_count++) { if (strcmp(service->param_names[param_count], "include") == 0) { d_printf(_("%s = %s\n"), service->param_names[param_count], service->param_values[param_count]); } } error: if (!(W_ERROR_IS_OK(werr))) { status = werror_to_ntstatus(werr); } dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr); TALLOC_FREE(frame); return status; } static NTSTATUS rpc_conf_delincludes_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 ) { TALLOC_CTX *frame = talloc_stackframe(); NTSTATUS status = NT_STATUS_OK; WERROR werr = WERR_OK; WERROR _werr; struct dcerpc_binding_handle *b = pipe_hnd->binding_handle; /* key info */ struct policy_handle hive_hnd, key_hnd; ZERO_STRUCT(hive_hnd); ZERO_STRUCT(key_hnd); if (argc != 1 || c->display_usage) { rpc_conf_delincludes_usage(c, argc, argv); status = NT_STATUS_INVALID_PARAMETER; goto error; } /* try REG_KEY_WRITE */ 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; } status = rpc_conf_del_value(frame, b, &key_hnd, argv[0], "includes", &werr); error: if (!(W_ERROR_IS_OK(werr))) { status = werror_to_ntstatus(werr); } dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr); dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr); TALLOC_FREE(frame); return status; } static int rpc_conf_drop(struct net_context *c, int argc, const char **argv) { return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, rpc_conf_drop_internal, argc, argv ); } static int rpc_conf_showshare(struct net_context *c, int argc, const char **argv) { return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, rpc_conf_showshare_internal, argc, argv ); } static int rpc_conf_listshares(struct net_context *c, int argc, const char **argv) { return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, rpc_conf_listshares_internal, argc, argv ); } static int rpc_conf_list(struct net_context *c, int argc, const char **argv) { return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, rpc_conf_list_internal, argc, argv ); } static int rpc_conf_delshare(struct net_context *c, int argc, const char **argv) { return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, rpc_conf_delshare_internal, argc, argv ); } static int rpc_conf_getparm(struct net_context *c, int argc, const char **argv) { return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, rpc_conf_getparm_internal, argc, argv ); } static int rpc_conf_setparm(struct net_context *c, int argc, const char **argv) { return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, rpc_conf_setparm_internal, argc, argv ); } static int rpc_conf_delparm(struct net_context *c, int argc, const char **argv) { return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, rpc_conf_delparm_internal, argc, argv ); } static int rpc_conf_getincludes(struct net_context *c, int argc, const char **argv) { return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, rpc_conf_getincludes_internal, argc, argv ); } static int rpc_conf_setincludes(struct net_context *c, int argc, const char **argv) { d_printf("Function not yet implemented\n"); return 0; } static int rpc_conf_delincludes(struct net_context *c, int argc, const char **argv) { return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0, rpc_conf_delincludes_internal, argc, argv ); } /* function calls */ int net_rpc_conf(struct net_context *c, int argc, const char **argv) { struct functable func_table[] = { { "list", rpc_conf_list, NET_TRANSPORT_RPC, N_("Dump the complete remote configuration in smb.conf like " "format."), N_("net rpc conf list\n" " Dump the complete remote configuration in smb.conf " "like format.") }, { "listshares", rpc_conf_listshares, NET_TRANSPORT_RPC, N_("List the remote share names."), N_("net rpc conf list\n" " List the remote share names.") }, { "drop", rpc_conf_drop, NET_TRANSPORT_RPC, N_("Delete the complete remote configuration."), N_("net rpc conf drop\n" " Delete the complete remote configuration.") }, { "showshare", rpc_conf_showshare, NET_TRANSPORT_RPC, N_("Show the definition of a remote share."), N_("net rpc conf showshare\n" " Show the definition of a remote share.") }, { "delshare", rpc_conf_delshare, NET_TRANSPORT_RPC, N_("Delete a remote share."), N_("net rpc conf delshare\n" " Delete a remote share.") }, { "getparm", rpc_conf_getparm, NET_TRANSPORT_RPC, N_("Retrieve the value of a parameter."), N_("net rpc conf getparm\n" " Retrieve the value of a parameter.") }, { "setparm", rpc_conf_setparm, NET_TRANSPORT_RPC, N_("Store a parameter."), N_("net rpc conf setparm\n" " Store a parameter.") }, { "delparm", rpc_conf_delparm, NET_TRANSPORT_RPC, N_("Delete a parameter."), N_("net rpc conf delparm\n" " Delete a parameter.") }, { "getincludes", rpc_conf_getincludes, NET_TRANSPORT_RPC, N_("Show the includes of a share definition."), N_("net rpc conf getincludes\n" " Show the includes of a share definition.") }, { "setincludes", rpc_conf_setincludes, NET_TRANSPORT_RPC, N_("Set includes for a share."), N_("net rpc conf setincludes\n" " Set includes for a share.") }, { "delincludes", rpc_conf_delincludes, NET_TRANSPORT_RPC, N_("Delete includes from a share definition."), N_("net rpc conf delincludes\n" " Delete includes from a share definition.") }, {NULL, NULL, 0, NULL, NULL} }; return net_run_function(c, argc, argv, "net rpc conf", func_table); }