2 * Samba Unix/Linux SMB client library
3 * Distributed SMB/CIFS Server Management Utility
4 * Local configuration interface
5 * Copyright (C) Vicentiu Ciorbaru 2011
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 * This is an interface to Samba's configuration.
24 * This tool supports local as well as remote interaction via rpc
25 * with the configuration stored in the registry.
30 #include "utils/net.h"
31 #include "rpc_client/cli_pipe.h"
32 #include "../librpc/gen_ndr/ndr_samr_c.h"
33 #include "rpc_client/init_samr.h"
34 #include "../librpc/gen_ndr/ndr_winreg_c.h"
35 #include "../libcli/registry/util_reg.h"
36 #include "rpc_client/cli_winreg.h"
37 #include "../lib/smbconf/smbconf.h"
39 /* internal functions */
40 /**********************************************************
44 **********************************************************/
45 const char confpath[100] = "Software\\Samba\\smbconf";
47 static int rpc_conf_list_usage(struct net_context *c, int argc,
50 d_printf("%s net rpc conf list\n", _("Usage:"));
54 static int rpc_conf_listshares_usage(struct net_context *c, int argc,
57 d_printf("%s net rpc conf listshares\n", _("Usage:"));
61 static int rpc_conf_delshare_usage(struct net_context *c, int argc,
66 _("net rpc conf delshare <sharename>\n"));
70 static int rpc_conf_showshare_usage(struct net_context *c, int argc,
75 _("net rpc conf showshare <sharename>\n"));
79 static int rpc_conf_drop_usage(struct net_context *c, int argc,
82 d_printf("%s\nnet rpc conf drop\n", _("Usage:"));
86 static NTSTATUS rpc_conf_get_share(TALLOC_CTX *mem_ctx,
87 struct dcerpc_binding_handle *b,
88 struct policy_handle *parent_hnd,
89 const char *share_name,
90 struct smbconf_service *share,
93 TALLOC_CTX *frame = talloc_stackframe();
95 NTSTATUS status = NT_STATUS_OK;
96 WERROR result = WERR_OK;
98 struct policy_handle child_hnd;
99 int32_t includes_cnt, includes_idx = -1;
100 uint32_t num_vals, i, param_cnt = 0;
101 const char **val_names;
102 enum winreg_Type *types;
104 struct winreg_String key;
105 const char **multi_s = NULL;
106 const char *s = NULL;
107 struct smbconf_service tmp_share;
109 ZERO_STRUCT(tmp_share);
111 key.name = share_name;
112 status = dcerpc_winreg_OpenKey(b, frame, parent_hnd, key, 0,
113 REG_KEY_READ, &child_hnd, &result);
115 if (!(NT_STATUS_IS_OK(status))) {
116 d_fprintf(stderr, _("Failed to open subkey: %s\n"),
120 if (!(W_ERROR_IS_OK(result))) {
121 d_fprintf(stderr, _("Failed to open subkey: %s\n"),
125 /* get all the info from the share key */
126 status = dcerpc_winreg_enumvals(frame,
135 if (!(NT_STATUS_IS_OK(status))) {
136 d_fprintf(stderr, _("Failed to enumerate values: %s\n"),
140 if (!(W_ERROR_IS_OK(result))) {
141 d_fprintf(stderr, _("Failed to enumerate values: %s\n"),
145 /* check for includes */
146 for (i = 0; i < num_vals; i++) {
147 if (strcmp(val_names[i], "includes") == 0){
148 if (!pull_reg_multi_sz(frame,
154 _("Failed to enumerate values: %s\n"),
161 /* count the number of includes */
163 if (includes_idx != -1) {
164 for (includes_cnt = 0;
165 multi_s[includes_cnt] != NULL;
168 /* place the name of the share in the smbconf_service struct */
169 tmp_share.name = talloc_strdup(frame, share_name);
170 if (tmp_share.name == NULL) {
172 d_fprintf(stderr, _("Failed to create share: %s\n"),
176 /* place the number of parameters in the smbconf_service struct */
177 tmp_share.num_params = num_vals;
178 if (includes_idx != -1) {
179 tmp_share.num_params = num_vals + includes_cnt - 1;
181 /* allocate memory for the param_names and param_values lists */
182 tmp_share.param_names = talloc_zero_array(frame, char *, tmp_share.num_params);
183 if (tmp_share.param_names == NULL) {
185 d_fprintf(stderr, _("Failed to create share: %s\n"),
189 tmp_share.param_values = talloc_zero_array(frame, char *, tmp_share.num_params);
190 if (tmp_share.param_values == NULL) {
192 d_fprintf(stderr, _("Failed to create share: %s\n"),
196 /* place all params except includes */
197 for (i = 0; i < num_vals; i++) {
198 if (strcmp(val_names[i], "includes") != 0) {
199 if (!pull_reg_sz(frame, &data[i], &s)) {
202 _("Failed to enumerate values: %s\n"),
206 /* place param_names */
207 tmp_share.param_names[param_cnt] = talloc_strdup(frame, val_names[i]);
208 if (tmp_share.param_names[param_cnt] == NULL) {
210 d_fprintf(stderr, _("Failed to create share: %s\n"),
215 /* place param_values */
216 tmp_share.param_values[param_cnt++] = talloc_strdup(frame, s);
217 if (tmp_share.param_values[param_cnt - 1] == NULL) {
219 d_fprintf(stderr, _("Failed to create share: %s\n"),
225 /* place the includes last */
226 for (i = 0; i < includes_cnt; i++) {
227 tmp_share.param_names[param_cnt] = talloc_strdup(frame, "include");
228 if (tmp_share.param_names[param_cnt] == NULL) {
230 d_fprintf(stderr, _("Failed to create share: %s\n"),
235 tmp_share.param_values[param_cnt++] = talloc_strdup(frame, multi_s[i]);
236 if (tmp_share.param_values[param_cnt - 1] == NULL) {
238 d_fprintf(stderr, _("Failed to create share: %s\n"),
244 /* move everything to the main memory ctx */
245 for (i = 0; i < param_cnt; i++) {
246 tmp_share.param_names[i] = talloc_move(mem_ctx, &tmp_share.param_names[i]);
247 tmp_share.param_values[i] = talloc_move(mem_ctx, &tmp_share.param_values[i]);
250 tmp_share.name = talloc_move(mem_ctx, &tmp_share.name);
251 tmp_share.param_names = talloc_move(mem_ctx, &tmp_share.param_names);
252 tmp_share.param_values = talloc_move(mem_ctx, &tmp_share.param_values);
257 dcerpc_winreg_CloseKey(b, frame, &child_hnd, &_werr);
263 static int rpc_conf_print_shares(uint32_t num_shares,
264 struct smbconf_service *shares)
267 uint32_t share_count, param_count;
268 const char *indent = "\t";
270 if (num_shares == 0) {
274 for (share_count = 0; share_count < num_shares; share_count++) {
276 if (shares[share_count].name != NULL) {
277 d_printf("[%s]\n", shares[share_count].name);
280 for (param_count = 0;
281 param_count < shares[share_count].num_params;
284 d_printf("%s%s = %s\n",
286 shares[share_count].param_names[param_count],
287 shares[share_count].param_values[param_count]);
295 static NTSTATUS rpc_conf_open_conf(TALLOC_CTX *mem_ctx,
296 struct dcerpc_binding_handle *b,
297 uint32_t access_mask,
298 struct policy_handle *hive_hnd,
299 struct policy_handle *key_hnd,
302 TALLOC_CTX *frame = talloc_stackframe();
303 NTSTATUS status = NT_STATUS_OK;
304 WERROR result = WERR_OK;
306 struct policy_handle tmp_hive_hnd, tmp_key_hnd;
307 struct winreg_String key;
311 status = dcerpc_winreg_OpenHKLM(b, frame, NULL,
312 access_mask, &tmp_hive_hnd, &result);
315 * print no error messages if it is a read only open
316 * and key does not exist
317 * error still gets returned
320 if (access_mask == REG_KEY_READ &&
321 W_ERROR_EQUAL(result, WERR_BADFILE))
326 if (!(NT_STATUS_IS_OK(status))) {
327 d_fprintf(stderr, _("Failed to open hive: %s\n"),
331 if (!W_ERROR_IS_OK(result)) {
332 d_fprintf(stderr, _("Failed to open hive: %s\n"),
338 status = dcerpc_winreg_OpenKey(b, frame, &tmp_hive_hnd, key, 0,
339 access_mask, &tmp_key_hnd, &result);
342 * print no error messages if it is a read only open
343 * and key does not exist
344 * error still gets returned
347 if (access_mask == REG_KEY_READ &&
348 W_ERROR_EQUAL(result, WERR_BADFILE))
353 if (!(NT_STATUS_IS_OK(status))) {
354 d_fprintf(stderr, _("Failed to open smbconf key: %s\n"),
356 dcerpc_winreg_CloseKey(b, frame, &tmp_hive_hnd, &_werr);
359 if (!(W_ERROR_IS_OK(result))) {
360 d_fprintf(stderr, _("Failed to open smbconf key: %s\n"),
362 dcerpc_winreg_CloseKey(b, frame, &tmp_hive_hnd, &_werr);
366 *hive_hnd = tmp_hive_hnd;
367 *key_hnd = tmp_key_hnd;
376 static NTSTATUS rpc_conf_listshares_internal(struct net_context *c,
377 const struct dom_sid *domain_sid,
378 const char *domain_name,
379 struct cli_state *cli,
380 struct rpc_pipe_client *pipe_hnd,
386 TALLOC_CTX *frame = talloc_stackframe();
387 NTSTATUS status = NT_STATUS_OK;
388 WERROR werr = WERR_OK;
391 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
394 struct policy_handle hive_hnd, key_hnd;
395 uint32_t num_subkeys;
397 const char **subkeys = NULL;
400 ZERO_STRUCT(hive_hnd);
401 ZERO_STRUCT(key_hnd);
404 if (argc != 0 || c->display_usage) {
405 rpc_conf_listshares_usage(c, argc, argv);
406 status = NT_STATUS_INVALID_PARAMETER;
411 status = rpc_conf_open_conf(frame,
418 if (!(NT_STATUS_IS_OK(status))) {
422 if (!(W_ERROR_IS_OK(werr))) {
426 status = dcerpc_winreg_enum_keys(frame,
433 if (!(NT_STATUS_IS_OK(status))) {
434 d_fprintf(stderr, _("Failed to enumerate keys: %s\n"),
439 if (!(W_ERROR_IS_OK(werr))) {
440 d_fprintf(stderr, _("Failed to enumerate keys: %s\n"),
445 for (i = 0; i < num_subkeys; i++) {
446 d_printf("%s\n", subkeys[i]);
450 if (!(W_ERROR_IS_OK(werr))) {
451 status = werror_to_ntstatus(werr);
454 dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
455 dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
461 static NTSTATUS rpc_conf_delshare_internal(struct net_context *c,
462 const struct dom_sid *domain_sid,
463 const char *domain_name,
464 struct cli_state *cli,
465 struct rpc_pipe_client *pipe_hnd,
471 TALLOC_CTX *frame = talloc_stackframe();
472 NTSTATUS status = NT_STATUS_OK;
473 WERROR werr = WERR_OK;
476 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
479 struct policy_handle hive_hnd, key_hnd;
481 ZERO_STRUCT(hive_hnd);
482 ZERO_STRUCT(key_hnd);
485 if (argc != 1 || c->display_usage) {
486 rpc_conf_delshare_usage(c, argc, argv);
487 status = NT_STATUS_INVALID_PARAMETER;
491 status = rpc_conf_open_conf(frame,
498 if (!(NT_STATUS_IS_OK(status))) {
502 if (!(W_ERROR_IS_OK(werr))) {
506 status = dcerpc_winreg_delete_subkeys_recursive(frame,
513 if (!NT_STATUS_IS_OK(status)) {
515 "winreg_delete_subkeys: Could not delete key %s: %s\n",
516 argv[0], nt_errstr(status));
520 if (W_ERROR_EQUAL(werr, WERR_BADFILE)){
521 d_fprintf(stderr, _("ERROR: Key does not exist\n"));
525 if (!W_ERROR_IS_OK(werr)) {
527 "winreg_delete_subkeys: Could not delete key %s: %s\n",
528 argv[0], win_errstr(werr));
533 if (!(W_ERROR_IS_OK(werr))) {
534 status = werror_to_ntstatus(werr);
537 dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
538 dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
545 static NTSTATUS rpc_conf_list_internal(struct net_context *c,
546 const struct dom_sid *domain_sid,
547 const char *domain_name,
548 struct cli_state *cli,
549 struct rpc_pipe_client *pipe_hnd,
555 TALLOC_CTX *frame = talloc_stackframe();
556 NTSTATUS status = NT_STATUS_OK;
557 WERROR werr = WERR_OK;
560 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
563 struct policy_handle hive_hnd, key_hnd;
564 uint32_t num_subkeys;
566 struct smbconf_service *shares;
567 const char **subkeys = NULL;
570 ZERO_STRUCT(hive_hnd);
571 ZERO_STRUCT(key_hnd);
574 if (argc != 0 || c->display_usage) {
575 rpc_conf_list_usage(c, argc, argv);
576 status = NT_STATUS_INVALID_PARAMETER;
580 status = rpc_conf_open_conf(frame,
587 if (!(NT_STATUS_IS_OK(status))) {
591 if (!(W_ERROR_IS_OK(werr))) {
595 status = dcerpc_winreg_enum_keys(frame,
602 if (!(NT_STATUS_IS_OK(status))) {
603 d_fprintf(stderr, _("Failed to enumerate keys: %s\n"),
608 if (!(W_ERROR_IS_OK(werr))) {
609 d_fprintf(stderr, _("Failed to enumerate keys: %s\n"),
614 if (num_subkeys == 0) {
615 dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
616 dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
621 /* get info from each subkey */
622 shares = talloc_zero_array(frame, struct smbconf_service, num_subkeys);
623 if (shares == NULL) {
625 d_fprintf(stderr, _("Failed to create shares: %s\n"),
631 for (i = 0; i < num_subkeys; i++) {
632 /* get each share and place it in the shares array */
633 status = rpc_conf_get_share(frame,
639 if (!(NT_STATUS_IS_OK(status))) {
642 if (!(W_ERROR_IS_OK(werr))) {
647 /* print the shares array */
648 rpc_conf_print_shares(num_subkeys, shares);
651 if (!(W_ERROR_IS_OK(werr))) {
652 status = werror_to_ntstatus(werr);
655 dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
656 dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
663 static NTSTATUS rpc_conf_drop_internal(struct net_context *c,
664 const struct dom_sid *domain_sid,
665 const char *domain_name,
666 struct cli_state *cli,
667 struct rpc_pipe_client *pipe_hnd,
672 TALLOC_CTX *frame = talloc_stackframe();
673 NTSTATUS status = NT_STATUS_OK;
674 WERROR werr = WERR_OK;
677 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
680 struct policy_handle hive_hnd, key_hnd;
681 const char *keyname = confpath;
682 struct winreg_String wkey, wkeyclass;
683 enum winreg_CreateAction action = REG_ACTION_NONE;
686 ZERO_STRUCT(hive_hnd);
687 ZERO_STRUCT(key_hnd);
690 if (argc != 0 || c->display_usage) {
691 rpc_conf_drop_usage(c, argc, argv);
692 status = NT_STATUS_INVALID_PARAMETER;
696 status = rpc_conf_open_conf(frame,
703 if (!(NT_STATUS_IS_OK(status))) {
707 if (!(W_ERROR_IS_OK(werr))) {
711 status = dcerpc_winreg_delete_subkeys_recursive(frame,
718 if (!NT_STATUS_IS_OK(status)) {
719 d_printf("winreg_delete_subkeys: Could not delete key %s: %s\n",
720 keyname, nt_errstr(status));
724 if (!W_ERROR_IS_OK(werr)) {
725 d_printf("winreg_delete_subkeys: Could not delete key %s: %s\n",
726 keyname, win_errstr(werr));
731 ZERO_STRUCT(wkeyclass);
733 action = REG_ACTION_NONE;
735 status = dcerpc_winreg_CreateKey(b,
747 if (!NT_STATUS_IS_OK(status)) {
748 d_printf("winreg_CreateKey: Could not create smbconf key\n");
752 if (!W_ERROR_IS_OK(werr)) {
753 d_printf("winreg_CreateKey: Could not create smbconf key\n");
759 if (!(W_ERROR_IS_OK(werr))) {
760 status = werror_to_ntstatus(werr);
763 dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
764 dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
770 static NTSTATUS rpc_conf_showshare_internal(struct net_context *c,
771 const struct dom_sid *domain_sid,
772 const char *domain_name,
773 struct cli_state *cli,
774 struct rpc_pipe_client *pipe_hnd,
779 TALLOC_CTX *frame = talloc_stackframe();
780 NTSTATUS status = NT_STATUS_OK;
781 WERROR werr = WERR_OK;
784 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
787 struct policy_handle hive_hnd, key_hnd;
788 struct smbconf_service *service = NULL;
789 const char *sharename = NULL;
792 ZERO_STRUCT(hive_hnd);
793 ZERO_STRUCT(key_hnd);
796 if (argc != 1 || c->display_usage) {
797 rpc_conf_showshare_usage(c, argc, argv);
798 status = NT_STATUS_INVALID_PARAMETER;
802 status = rpc_conf_open_conf(frame,
809 if (!(NT_STATUS_IS_OK(status))) {
813 if (!(W_ERROR_IS_OK(werr))) {
817 sharename = talloc_strdup(frame, argv[0]);
818 if (sharename == NULL) {
820 d_fprintf(stderr, _("Failed to create share: %s\n"),
825 service = talloc(frame, struct smbconf_service);
826 if (service == NULL) {
828 d_fprintf(stderr, _("Failed to create share: %s\n"),
833 status = rpc_conf_get_share(frame,
840 if (!(NT_STATUS_IS_OK(status))) {
843 if (!(W_ERROR_IS_OK(werr))) {
847 rpc_conf_print_shares(1, service);
850 if (!(W_ERROR_IS_OK(werr))) {
851 status = werror_to_ntstatus(werr);
854 dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
855 dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
861 static int rpc_conf_drop(struct net_context *c, int argc,
864 return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
865 rpc_conf_drop_internal, argc, argv );
869 static int rpc_conf_showshare(struct net_context *c, int argc,
872 return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
873 rpc_conf_showshare_internal, argc, argv );
876 static int rpc_conf_listshares(struct net_context *c, int argc,
879 return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
880 rpc_conf_listshares_internal, argc, argv );
883 static int rpc_conf_list(struct net_context *c, int argc,
886 return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
887 rpc_conf_list_internal, argc, argv );
890 static int rpc_conf_delshare(struct net_context *c, int argc,
893 return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
894 rpc_conf_delshare_internal, argc, argv );
897 static int rpc_conf_getparm(struct net_context *c, int argc,
904 int net_rpc_conf(struct net_context *c, int argc,
907 struct functable func_table[] = {
912 N_("Dump the complete remote configuration in smb.conf like "
914 N_("net rpc conf list\n"
915 " Dump the complete remote configuration in smb.conf "
923 N_("List the remote share names."),
924 N_("net rpc conf list\n"
925 " List the remote share names.")
932 N_("Delete the complete remote configuration."),
933 N_("net rpc conf drop\n"
934 " Delete the complete remote configuration.")
941 N_("Show the definition of a remote share."),
942 N_("net rpc conf showshare\n"
943 " Show the definition of a remote share.")
950 N_("Delete a remote share."),
951 N_("net rpc conf delshare\n"
952 " Delete a remote share.")
958 N_("Retrieve the value of a parameter."),
959 N_("net rpc conf getparm\n"
960 " Retrieve the value of a parameter.")
962 {NULL, NULL, 0, NULL, NULL}
965 return net_run_function(c, argc, argv, "net rpc conf", func_table);