s3:trusts_util: pass dcname to trust_pw_change()
[Samba.git] / source3 / utils / net_rpc.c
blob80536e5ab5eb3c187aaeac22996e84a9d3b0008b
1 /*
2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5 Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
6 Copyright (C) 2004,2008 Guenther Deschner (gd@samba.org)
7 Copyright (C) 2005 Jeremy Allison (jra@samba.org)
8 Copyright (C) 2006 Jelmer Vernooij (jelmer@samba.org)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include "includes.h"
24 #include "utils/net.h"
25 #include "rpc_client/cli_pipe.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../librpc/gen_ndr/ndr_samr_c.h"
28 #include "rpc_client/cli_samr.h"
29 #include "rpc_client/init_samr.h"
30 #include "../librpc/gen_ndr/ndr_lsa_c.h"
31 #include "rpc_client/cli_lsarpc.h"
32 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
33 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
34 #include "../librpc/gen_ndr/ndr_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_initshutdown_c.h"
36 #include "../librpc/gen_ndr/ndr_winreg_c.h"
37 #include "secrets.h"
38 #include "lib/netapi/netapi.h"
39 #include "lib/netapi/netapi_net.h"
40 #include "librpc/gen_ndr/libnet_join.h"
41 #include "libnet/libnet_join.h"
42 #include "rpc_client/init_lsa.h"
43 #include "../libcli/security/security.h"
44 #include "libsmb/libsmb.h"
45 #include "libsmb/clirap.h"
46 #include "nsswitch/libwbclient/wbclient.h"
47 #include "passdb.h"
48 #include "../libcli/smb/smbXcli_base.h"
50 static int net_mode_share;
51 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
53 /**
54 * @file net_rpc.c
56 * @brief RPC based subcommands for the 'net' utility.
58 * This file should contain much of the functionality that used to
59 * be found in rpcclient, execpt that the commands should change
60 * less often, and the fucntionality should be sane (the user is not
61 * expected to know a rid/sid before they conduct an operation etc.)
63 * @todo Perhaps eventually these should be split out into a number
64 * of files, as this could get quite big.
65 **/
68 /**
69 * Many of the RPC functions need the domain sid. This function gets
70 * it at the start of every run
72 * @param cli A cli_state already connected to the remote machine
74 * @return The Domain SID of the remote machine.
75 **/
77 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
78 struct dom_sid **domain_sid,
79 const char **domain_name)
81 struct rpc_pipe_client *lsa_pipe = NULL;
82 struct policy_handle pol;
83 NTSTATUS status, result;
84 union lsa_PolicyInformation *info = NULL;
85 struct dcerpc_binding_handle *b;
87 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
88 &lsa_pipe);
89 if (!NT_STATUS_IS_OK(status)) {
90 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
91 return status;
94 b = lsa_pipe->binding_handle;
96 status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
97 SEC_FLAG_MAXIMUM_ALLOWED,
98 &pol);
99 if (!NT_STATUS_IS_OK(status)) {
100 d_fprintf(stderr, "open_policy %s: %s\n",
101 _("failed"),
102 nt_errstr(status));
103 return status;
106 status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
107 &pol,
108 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
109 &info,
110 &result);
111 if (!NT_STATUS_IS_OK(status)) {
112 d_fprintf(stderr, "lsaquery %s: %s\n",
113 _("failed"),
114 nt_errstr(status));
115 return status;
117 if (!NT_STATUS_IS_OK(result)) {
118 d_fprintf(stderr, "lsaquery %s: %s\n",
119 _("failed"),
120 nt_errstr(result));
121 return result;
124 *domain_name = info->account_domain.name.string;
125 *domain_sid = info->account_domain.sid;
127 dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
128 TALLOC_FREE(lsa_pipe);
130 return NT_STATUS_OK;
134 * Run a single RPC command, from start to finish.
136 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
137 * @param conn_flag a NET_FLAG_ combination. Passed to
138 * net_make_ipc_connection.
139 * @param argc Standard main() style argc.
140 * @param argv Standard main() style argv. Initial components are already
141 * stripped.
142 * @return A shell status integer (0 for success).
145 int run_rpc_command(struct net_context *c,
146 struct cli_state *cli_arg,
147 const struct ndr_interface_table *table,
148 int conn_flags,
149 rpc_command_fn fn,
150 int argc,
151 const char **argv)
153 struct cli_state *cli = NULL;
154 struct rpc_pipe_client *pipe_hnd = NULL;
155 TALLOC_CTX *mem_ctx;
156 NTSTATUS nt_status;
157 struct dom_sid *domain_sid;
158 const char *domain_name;
159 int ret = -1;
161 /* make use of cli_state handed over as an argument, if possible */
162 if (!cli_arg) {
163 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
164 if (!NT_STATUS_IS_OK(nt_status)) {
165 DEBUG(1, ("failed to make ipc connection: %s\n",
166 nt_errstr(nt_status)));
167 return -1;
169 } else {
170 cli = cli_arg;
173 if (!cli) {
174 return -1;
177 /* Create mem_ctx */
179 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
180 DEBUG(0, ("talloc_init() failed\n"));
181 goto fail;
184 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
185 &domain_name);
186 if (!NT_STATUS_IS_OK(nt_status)) {
187 goto fail;
190 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
191 if (lp_client_schannel()
192 && (ndr_syntax_id_equal(&table->syntax_id,
193 &ndr_table_netlogon.syntax_id))) {
194 /* Always try and create an schannel netlogon pipe. */
195 TALLOC_FREE(c->netlogon_creds);
196 nt_status = cli_rpc_pipe_open_schannel(
197 cli, c->msg_ctx, table, NCACN_NP,
198 domain_name,
199 &pipe_hnd, c, &c->netlogon_creds);
200 if (!NT_STATUS_IS_OK(nt_status)) {
201 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
202 nt_errstr(nt_status) ));
203 goto fail;
205 } else {
206 if (conn_flags & NET_FLAGS_SEAL) {
207 nt_status = cli_rpc_pipe_open_generic_auth(
208 cli, table,
209 (conn_flags & NET_FLAGS_TCP) ?
210 NCACN_IP_TCP : NCACN_NP,
211 CRED_DONT_USE_KERBEROS,
212 DCERPC_AUTH_TYPE_NTLMSSP,
213 DCERPC_AUTH_LEVEL_PRIVACY,
214 smbXcli_conn_remote_name(cli->conn),
215 lp_workgroup(), c->opt_user_name,
216 c->opt_password, &pipe_hnd);
217 } else {
218 nt_status = cli_rpc_pipe_open_noauth(
219 cli, table,
220 &pipe_hnd);
222 if (!NT_STATUS_IS_OK(nt_status)) {
223 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
224 table->name,
225 nt_errstr(nt_status) ));
226 goto fail;
231 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
233 if (!NT_STATUS_IS_OK(nt_status)) {
234 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
235 } else {
236 ret = 0;
237 DEBUG(5, ("rpc command function succedded\n"));
240 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
241 if (pipe_hnd) {
242 TALLOC_FREE(pipe_hnd);
246 fail:
247 /* close the connection only if it was opened here */
248 if (!cli_arg) {
249 cli_shutdown(cli);
252 talloc_destroy(mem_ctx);
253 return ret;
257 * Force a change of the trust acccount password.
259 * All parameters are provided by the run_rpc_command function, except for
260 * argc, argv which are passed through.
262 * @param domain_sid The domain sid acquired from the remote server.
263 * @param cli A cli_state connected to the server.
264 * @param mem_ctx Talloc context, destroyed on completion of the function.
265 * @param argc Standard main() style argc.
266 * @param argv Standard main() style argv. Initial components are already
267 * stripped.
269 * @return Normal NTSTATUS return.
272 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
273 const struct dom_sid *domain_sid,
274 const char *domain_name,
275 struct cli_state *cli,
276 struct rpc_pipe_client *pipe_hnd,
277 TALLOC_CTX *mem_ctx,
278 int argc,
279 const char **argv)
281 NTSTATUS status;
282 const char *dcname = NULL;
284 if (cli == NULL) {
285 return NT_STATUS_INTERNAL_ERROR;
288 dcname = smbXcli_conn_remote_name(cli->conn);
290 status = trust_pw_change(c->netlogon_creds,
291 c->msg_ctx,
292 pipe_hnd->binding_handle,
293 c->opt_target_workgroup,
294 dcname,
295 true); /* force */
296 if (!NT_STATUS_IS_OK(status)) {
297 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
298 nt_errstr(status));
299 return status;
302 return NT_STATUS_OK;
306 * Force a change of the trust acccount password.
308 * @param argc Standard main() style argc.
309 * @param argv Standard main() style argv. Initial components are already
310 * stripped.
312 * @return A shell status integer (0 for success).
315 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
317 if (c->display_usage) {
318 d_printf( "%s\n"
319 "net rpc changetrustpw\n"
320 " %s\n",
321 _("Usage:"),
322 _("Change the machine trust password"));
323 return 0;
326 return run_rpc_command(c, NULL, &ndr_table_netlogon,
327 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
328 rpc_changetrustpw_internals,
329 argc, argv);
333 * Join a domain, the old way. This function exists to allow
334 * the message to be displayed when oldjoin was explicitly
335 * requested, but not when it was implied by "net rpc join".
337 * This uses 'machinename' as the inital password, and changes it.
339 * The password should be created with 'server manager' or equiv first.
341 * @param argc Standard main() style argc.
342 * @param argv Standard main() style argv. Initial components are already
343 * stripped.
345 * @return A shell status integer (0 for success).
348 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
350 struct libnet_JoinCtx *r = NULL;
351 TALLOC_CTX *mem_ctx;
352 WERROR werr;
353 const char *domain = lp_workgroup(); /* FIXME */
354 bool modify_config = lp_config_backend_is_registry();
355 enum netr_SchannelType sec_chan_type;
356 char *pw = NULL;
358 if (c->display_usage) {
359 d_printf("Usage:\n"
360 "net rpc oldjoin\n"
361 " Join a domain the old way\n");
362 return 0;
365 mem_ctx = talloc_init("net_rpc_oldjoin");
366 if (!mem_ctx) {
367 return -1;
370 werr = libnet_init_JoinCtx(mem_ctx, &r);
371 if (!W_ERROR_IS_OK(werr)) {
372 goto fail;
376 check what type of join - if the user want's to join as
377 a BDC, the server must agree that we are a BDC.
379 if (argc >= 0) {
380 sec_chan_type = get_sec_channel_type(argv[0]);
381 } else {
382 sec_chan_type = get_sec_channel_type(NULL);
385 if (!c->msg_ctx) {
386 d_fprintf(stderr, _("Could not initialise message context. "
387 "Try running as root\n"));
388 werr = WERR_ACCESS_DENIED;
389 goto fail;
392 pw = talloc_strndup(r, lp_netbios_name(), 14);
393 if (pw == NULL) {
394 werr = WERR_NOT_ENOUGH_MEMORY;
395 goto fail;
398 r->in.msg_ctx = c->msg_ctx;
399 r->in.domain_name = domain;
400 r->in.secure_channel_type = sec_chan_type;
401 r->in.dc_name = c->opt_host;
402 r->in.admin_account = "";
403 r->in.admin_password = strlower_talloc(r, pw);
404 if (r->in.admin_password == NULL) {
405 werr = WERR_NOT_ENOUGH_MEMORY;
406 goto fail;
408 r->in.debug = true;
409 r->in.modify_config = modify_config;
410 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
411 WKSSVC_JOIN_FLAGS_JOIN_UNSECURE |
412 WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
414 werr = libnet_Join(mem_ctx, r);
415 if (!W_ERROR_IS_OK(werr)) {
416 goto fail;
419 /* Check the short name of the domain */
421 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
422 d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE());
423 d_printf("domain name obtained from the server.\n");
424 d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name);
425 d_printf("You should set \"workgroup = %s\" in %s.\n",
426 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
429 d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name);
431 if (r->out.dns_domain_name) {
432 d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name,
433 r->out.dns_domain_name);
434 } else {
435 d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name,
436 r->out.netbios_domain_name);
439 /* print out informative error string in case there is one */
440 if (r->out.error_string != NULL) {
441 d_printf("%s\n", r->out.error_string);
444 TALLOC_FREE(mem_ctx);
446 return 0;
448 fail:
449 if (c->opt_flags & NET_FLAGS_EXPECT_FALLBACK) {
450 goto cleanup;
453 /* issue an overall failure message at the end. */
454 d_fprintf(stderr, _("Failed to join domain: %s\n"),
455 r && r->out.error_string ? r->out.error_string :
456 get_friendly_werror_msg(werr));
458 cleanup:
459 TALLOC_FREE(mem_ctx);
461 return -1;
465 * check that a join is OK
467 * @return A shell status integer (0 for success)
470 int net_rpc_testjoin(struct net_context *c, int argc, const char **argv)
472 NTSTATUS status;
473 TALLOC_CTX *mem_ctx;
474 const char *domain = c->opt_target_workgroup;
475 const char *dc = c->opt_host;
477 if (c->display_usage) {
478 d_printf("Usage\n"
479 "net rpc testjoin\n"
480 " Test if a join is OK\n");
481 return 0;
484 mem_ctx = talloc_init("net_rpc_testjoin");
485 if (!mem_ctx) {
486 return -1;
489 if (!dc) {
490 struct netr_DsRGetDCNameInfo *info;
492 if (!c->msg_ctx) {
493 d_fprintf(stderr, _("Could not initialise message context. "
494 "Try running as root\n"));
495 talloc_destroy(mem_ctx);
496 return -1;
499 status = dsgetdcname(mem_ctx,
500 c->msg_ctx,
501 domain,
502 NULL,
503 NULL,
504 DS_RETURN_DNS_NAME,
505 &info);
506 if (!NT_STATUS_IS_OK(status)) {
507 talloc_destroy(mem_ctx);
508 return -1;
511 dc = strip_hostname(info->dc_unc);
514 /* Display success or failure */
515 status = libnet_join_ok(c->msg_ctx,
516 c->opt_workgroup,
518 c->opt_kerberos);
519 if (!NT_STATUS_IS_OK(status)) {
520 fprintf(stderr,"Join to domain '%s' is not valid: %s\n",
521 domain, nt_errstr(status));
522 talloc_destroy(mem_ctx);
523 return -1;
526 printf("Join to '%s' is OK\n",domain);
527 talloc_destroy(mem_ctx);
529 return 0;
533 * Join a domain using the administrator username and password
535 * @param argc Standard main() style argc
536 * @param argc Standard main() style argv. Initial components are already
537 * stripped. Currently not used.
538 * @return A shell status integer (0 for success)
542 static int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
544 struct libnet_JoinCtx *r = NULL;
545 TALLOC_CTX *mem_ctx;
546 WERROR werr;
547 const char *domain = lp_workgroup(); /* FIXME */
548 bool modify_config = lp_config_backend_is_registry();
549 enum netr_SchannelType sec_chan_type;
551 if (c->display_usage) {
552 d_printf("Usage:\n"
553 "net rpc join\n"
554 " Join a domain the new way\n");
555 return 0;
558 mem_ctx = talloc_init("net_rpc_join_newstyle");
559 if (!mem_ctx) {
560 return -1;
563 werr = libnet_init_JoinCtx(mem_ctx, &r);
564 if (!W_ERROR_IS_OK(werr)) {
565 goto fail;
569 check what type of join - if the user want's to join as
570 a BDC, the server must agree that we are a BDC.
572 if (argc >= 0) {
573 sec_chan_type = get_sec_channel_type(argv[0]);
574 } else {
575 sec_chan_type = get_sec_channel_type(NULL);
578 if (!c->msg_ctx) {
579 d_fprintf(stderr, _("Could not initialise message context. "
580 "Try running as root\n"));
581 werr = WERR_ACCESS_DENIED;
582 goto fail;
585 r->in.msg_ctx = c->msg_ctx;
586 r->in.domain_name = domain;
587 r->in.secure_channel_type = sec_chan_type;
588 r->in.dc_name = c->opt_host;
589 r->in.admin_account = c->opt_user_name;
590 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
591 r->in.debug = true;
592 r->in.use_kerberos = c->opt_kerberos;
593 r->in.modify_config = modify_config;
594 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
595 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
596 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
598 werr = libnet_Join(mem_ctx, r);
599 if (!W_ERROR_IS_OK(werr)) {
600 goto fail;
603 /* Check the short name of the domain */
605 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
606 d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE());
607 d_printf("domain name obtained from the server.\n");
608 d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name);
609 d_printf("You should set \"workgroup = %s\" in %s.\n",
610 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
613 d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name);
615 if (r->out.dns_domain_name) {
616 d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name,
617 r->out.dns_domain_name);
618 } else {
619 d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name,
620 r->out.netbios_domain_name);
623 /* print out informative error string in case there is one */
624 if (r->out.error_string != NULL) {
625 d_printf("%s\n", r->out.error_string);
628 TALLOC_FREE(mem_ctx);
630 return 0;
632 fail:
633 /* issue an overall failure message at the end. */
634 d_printf("Failed to join domain: %s\n",
635 r && r->out.error_string ? r->out.error_string :
636 get_friendly_werror_msg(werr));
638 TALLOC_FREE(mem_ctx);
640 return -1;
644 * 'net rpc join' entrypoint.
645 * @param argc Standard main() style argc.
646 * @param argv Standard main() style argv. Initial components are already
647 * stripped
649 * Main 'net_rpc_join()' (where the admin username/password is used) is
650 * in net_rpc_join.c.
651 * Try to just change the password, but if that doesn't work, use/prompt
652 * for a username/password.
655 int net_rpc_join(struct net_context *c, int argc, const char **argv)
657 int ret;
659 if (c->display_usage) {
660 d_printf("%s\n%s",
661 _("Usage:"),
662 _("net rpc join -U <username>[%%password] <type>\n"
663 " Join a domain\n"
664 " username\tName of the admin user"
665 " password\tPassword of the admin user, will "
666 "prompt if not specified\n"
667 " type\tCan be one of the following:\n"
668 "\t\tMEMBER\tJoin as member server (default)\n"
669 "\t\tBDC\tJoin as BDC\n"
670 "\t\tPDC\tJoin as PDC\n"));
671 return 0;
674 if (lp_server_role() == ROLE_STANDALONE) {
675 d_printf(_("cannot join as standalone machine\n"));
676 return -1;
679 if (strlen(lp_netbios_name()) > 15) {
680 d_printf(_("Our netbios name can be at most 15 chars long, "
681 "\"%s\" is %u chars long\n"),
682 lp_netbios_name(), (unsigned int)strlen(lp_netbios_name()));
683 return -1;
686 c->opt_flags |= NET_FLAGS_EXPECT_FALLBACK;
687 ret = net_rpc_oldjoin(c, argc, argv);
688 c->opt_flags &= ~NET_FLAGS_EXPECT_FALLBACK;
689 if (ret == 0) {
690 return 0;
693 return net_rpc_join_newstyle(c, argc, argv);
697 * display info about a rpc domain
699 * All parameters are provided by the run_rpc_command function, except for
700 * argc, argv which are passed through.
702 * @param domain_sid The domain sid acquired from the remote server
703 * @param cli A cli_state connected to the server.
704 * @param mem_ctx Talloc context, destroyed on completion of the function.
705 * @param argc Standard main() style argc.
706 * @param argv Standard main() style argv. Initial components are already
707 * stripped.
709 * @return Normal NTSTATUS return.
712 NTSTATUS rpc_info_internals(struct net_context *c,
713 const struct dom_sid *domain_sid,
714 const char *domain_name,
715 struct cli_state *cli,
716 struct rpc_pipe_client *pipe_hnd,
717 TALLOC_CTX *mem_ctx,
718 int argc,
719 const char **argv)
721 struct policy_handle connect_pol, domain_pol;
722 NTSTATUS status, result;
723 union samr_DomainInfo *info = NULL;
724 fstring sid_str;
725 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
727 sid_to_fstring(sid_str, domain_sid);
729 /* Get sam policy handle */
730 status = dcerpc_samr_Connect2(b, mem_ctx,
731 pipe_hnd->desthost,
732 MAXIMUM_ALLOWED_ACCESS,
733 &connect_pol,
734 &result);
735 if (!NT_STATUS_IS_OK(status)) {
736 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
737 nt_errstr(status));
738 goto done;
741 if (!NT_STATUS_IS_OK(result)) {
742 status = result;
743 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
744 nt_errstr(result));
745 goto done;
748 /* Get domain policy handle */
749 status = dcerpc_samr_OpenDomain(b, mem_ctx,
750 &connect_pol,
751 MAXIMUM_ALLOWED_ACCESS,
752 discard_const_p(struct dom_sid2, domain_sid),
753 &domain_pol,
754 &result);
755 if (!NT_STATUS_IS_OK(status)) {
756 d_fprintf(stderr, _("Could not open domain: %s\n"),
757 nt_errstr(status));
758 goto done;
760 if (!NT_STATUS_IS_OK(result)) {
761 status = result;
762 d_fprintf(stderr, _("Could not open domain: %s\n"),
763 nt_errstr(result));
764 goto done;
767 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
768 &domain_pol,
770 &info,
771 &result);
772 if (!NT_STATUS_IS_OK(status)) {
773 goto done;
775 status = result;
776 if (NT_STATUS_IS_OK(result)) {
777 d_printf(_("Domain Name: %s\n"),
778 info->general.domain_name.string);
779 d_printf(_("Domain SID: %s\n"), sid_str);
780 d_printf(_("Sequence number: %llu\n"),
781 (unsigned long long)info->general.sequence_num);
782 d_printf(_("Num users: %u\n"), info->general.num_users);
783 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
784 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
787 done:
788 return status;
792 * 'net rpc info' entrypoint.
793 * @param argc Standard main() style argc.
794 * @param argv Standard main() style argv. Initial components are already
795 * stripped.
798 int net_rpc_info(struct net_context *c, int argc, const char **argv)
800 if (c->display_usage) {
801 d_printf( "%s\n"
802 "net rpc info\n"
803 " %s\n",
804 _("Usage:"),
805 _("Display information about the domain"));
806 return 0;
809 return run_rpc_command(c, NULL, &ndr_table_samr,
810 NET_FLAGS_PDC, rpc_info_internals,
811 argc, argv);
815 * Fetch domain SID into the local secrets.tdb.
817 * All parameters are provided by the run_rpc_command function, except for
818 * argc, argv which are passed through.
820 * @param domain_sid The domain sid acquired from the remote server.
821 * @param cli A cli_state connected to the server.
822 * @param mem_ctx Talloc context, destroyed on completion of the function.
823 * @param argc Standard main() style argc.
824 * @param argv Standard main() style argv. Initial components are already
825 * stripped.
827 * @return Normal NTSTATUS return.
830 static NTSTATUS rpc_getsid_internals(struct net_context *c,
831 const struct dom_sid *domain_sid,
832 const char *domain_name,
833 struct cli_state *cli,
834 struct rpc_pipe_client *pipe_hnd,
835 TALLOC_CTX *mem_ctx,
836 int argc,
837 const char **argv)
839 fstring sid_str;
841 sid_to_fstring(sid_str, domain_sid);
842 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
843 sid_str, domain_name);
845 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
846 DEBUG(0,("Can't store domain SID\n"));
847 return NT_STATUS_UNSUCCESSFUL;
850 return NT_STATUS_OK;
854 * 'net rpc getsid' entrypoint.
855 * @param argc Standard main() style argc.
856 * @param argv Standard main() style argv. Initial components are already
857 * stripped.
860 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
862 int conn_flags = NET_FLAGS_PDC;
864 if (!c->opt_user_specified) {
865 conn_flags |= NET_FLAGS_ANONYMOUS;
868 if (c->display_usage) {
869 d_printf( "%s\n"
870 "net rpc getsid\n"
871 " %s\n",
872 _("Usage:"),
873 _("Fetch domain SID into local secrets.tdb"));
874 return 0;
877 return run_rpc_command(c, NULL, &ndr_table_samr,
878 conn_flags,
879 rpc_getsid_internals,
880 argc, argv);
883 /****************************************************************************/
886 * Basic usage function for 'net rpc user'.
887 * @param argc Standard main() style argc.
888 * @param argv Standard main() style argv. Initial components are already
889 * stripped.
892 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
894 return net_user_usage(c, argc, argv);
898 * Add a new user to a remote RPC server.
900 * @param argc Standard main() style argc.
901 * @param argv Standard main() style argv. Initial components are already
902 * stripped.
904 * @return A shell status integer (0 for success).
907 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
909 NET_API_STATUS status;
910 struct USER_INFO_1 info1;
911 uint32_t parm_error = 0;
913 if (argc < 1 || c->display_usage) {
914 rpc_user_usage(c, argc, argv);
915 return 0;
918 ZERO_STRUCT(info1);
920 info1.usri1_name = argv[0];
921 if (argc == 2) {
922 info1.usri1_password = argv[1];
925 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
927 if (status != 0) {
928 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
929 argv[0], libnetapi_get_error_string(c->netapi_ctx,
930 status));
931 return -1;
932 } else {
933 d_printf(_("Added user '%s'.\n"), argv[0]);
936 return 0;
940 * Rename a user on a remote RPC server.
942 * @param argc Standard main() style argc.
943 * @param argv Standard main() style argv. Initial components are already
944 * stripped.
946 * @return A shell status integer (0 for success).
949 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
951 NET_API_STATUS status;
952 struct USER_INFO_0 u0;
953 uint32_t parm_err = 0;
955 if (argc != 2 || c->display_usage) {
956 rpc_user_usage(c, argc, argv);
957 return 0;
960 u0.usri0_name = argv[1];
962 status = NetUserSetInfo(c->opt_host, argv[0],
963 0, (uint8_t *)&u0, &parm_err);
964 if (status) {
965 d_fprintf(stderr,
966 _("Failed to rename user from %s to %s - %s\n"),
967 argv[0], argv[1],
968 libnetapi_get_error_string(c->netapi_ctx, status));
969 } else {
970 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
973 return status;
977 * Set a user's primary group
979 * @param argc Standard main() style argc.
980 * @param argv Standard main() style argv. Initial components are already
981 * stripped.
983 * @return A shell status integer (0 for success).
986 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
987 const char **argv)
989 NET_API_STATUS status;
990 uint8_t *buffer;
991 struct GROUP_INFO_2 *g2;
992 struct USER_INFO_1051 u1051;
993 uint32_t parm_err = 0;
995 if (argc != 2 || c->display_usage) {
996 rpc_user_usage(c, argc, argv);
997 return 0;
1000 status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
1001 if (status) {
1002 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
1003 argv[1],
1004 libnetapi_get_error_string(c->netapi_ctx, status));
1005 return status;
1007 g2 = (struct GROUP_INFO_2 *)buffer;
1009 u1051.usri1051_primary_group_id = g2->grpi2_group_id;
1011 NetApiBufferFree(buffer);
1013 status = NetUserSetInfo(c->opt_host, argv[0], 1051,
1014 (uint8_t *)&u1051, &parm_err);
1015 if (status) {
1016 d_fprintf(stderr,
1017 _("Failed to set user's primary group %s to %s - "
1018 "%s\n"), argv[0], argv[1],
1019 libnetapi_get_error_string(c->netapi_ctx, status));
1020 } else {
1021 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
1022 argv[1]);
1024 return status;
1028 * Delete a user from a remote RPC server.
1030 * @param argc Standard main() style argc.
1031 * @param argv Standard main() style argv. Initial components are already
1032 * stripped.
1034 * @return A shell status integer (0 for success).
1037 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
1039 NET_API_STATUS status;
1041 if (argc < 1 || c->display_usage) {
1042 rpc_user_usage(c, argc, argv);
1043 return 0;
1046 status = NetUserDel(c->opt_host, argv[0]);
1048 if (status != 0) {
1049 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
1050 argv[0],
1051 libnetapi_get_error_string(c->netapi_ctx, status));
1052 return -1;
1053 } else {
1054 d_printf(_("Deleted user '%s'.\n"), argv[0]);
1057 return 0;
1061 * Set a user's password on a remote RPC server.
1063 * @param argc Standard main() style argc.
1064 * @param argv Standard main() style argv. Initial components are already
1065 * stripped.
1067 * @return A shell status integer (0 for success).
1070 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
1072 NET_API_STATUS status;
1073 char *prompt = NULL;
1074 struct USER_INFO_1003 u1003;
1075 uint32_t parm_err = 0;
1076 int ret;
1078 if (argc < 1 || c->display_usage) {
1079 rpc_user_usage(c, argc, argv);
1080 return 0;
1083 if (argv[1]) {
1084 u1003.usri1003_password = argv[1];
1085 } else {
1086 char pwd[256] = {0};
1087 ret = asprintf(&prompt, _("Enter new password for %s:"),
1088 argv[0]);
1089 if (ret == -1) {
1090 return -1;
1093 ret = samba_getpass(prompt, pwd, sizeof(pwd), false, false);
1094 SAFE_FREE(prompt);
1095 if (ret < 0) {
1096 return -1;
1099 u1003.usri1003_password = talloc_strdup(c, pwd);
1100 if (u1003.usri1003_password == NULL) {
1101 return -1;
1105 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
1107 /* Display results */
1108 if (status != 0) {
1109 d_fprintf(stderr,
1110 _("Failed to set password for '%s' with error: %s.\n"),
1111 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1112 status));
1113 return -1;
1116 return 0;
1120 * List a user's groups from a remote RPC server.
1122 * @param argc Standard main() style argc.
1123 * @param argv Standard main() style argv. Initial components are already
1124 * stripped.
1126 * @return A shell status integer (0 for success)
1129 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
1132 NET_API_STATUS status;
1133 struct GROUP_USERS_INFO_0 *u0 = NULL;
1134 uint32_t entries_read = 0;
1135 uint32_t total_entries = 0;
1136 int i;
1139 if (argc < 1 || c->display_usage) {
1140 rpc_user_usage(c, argc, argv);
1141 return 0;
1144 status = NetUserGetGroups(c->opt_host,
1145 argv[0],
1147 (uint8_t **)(void *)&u0,
1148 (uint32_t)-1,
1149 &entries_read,
1150 &total_entries);
1151 if (status != 0) {
1152 d_fprintf(stderr,
1153 _("Failed to get groups for '%s' with error: %s.\n"),
1154 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1155 status));
1156 return -1;
1159 for (i=0; i < entries_read; i++) {
1160 printf("%s\n", u0->grui0_name);
1161 u0++;
1164 return 0;
1168 * List users on a remote RPC server.
1170 * All parameters are provided by the run_rpc_command function, except for
1171 * argc, argv which are passed through.
1173 * @param domain_sid The domain sid acquired from the remote server.
1174 * @param cli A cli_state connected to the server.
1175 * @param mem_ctx Talloc context, destroyed on completion of the function.
1176 * @param argc Standard main() style argc.
1177 * @param argv Standard main() style argv. Initial components are already
1178 * stripped.
1180 * @return Normal NTSTATUS return.
1183 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
1185 NET_API_STATUS status;
1186 uint32_t start_idx=0, num_entries, i, loop_count = 0;
1187 struct NET_DISPLAY_USER *info = NULL;
1188 void *buffer = NULL;
1190 /* Query domain users */
1191 if (c->opt_long_list_entries)
1192 d_printf(_("\nUser name Comment"
1193 "\n-----------------------------\n"));
1194 do {
1195 uint32_t max_entries, max_size;
1197 dcerpc_get_query_dispinfo_params(
1198 loop_count, &max_entries, &max_size);
1200 status = NetQueryDisplayInformation(c->opt_host,
1202 start_idx,
1203 max_entries,
1204 max_size,
1205 &num_entries,
1206 &buffer);
1207 if (status != 0 && status != ERROR_MORE_DATA) {
1208 return status;
1211 info = (struct NET_DISPLAY_USER *)buffer;
1213 for (i = 0; i < num_entries; i++) {
1215 if (c->opt_long_list_entries)
1216 printf("%-21.21s %s\n", info->usri1_name,
1217 info->usri1_comment);
1218 else
1219 printf("%s\n", info->usri1_name);
1220 info++;
1223 NetApiBufferFree(buffer);
1225 loop_count++;
1226 start_idx += num_entries;
1228 } while (status == ERROR_MORE_DATA);
1230 return status;
1234 * 'net rpc user' entrypoint.
1235 * @param argc Standard main() style argc.
1236 * @param argv Standard main() style argv. Initial components are already
1237 * stripped.
1240 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1242 NET_API_STATUS status;
1244 struct functable func[] = {
1246 "add",
1247 rpc_user_add,
1248 NET_TRANSPORT_RPC,
1249 N_("Add specified user"),
1250 N_("net rpc user add\n"
1251 " Add specified user")
1254 "info",
1255 rpc_user_info,
1256 NET_TRANSPORT_RPC,
1257 N_("List domain groups of user"),
1258 N_("net rpc user info\n"
1259 " List domain groups of user")
1262 "delete",
1263 rpc_user_delete,
1264 NET_TRANSPORT_RPC,
1265 N_("Remove specified user"),
1266 N_("net rpc user delete\n"
1267 " Remove specified user")
1270 "password",
1271 rpc_user_password,
1272 NET_TRANSPORT_RPC,
1273 N_("Change user password"),
1274 N_("net rpc user password\n"
1275 " Change user password")
1278 "rename",
1279 rpc_user_rename,
1280 NET_TRANSPORT_RPC,
1281 N_("Rename specified user"),
1282 N_("net rpc user rename\n"
1283 " Rename specified user")
1286 "setprimarygroup",
1287 rpc_user_setprimarygroup,
1288 NET_TRANSPORT_RPC,
1289 "Set a user's primary group",
1290 "net rpc user setprimarygroup\n"
1291 " Set a user's primary group"
1293 {NULL, NULL, 0, NULL, NULL}
1296 status = libnetapi_net_init(&c->netapi_ctx);
1297 if (status != 0) {
1298 return -1;
1300 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1301 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1302 if (c->opt_kerberos) {
1303 libnetapi_set_use_kerberos(c->netapi_ctx);
1306 if (argc == 0) {
1307 if (c->display_usage) {
1308 d_printf( "%s\n"
1309 "net rpc user\n"
1310 " %s\n",
1311 _("Usage:"),
1312 _("List all users"));
1313 net_display_usage_from_functable(func);
1314 return 0;
1317 return rpc_user_list(c, argc, argv);
1320 return net_run_function(c, argc, argv, "net rpc user", func);
1323 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1324 TALLOC_CTX *mem_ctx,
1325 struct rpc_sh_ctx *ctx,
1326 struct rpc_pipe_client *pipe_hnd,
1327 int argc, const char **argv)
1329 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1332 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1333 TALLOC_CTX *mem_ctx,
1334 struct rpc_sh_ctx *ctx,
1335 struct rpc_pipe_client *pipe_hnd,
1336 int argc, const char **argv)
1338 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1341 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1342 TALLOC_CTX *mem_ctx,
1343 struct rpc_sh_ctx *ctx,
1344 struct rpc_pipe_client *pipe_hnd,
1345 int argc, const char **argv,
1346 NTSTATUS (*fn)(
1347 struct net_context *c,
1348 TALLOC_CTX *mem_ctx,
1349 struct rpc_sh_ctx *ctx,
1350 struct rpc_pipe_client *pipe_hnd,
1351 struct policy_handle *user_hnd,
1352 int argc, const char **argv))
1354 struct policy_handle connect_pol, domain_pol, user_pol;
1355 NTSTATUS status, result;
1356 struct dom_sid sid;
1357 uint32_t rid;
1358 enum lsa_SidType type;
1359 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1361 if (argc == 0) {
1362 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1363 ctx->whoami);
1364 return NT_STATUS_INVALID_PARAMETER;
1367 ZERO_STRUCT(connect_pol);
1368 ZERO_STRUCT(domain_pol);
1369 ZERO_STRUCT(user_pol);
1371 status = net_rpc_lookup_name(c, mem_ctx, ctx->cli,
1372 argv[0], NULL, NULL, &sid, &type);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1375 nt_errstr(status));
1376 goto done;
1379 if (type != SID_NAME_USER) {
1380 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1381 sid_type_lookup(type));
1382 status = NT_STATUS_NO_SUCH_USER;
1383 goto done;
1386 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1387 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1388 status = NT_STATUS_NO_SUCH_USER;
1389 goto done;
1392 status = dcerpc_samr_Connect2(b, mem_ctx,
1393 pipe_hnd->desthost,
1394 MAXIMUM_ALLOWED_ACCESS,
1395 &connect_pol,
1396 &result);
1397 if (!NT_STATUS_IS_OK(status)) {
1398 goto done;
1400 if (!NT_STATUS_IS_OK(result)) {
1401 status = result;
1402 goto done;
1405 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1406 &connect_pol,
1407 MAXIMUM_ALLOWED_ACCESS,
1408 ctx->domain_sid,
1409 &domain_pol,
1410 &result);
1411 if (!NT_STATUS_IS_OK(status)) {
1412 goto done;
1414 if (!NT_STATUS_IS_OK(result)) {
1415 status = result;
1416 goto done;
1419 status = dcerpc_samr_OpenUser(b, mem_ctx,
1420 &domain_pol,
1421 MAXIMUM_ALLOWED_ACCESS,
1422 rid,
1423 &user_pol,
1424 &result);
1425 if (!NT_STATUS_IS_OK(status)) {
1426 goto done;
1428 if (!NT_STATUS_IS_OK(result)) {
1429 status = result;
1430 goto done;
1433 status = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1435 done:
1436 if (is_valid_policy_hnd(&user_pol)) {
1437 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1439 if (is_valid_policy_hnd(&domain_pol)) {
1440 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1442 if (is_valid_policy_hnd(&connect_pol)) {
1443 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
1445 return status;
1448 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1449 TALLOC_CTX *mem_ctx,
1450 struct rpc_sh_ctx *ctx,
1451 struct rpc_pipe_client *pipe_hnd,
1452 struct policy_handle *user_hnd,
1453 int argc, const char **argv)
1455 NTSTATUS status, result;
1456 union samr_UserInfo *info = NULL;
1457 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1459 if (argc != 0) {
1460 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1461 ctx->whoami);
1462 return NT_STATUS_INVALID_PARAMETER;
1465 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1466 user_hnd,
1468 &info,
1469 &result);
1470 if (!NT_STATUS_IS_OK(status)) {
1471 return status;
1473 if (!NT_STATUS_IS_OK(result)) {
1474 return result;
1477 d_printf(_("user rid: %d, group rid: %d\n"),
1478 info->info21.rid,
1479 info->info21.primary_gid);
1481 return result;
1484 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1485 TALLOC_CTX *mem_ctx,
1486 struct rpc_sh_ctx *ctx,
1487 struct rpc_pipe_client *pipe_hnd,
1488 int argc, const char **argv)
1490 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1491 rpc_sh_user_show_internals);
1494 #define FETCHSTR(name, rec) \
1495 do { if (strequal(ctx->thiscmd, name)) { \
1496 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1497 } while (0);
1499 #define SETSTR(name, rec, flag) \
1500 do { if (strequal(ctx->thiscmd, name)) { \
1501 init_lsa_String(&(info->info21.rec), argv[0]); \
1502 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1503 } while (0);
1505 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1506 TALLOC_CTX *mem_ctx,
1507 struct rpc_sh_ctx *ctx,
1508 struct rpc_pipe_client *pipe_hnd,
1509 struct policy_handle *user_hnd,
1510 int argc, const char **argv)
1512 NTSTATUS status, result;
1513 const char *username;
1514 const char *oldval = "";
1515 union samr_UserInfo *info = NULL;
1516 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1518 if (argc > 1) {
1519 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1520 _("Usage:"), ctx->whoami);
1521 return NT_STATUS_INVALID_PARAMETER;
1524 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1525 user_hnd,
1527 &info,
1528 &result);
1529 if (!NT_STATUS_IS_OK(status)) {
1530 return status;
1532 if (!NT_STATUS_IS_OK(result)) {
1533 return result;
1536 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1538 FETCHSTR("fullname", full_name);
1539 FETCHSTR("homedir", home_directory);
1540 FETCHSTR("homedrive", home_drive);
1541 FETCHSTR("logonscript", logon_script);
1542 FETCHSTR("profilepath", profile_path);
1543 FETCHSTR("description", description);
1545 if (argc == 0) {
1546 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1547 goto done;
1550 if (strcmp(argv[0], "NULL") == 0) {
1551 argv[0] = "";
1554 ZERO_STRUCT(info->info21);
1556 SETSTR("fullname", full_name, FULL_NAME);
1557 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1558 SETSTR("homedrive", home_drive, HOME_DRIVE);
1559 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1560 SETSTR("profilepath", profile_path, PROFILE_PATH);
1561 SETSTR("description", description, DESCRIPTION);
1563 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1564 user_hnd,
1566 info,
1567 &result);
1568 if (!NT_STATUS_IS_OK(status)) {
1569 return status;
1572 status = result;
1574 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1575 ctx->thiscmd, oldval, argv[0]);
1577 done:
1579 return status;
1582 #define HANDLEFLG(name, rec) \
1583 do { if (strequal(ctx->thiscmd, name)) { \
1584 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1585 if (newval) { \
1586 newflags = oldflags | ACB_##rec; \
1587 } else { \
1588 newflags = oldflags & ~ACB_##rec; \
1589 } } } while (0);
1591 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1592 TALLOC_CTX *mem_ctx,
1593 struct rpc_sh_ctx *ctx,
1594 struct rpc_pipe_client *pipe_hnd,
1595 int argc, const char **argv)
1597 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1598 rpc_sh_user_str_edit_internals);
1601 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1602 TALLOC_CTX *mem_ctx,
1603 struct rpc_sh_ctx *ctx,
1604 struct rpc_pipe_client *pipe_hnd,
1605 struct policy_handle *user_hnd,
1606 int argc, const char **argv)
1608 NTSTATUS status, result;
1609 const char *username;
1610 const char *oldval = "unknown";
1611 uint32_t oldflags, newflags;
1612 bool newval;
1613 union samr_UserInfo *info = NULL;
1614 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1616 if ((argc > 1) ||
1617 ((argc == 1) && !strequal(argv[0], "yes") &&
1618 !strequal(argv[0], "no"))) {
1619 /* TRANSATORS: The yes|no here are program keywords. Please do
1620 not translate. */
1621 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1622 ctx->whoami);
1623 return NT_STATUS_INVALID_PARAMETER;
1626 newval = strequal(argv[0], "yes");
1628 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1629 user_hnd,
1631 &info,
1632 &result);
1633 if (!NT_STATUS_IS_OK(status)) {
1634 return status;
1636 if (!NT_STATUS_IS_OK(result)) {
1637 return result;
1640 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1641 oldflags = info->info21.acct_flags;
1642 newflags = info->info21.acct_flags;
1644 HANDLEFLG("disabled", DISABLED);
1645 HANDLEFLG("pwnotreq", PWNOTREQ);
1646 HANDLEFLG("autolock", AUTOLOCK);
1647 HANDLEFLG("pwnoexp", PWNOEXP);
1649 if (argc == 0) {
1650 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1651 oldval);
1652 goto done;
1655 ZERO_STRUCT(info->info21);
1657 info->info21.acct_flags = newflags;
1658 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1660 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1661 user_hnd,
1663 info,
1664 &result);
1665 if (!NT_STATUS_IS_OK(status)) {
1666 goto done;
1668 status = result;
1669 if (NT_STATUS_IS_OK(result)) {
1670 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1671 ctx->thiscmd, oldval, argv[0]);
1674 done:
1676 return status;
1679 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1680 TALLOC_CTX *mem_ctx,
1681 struct rpc_sh_ctx *ctx,
1682 struct rpc_pipe_client *pipe_hnd,
1683 int argc, const char **argv)
1685 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1686 rpc_sh_user_flag_edit_internals);
1689 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1690 TALLOC_CTX *mem_ctx,
1691 struct rpc_sh_ctx *ctx)
1693 static struct rpc_sh_cmd cmds[] = {
1695 { "fullname", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1696 N_("Show/Set a user's full name") },
1698 { "homedir", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1699 N_("Show/Set a user's home directory") },
1701 { "homedrive", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1702 N_("Show/Set a user's home drive") },
1704 { "logonscript", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1705 N_("Show/Set a user's logon script") },
1707 { "profilepath", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1708 N_("Show/Set a user's profile path") },
1710 { "description", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1711 N_("Show/Set a user's description") },
1713 { "disabled", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1714 N_("Show/Set whether a user is disabled") },
1716 { "autolock", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1717 N_("Show/Set whether a user locked out") },
1719 { "pwnotreq", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1720 N_("Show/Set whether a user does not need a password") },
1722 { "pwnoexp", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1723 N_("Show/Set whether a user's password does not expire") },
1725 { NULL, NULL, 0, NULL, NULL }
1728 return cmds;
1731 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1732 TALLOC_CTX *mem_ctx,
1733 struct rpc_sh_ctx *ctx)
1735 static struct rpc_sh_cmd cmds[] = {
1737 { "list", NULL, &ndr_table_samr, rpc_sh_user_list,
1738 N_("List available users") },
1740 { "info", NULL, &ndr_table_samr, rpc_sh_user_info,
1741 N_("List the domain groups a user is member of") },
1743 { "show", NULL, &ndr_table_samr, rpc_sh_user_show,
1744 N_("Show info about a user") },
1746 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1747 N_("Show/Modify a user's fields") },
1749 { NULL, NULL, 0, NULL, NULL }
1752 return cmds;
1755 /****************************************************************************/
1758 * Basic usage function for 'net rpc group'.
1759 * @param argc Standard main() style argc.
1760 * @param argv Standard main() style argv. Initial components are already
1761 * stripped.
1764 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1766 return net_group_usage(c, argc, argv);
1770 * Delete group on a remote RPC server.
1772 * All parameters are provided by the run_rpc_command function, except for
1773 * argc, argv which are passed through.
1775 * @param domain_sid The domain sid acquired from the remote server.
1776 * @param cli A cli_state connected to the server.
1777 * @param mem_ctx Talloc context, destroyed on completion of the function.
1778 * @param argc Standard main() style argc.
1779 * @param argv Standard main() style argv. Initial components are already
1780 * stripped.
1782 * @return Normal NTSTATUS return.
1785 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1786 const struct dom_sid *domain_sid,
1787 const char *domain_name,
1788 struct cli_state *cli,
1789 struct rpc_pipe_client *pipe_hnd,
1790 TALLOC_CTX *mem_ctx,
1791 int argc,
1792 const char **argv)
1794 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1795 bool group_is_primary = false;
1796 NTSTATUS status, result;
1797 uint32_t group_rid;
1798 struct samr_RidAttrArray *rids = NULL;
1799 /* char **names; */
1800 int i;
1801 /* struct samr_RidWithAttribute *user_gids; */
1802 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1804 struct samr_Ids group_rids, name_types;
1805 struct lsa_String lsa_acct_name;
1806 union samr_UserInfo *info = NULL;
1808 if (argc < 1 || c->display_usage) {
1809 rpc_group_usage(c, argc,argv);
1810 return NT_STATUS_OK; /* ok? */
1813 status = dcerpc_samr_Connect2(b, mem_ctx,
1814 pipe_hnd->desthost,
1815 MAXIMUM_ALLOWED_ACCESS,
1816 &connect_pol,
1817 &result);
1818 if (!NT_STATUS_IS_OK(status)) {
1819 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1820 goto done;
1823 if (!NT_STATUS_IS_OK(result)) {
1824 status = result;
1825 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1826 goto done;
1829 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1830 &connect_pol,
1831 MAXIMUM_ALLOWED_ACCESS,
1832 discard_const_p(struct dom_sid2, domain_sid),
1833 &domain_pol,
1834 &result);
1835 if (!NT_STATUS_IS_OK(status)) {
1836 d_fprintf(stderr, _("Request open_domain failed\n"));
1837 goto done;
1840 if (!NT_STATUS_IS_OK(result)) {
1841 status = result;
1842 d_fprintf(stderr, _("Request open_domain failed\n"));
1843 goto done;
1846 init_lsa_String(&lsa_acct_name, argv[0]);
1848 status = dcerpc_samr_LookupNames(b, mem_ctx,
1849 &domain_pol,
1851 &lsa_acct_name,
1852 &group_rids,
1853 &name_types,
1854 &result);
1855 if (!NT_STATUS_IS_OK(status)) {
1856 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1857 goto done;
1860 if (!NT_STATUS_IS_OK(result)) {
1861 status = result;
1862 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1863 goto done;
1865 if (group_rids.count != 1) {
1866 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1867 goto done;
1869 if (name_types.count != 1) {
1870 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1871 goto done;
1874 switch (name_types.ids[0])
1876 case SID_NAME_DOM_GRP:
1877 status = dcerpc_samr_OpenGroup(b, mem_ctx,
1878 &domain_pol,
1879 MAXIMUM_ALLOWED_ACCESS,
1880 group_rids.ids[0],
1881 &group_pol,
1882 &result);
1883 if (!NT_STATUS_IS_OK(status)) {
1884 d_fprintf(stderr, _("Request open_group failed"));
1885 goto done;
1888 if (!NT_STATUS_IS_OK(result)) {
1889 status = result;
1890 d_fprintf(stderr, _("Request open_group failed"));
1891 goto done;
1894 group_rid = group_rids.ids[0];
1896 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
1897 &group_pol,
1898 &rids,
1899 &result);
1900 if (!NT_STATUS_IS_OK(status)) {
1901 d_fprintf(stderr,
1902 _("Unable to query group members of %s"),
1903 argv[0]);
1904 goto done;
1907 if (!NT_STATUS_IS_OK(result)) {
1908 status = result;
1909 d_fprintf(stderr,
1910 _("Unable to query group members of %s"),
1911 argv[0]);
1912 goto done;
1915 if (c->opt_verbose) {
1916 d_printf(
1917 _("Domain Group %s (rid: %d) has %d members\n"),
1918 argv[0],group_rid, rids->count);
1921 /* Check if group is anyone's primary group */
1922 for (i = 0; i < rids->count; i++)
1924 status = dcerpc_samr_OpenUser(b, mem_ctx,
1925 &domain_pol,
1926 MAXIMUM_ALLOWED_ACCESS,
1927 rids->rids[i],
1928 &user_pol,
1929 &result);
1930 if (!NT_STATUS_IS_OK(status)) {
1931 d_fprintf(stderr,
1932 _("Unable to open group member %d\n"),
1933 rids->rids[i]);
1934 goto done;
1937 if (!NT_STATUS_IS_OK(result)) {
1938 status = result;
1939 d_fprintf(stderr,
1940 _("Unable to open group member %d\n"),
1941 rids->rids[i]);
1942 goto done;
1945 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1946 &user_pol,
1948 &info,
1949 &result);
1950 if (!NT_STATUS_IS_OK(status)) {
1951 d_fprintf(stderr,
1952 _("Unable to lookup userinfo for group "
1953 "member %d\n"),
1954 rids->rids[i]);
1955 goto done;
1958 if (!NT_STATUS_IS_OK(result)) {
1959 status = result;
1960 d_fprintf(stderr,
1961 _("Unable to lookup userinfo for group "
1962 "member %d\n"),
1963 rids->rids[i]);
1964 goto done;
1967 if (info->info21.primary_gid == group_rid) {
1968 if (c->opt_verbose) {
1969 d_printf(_("Group is primary group "
1970 "of %s\n"),
1971 info->info21.account_name.string);
1973 group_is_primary = true;
1976 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1979 if (group_is_primary) {
1980 d_fprintf(stderr, _("Unable to delete group because "
1981 "some of it's members have it as primary "
1982 "group\n"));
1983 status = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1984 goto done;
1987 /* remove all group members */
1988 for (i = 0; i < rids->count; i++)
1990 if (c->opt_verbose)
1991 d_printf(_("Remove group member %d..."),
1992 rids->rids[i]);
1993 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
1994 &group_pol,
1995 rids->rids[i],
1996 &result);
1997 if (!NT_STATUS_IS_OK(status)) {
1998 goto done;
2000 status = result;
2001 if (NT_STATUS_IS_OK(result)) {
2002 if (c->opt_verbose)
2003 d_printf(_("ok\n"));
2004 } else {
2005 if (c->opt_verbose)
2006 d_printf("%s\n", _("failed"));
2007 goto done;
2011 status = dcerpc_samr_DeleteDomainGroup(b, mem_ctx,
2012 &group_pol,
2013 &result);
2014 if (!NT_STATUS_IS_OK(status)) {
2015 break;
2018 status = result;
2020 break;
2021 /* removing a local group is easier... */
2022 case SID_NAME_ALIAS:
2023 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2024 &domain_pol,
2025 MAXIMUM_ALLOWED_ACCESS,
2026 group_rids.ids[0],
2027 &group_pol,
2028 &result);
2029 if (!NT_STATUS_IS_OK(status)) {
2030 d_fprintf(stderr, _("Request open_alias failed\n"));
2031 goto done;
2033 if (!NT_STATUS_IS_OK(result)) {
2034 status = result;
2035 d_fprintf(stderr, _("Request open_alias failed\n"));
2036 goto done;
2039 status = dcerpc_samr_DeleteDomAlias(b, mem_ctx,
2040 &group_pol,
2041 &result);
2042 if (!NT_STATUS_IS_OK(status)) {
2043 break;
2046 status = result;
2048 break;
2049 default:
2050 d_fprintf(stderr, _("%s is of type %s. This command is only "
2051 "for deleting local or global groups\n"),
2052 argv[0],sid_type_lookup(name_types.ids[0]));
2053 status = NT_STATUS_UNSUCCESSFUL;
2054 goto done;
2057 if (NT_STATUS_IS_OK(status)) {
2058 if (c->opt_verbose)
2059 d_printf(_("Deleted %s '%s'\n"),
2060 sid_type_lookup(name_types.ids[0]), argv[0]);
2061 } else {
2062 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
2063 get_friendly_nt_error_msg(status));
2066 done:
2067 return status;
2071 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
2073 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2074 rpc_group_delete_internals, argc,argv);
2077 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
2079 NET_API_STATUS status;
2080 struct GROUP_INFO_1 info1;
2081 uint32_t parm_error = 0;
2083 if (argc != 1 || c->display_usage) {
2084 rpc_group_usage(c, argc, argv);
2085 return 0;
2088 ZERO_STRUCT(info1);
2090 info1.grpi1_name = argv[0];
2091 if (c->opt_comment && strlen(c->opt_comment) > 0) {
2092 info1.grpi1_comment = c->opt_comment;
2095 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
2097 if (status != 0) {
2098 d_fprintf(stderr,
2099 _("Failed to add group '%s' with error: %s.\n"),
2100 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2101 status));
2102 return -1;
2103 } else {
2104 d_printf(_("Added group '%s'.\n"), argv[0]);
2107 return 0;
2110 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
2112 NET_API_STATUS status;
2113 struct LOCALGROUP_INFO_1 info1;
2114 uint32_t parm_error = 0;
2116 if (argc != 1 || c->display_usage) {
2117 rpc_group_usage(c, argc, argv);
2118 return 0;
2121 ZERO_STRUCT(info1);
2123 info1.lgrpi1_name = argv[0];
2124 if (c->opt_comment && strlen(c->opt_comment) > 0) {
2125 info1.lgrpi1_comment = c->opt_comment;
2128 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
2130 if (status != 0) {
2131 d_fprintf(stderr,
2132 _("Failed to add alias '%s' with error: %s.\n"),
2133 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2134 status));
2135 return -1;
2136 } else {
2137 d_printf(_("Added alias '%s'.\n"), argv[0]);
2140 return 0;
2143 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
2145 if (c->opt_localgroup)
2146 return rpc_alias_add_internals(c, argc, argv);
2148 return rpc_group_add_internals(c, argc, argv);
2151 static NTSTATUS get_sid_from_name(struct cli_state *cli,
2152 TALLOC_CTX *mem_ctx,
2153 const char *name,
2154 struct dom_sid *sid,
2155 enum lsa_SidType *type)
2157 struct dom_sid *sids = NULL;
2158 enum lsa_SidType *types = NULL;
2159 struct rpc_pipe_client *pipe_hnd = NULL;
2160 struct policy_handle lsa_pol;
2161 NTSTATUS status, result;
2162 struct dcerpc_binding_handle *b;
2164 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
2165 &pipe_hnd);
2166 if (!NT_STATUS_IS_OK(status)) {
2167 goto done;
2170 b = pipe_hnd->binding_handle;
2172 status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
2173 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2175 if (!NT_STATUS_IS_OK(status)) {
2176 goto done;
2179 status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
2180 &name, NULL, 1, &sids, &types);
2182 if (NT_STATUS_IS_OK(status)) {
2183 sid_copy(sid, &sids[0]);
2184 *type = types[0];
2187 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
2189 done:
2190 if (pipe_hnd) {
2191 TALLOC_FREE(pipe_hnd);
2194 if (!NT_STATUS_IS_OK(status) && (strncasecmp_m(name, "S-", 2) == 0)) {
2196 /* Try as S-1-5-whatever */
2198 struct dom_sid tmp_sid;
2200 if (string_to_sid(&tmp_sid, name)) {
2201 sid_copy(sid, &tmp_sid);
2202 *type = SID_NAME_UNKNOWN;
2203 status = NT_STATUS_OK;
2207 return status;
2210 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
2211 TALLOC_CTX *mem_ctx,
2212 const struct dom_sid *group_sid,
2213 const char *member)
2215 struct policy_handle connect_pol, domain_pol;
2216 NTSTATUS status, result;
2217 uint32_t group_rid;
2218 struct policy_handle group_pol;
2219 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2221 struct samr_Ids rids, rid_types;
2222 struct lsa_String lsa_acct_name;
2224 struct dom_sid sid;
2226 sid_copy(&sid, group_sid);
2228 if (!sid_split_rid(&sid, &group_rid)) {
2229 return NT_STATUS_UNSUCCESSFUL;
2232 /* Get sam policy handle */
2233 status = dcerpc_samr_Connect2(b, mem_ctx,
2234 pipe_hnd->desthost,
2235 MAXIMUM_ALLOWED_ACCESS,
2236 &connect_pol,
2237 &result);
2238 if (!NT_STATUS_IS_OK(status)) {
2239 return status;
2241 if (!NT_STATUS_IS_OK(result)) {
2242 return result;
2245 /* Get domain policy handle */
2246 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2247 &connect_pol,
2248 MAXIMUM_ALLOWED_ACCESS,
2249 &sid,
2250 &domain_pol,
2251 &result);
2252 if (!NT_STATUS_IS_OK(status)) {
2253 return status;
2255 if (!NT_STATUS_IS_OK(result)) {
2256 return result;
2259 init_lsa_String(&lsa_acct_name, member);
2261 status = dcerpc_samr_LookupNames(b, mem_ctx,
2262 &domain_pol,
2264 &lsa_acct_name,
2265 &rids,
2266 &rid_types,
2267 &result);
2268 if (!NT_STATUS_IS_OK(status)) {
2269 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2270 member);
2271 goto done;
2274 if (!NT_STATUS_IS_OK(result)) {
2275 status = result;
2276 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2277 member);
2278 goto done;
2280 if (rids.count != 1) {
2281 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2282 goto done;
2284 if (rid_types.count != 1) {
2285 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2286 goto done;
2289 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2290 &domain_pol,
2291 MAXIMUM_ALLOWED_ACCESS,
2292 group_rid,
2293 &group_pol,
2294 &result);
2295 if (!NT_STATUS_IS_OK(status)) {
2296 goto done;
2299 if (!NT_STATUS_IS_OK(result)) {
2300 status = result;
2301 goto done;
2304 status = dcerpc_samr_AddGroupMember(b, mem_ctx,
2305 &group_pol,
2306 rids.ids[0],
2307 0x0005, /* unknown flags */
2308 &result);
2309 if (!NT_STATUS_IS_OK(status)) {
2310 goto done;
2313 status = result;
2315 done:
2316 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2317 return status;
2320 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2321 struct cli_state *cli,
2322 TALLOC_CTX *mem_ctx,
2323 const struct dom_sid *alias_sid,
2324 const char *member)
2326 struct policy_handle connect_pol, domain_pol;
2327 NTSTATUS status, result;
2328 uint32_t alias_rid;
2329 struct policy_handle alias_pol;
2330 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2332 struct dom_sid member_sid;
2333 enum lsa_SidType member_type;
2335 struct dom_sid sid;
2337 sid_copy(&sid, alias_sid);
2339 if (!sid_split_rid(&sid, &alias_rid)) {
2340 return NT_STATUS_UNSUCCESSFUL;
2343 result = get_sid_from_name(cli, mem_ctx,
2344 member, &member_sid, &member_type);
2346 if (!NT_STATUS_IS_OK(result)) {
2347 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2348 member);
2349 return result;
2352 /* Get sam policy handle */
2353 status = dcerpc_samr_Connect2(b, mem_ctx,
2354 pipe_hnd->desthost,
2355 MAXIMUM_ALLOWED_ACCESS,
2356 &connect_pol,
2357 &result);
2358 if (!NT_STATUS_IS_OK(status)) {
2359 goto done;
2361 if (!NT_STATUS_IS_OK(result)) {
2362 status = result;
2363 goto done;
2366 /* Get domain policy handle */
2367 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2368 &connect_pol,
2369 MAXIMUM_ALLOWED_ACCESS,
2370 &sid,
2371 &domain_pol,
2372 &result);
2373 if (!NT_STATUS_IS_OK(status)) {
2374 goto done;
2376 if (!NT_STATUS_IS_OK(result)) {
2377 status = result;
2378 goto done;
2381 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2382 &domain_pol,
2383 MAXIMUM_ALLOWED_ACCESS,
2384 alias_rid,
2385 &alias_pol,
2386 &result);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 return status;
2390 if (!NT_STATUS_IS_OK(result)) {
2391 return result;
2394 status = dcerpc_samr_AddAliasMember(b, mem_ctx,
2395 &alias_pol,
2396 &member_sid,
2397 &result);
2398 if (!NT_STATUS_IS_OK(status)) {
2399 return status;
2402 status = result;
2404 done:
2405 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2406 return status;
2409 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2410 const struct dom_sid *domain_sid,
2411 const char *domain_name,
2412 struct cli_state *cli,
2413 struct rpc_pipe_client *pipe_hnd,
2414 TALLOC_CTX *mem_ctx,
2415 int argc,
2416 const char **argv)
2418 struct dom_sid group_sid;
2419 enum lsa_SidType group_type;
2421 if (argc != 2 || c->display_usage) {
2422 d_printf("%s\n%s",
2423 _("Usage:"),
2424 _("net rpc group addmem <group> <member>\n"
2425 " Add a member to a group\n"
2426 " group\tGroup to add member to\n"
2427 " member\tMember to add to group\n"));
2428 return NT_STATUS_UNSUCCESSFUL;
2431 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2432 &group_sid, &group_type))) {
2433 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2434 argv[0]);
2435 return NT_STATUS_UNSUCCESSFUL;
2438 if (group_type == SID_NAME_DOM_GRP) {
2439 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2440 &group_sid, argv[1]);
2442 if (!NT_STATUS_IS_OK(result)) {
2443 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2444 argv[1], argv[0], nt_errstr(result));
2446 return result;
2449 if (group_type == SID_NAME_ALIAS) {
2450 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, cli, mem_ctx,
2451 &group_sid, argv[1]);
2453 if (!NT_STATUS_IS_OK(result)) {
2454 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2455 argv[1], argv[0], nt_errstr(result));
2457 return result;
2460 d_fprintf(stderr, _("Can only add members to global or local groups "
2461 "which %s is not\n"), argv[0]);
2463 return NT_STATUS_UNSUCCESSFUL;
2466 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2468 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2469 rpc_group_addmem_internals,
2470 argc, argv);
2473 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2474 struct rpc_pipe_client *pipe_hnd,
2475 TALLOC_CTX *mem_ctx,
2476 const struct dom_sid *group_sid,
2477 const char *member)
2479 struct policy_handle connect_pol, domain_pol;
2480 NTSTATUS status, result;
2481 uint32_t group_rid;
2482 struct policy_handle group_pol;
2483 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2485 struct samr_Ids rids, rid_types;
2486 struct lsa_String lsa_acct_name;
2488 struct dom_sid sid;
2490 sid_copy(&sid, group_sid);
2492 if (!sid_split_rid(&sid, &group_rid))
2493 return NT_STATUS_UNSUCCESSFUL;
2495 /* Get sam policy handle */
2496 status = dcerpc_samr_Connect2(b, mem_ctx,
2497 pipe_hnd->desthost,
2498 MAXIMUM_ALLOWED_ACCESS,
2499 &connect_pol,
2500 &result);
2501 if (!NT_STATUS_IS_OK(status)) {
2502 return status;
2504 if (!NT_STATUS_IS_OK(result)) {
2505 return result;
2509 /* Get domain policy handle */
2510 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2511 &connect_pol,
2512 MAXIMUM_ALLOWED_ACCESS,
2513 &sid,
2514 &domain_pol,
2515 &result);
2516 if (!NT_STATUS_IS_OK(status)) {
2517 return status;
2519 if (!NT_STATUS_IS_OK(result)) {
2520 return result;
2523 init_lsa_String(&lsa_acct_name, member);
2525 status = dcerpc_samr_LookupNames(b, mem_ctx,
2526 &domain_pol,
2528 &lsa_acct_name,
2529 &rids,
2530 &rid_types,
2531 &result);
2532 if (!NT_STATUS_IS_OK(status)) {
2533 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2534 member);
2535 goto done;
2538 if (!NT_STATUS_IS_OK(result)) {
2539 status = result;
2540 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2541 member);
2542 goto done;
2544 if (rids.count != 1) {
2545 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2546 goto done;
2548 if (rid_types.count != 1) {
2549 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2550 goto done;
2553 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2554 &domain_pol,
2555 MAXIMUM_ALLOWED_ACCESS,
2556 group_rid,
2557 &group_pol,
2558 &result);
2559 if (!NT_STATUS_IS_OK(status)) {
2560 goto done;
2562 if (!NT_STATUS_IS_OK(result)) {
2563 status = result;
2564 goto done;
2567 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2568 &group_pol,
2569 rids.ids[0],
2570 &result);
2571 if (!NT_STATUS_IS_OK(status)) {
2572 goto done;
2575 status = result;
2576 done:
2577 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2578 return status;
2581 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2582 struct cli_state *cli,
2583 TALLOC_CTX *mem_ctx,
2584 const struct dom_sid *alias_sid,
2585 const char *member)
2587 struct policy_handle connect_pol, domain_pol;
2588 NTSTATUS status, result;
2589 uint32_t alias_rid;
2590 struct policy_handle alias_pol;
2591 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2593 struct dom_sid member_sid;
2594 enum lsa_SidType member_type;
2596 struct dom_sid sid;
2598 sid_copy(&sid, alias_sid);
2600 if (!sid_split_rid(&sid, &alias_rid))
2601 return NT_STATUS_UNSUCCESSFUL;
2603 result = get_sid_from_name(cli, mem_ctx,
2604 member, &member_sid, &member_type);
2606 if (!NT_STATUS_IS_OK(result)) {
2607 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2608 member);
2609 return result;
2612 /* Get sam policy handle */
2613 status = dcerpc_samr_Connect2(b, mem_ctx,
2614 pipe_hnd->desthost,
2615 MAXIMUM_ALLOWED_ACCESS,
2616 &connect_pol,
2617 &result);
2618 if (!NT_STATUS_IS_OK(status)) {
2619 goto done;
2621 if (!NT_STATUS_IS_OK(result)) {
2622 status = result;
2623 goto done;
2626 /* Get domain policy handle */
2627 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2628 &connect_pol,
2629 MAXIMUM_ALLOWED_ACCESS,
2630 &sid,
2631 &domain_pol,
2632 &result);
2633 if (!NT_STATUS_IS_OK(status)) {
2634 goto done;
2636 if (!NT_STATUS_IS_OK(result)) {
2637 status = result;
2638 goto done;
2641 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2642 &domain_pol,
2643 MAXIMUM_ALLOWED_ACCESS,
2644 alias_rid,
2645 &alias_pol,
2646 &result);
2647 if (!NT_STATUS_IS_OK(status)) {
2648 return status;
2651 if (!NT_STATUS_IS_OK(result)) {
2652 return result;
2655 status = dcerpc_samr_DeleteAliasMember(b, mem_ctx,
2656 &alias_pol,
2657 &member_sid,
2658 &result);
2660 if (!NT_STATUS_IS_OK(status)) {
2661 return status;
2664 status = result;
2666 done:
2667 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2668 return status;
2671 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2672 const struct dom_sid *domain_sid,
2673 const char *domain_name,
2674 struct cli_state *cli,
2675 struct rpc_pipe_client *pipe_hnd,
2676 TALLOC_CTX *mem_ctx,
2677 int argc,
2678 const char **argv)
2680 struct dom_sid group_sid;
2681 enum lsa_SidType group_type;
2683 if (argc != 2 || c->display_usage) {
2684 d_printf("%s\n%s",
2685 _("Usage:"),
2686 _("net rpc group delmem <group> <member>\n"
2687 " Delete a member from a group\n"
2688 " group\tGroup to delete member from\n"
2689 " member\tMember to delete from group\n"));
2690 return NT_STATUS_UNSUCCESSFUL;
2693 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2694 &group_sid, &group_type))) {
2695 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2696 argv[0]);
2697 return NT_STATUS_UNSUCCESSFUL;
2700 if (group_type == SID_NAME_DOM_GRP) {
2701 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2702 &group_sid, argv[1]);
2704 if (!NT_STATUS_IS_OK(result)) {
2705 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2706 argv[1], argv[0], nt_errstr(result));
2708 return result;
2711 if (group_type == SID_NAME_ALIAS) {
2712 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, cli, mem_ctx,
2713 &group_sid, argv[1]);
2715 if (!NT_STATUS_IS_OK(result)) {
2716 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2717 argv[1], argv[0], nt_errstr(result));
2719 return result;
2722 d_fprintf(stderr, _("Can only delete members from global or local "
2723 "groups which %s is not\n"), argv[0]);
2725 return NT_STATUS_UNSUCCESSFUL;
2728 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2730 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2731 rpc_group_delmem_internals,
2732 argc, argv);
2736 * List groups on a remote RPC server.
2738 * All parameters are provided by the run_rpc_command function, except for
2739 * argc, argv which are passes through.
2741 * @param domain_sid The domain sid acquired from the remote server.
2742 * @param cli A cli_state connected to the server.
2743 * @param mem_ctx Talloc context, destroyed on completion of the function.
2744 * @param argc Standard main() style argc.
2745 * @param argv Standard main() style argv. Initial components are already
2746 * stripped.
2748 * @return Normal NTSTATUS return.
2751 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2752 const struct dom_sid *domain_sid,
2753 const char *domain_name,
2754 struct cli_state *cli,
2755 struct rpc_pipe_client *pipe_hnd,
2756 TALLOC_CTX *mem_ctx,
2757 int argc,
2758 const char **argv)
2760 struct policy_handle connect_pol, domain_pol;
2761 NTSTATUS status, result;
2762 uint32_t start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2763 struct samr_SamArray *groups = NULL;
2764 bool global = false;
2765 bool local = false;
2766 bool builtin = false;
2767 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2769 if (c->display_usage) {
2770 d_printf("%s\n%s",
2771 _("Usage:"),
2772 _("net rpc group list [global] [local] [builtin]\n"
2773 " List groups on RPC server\n"
2774 " global\tList global groups\n"
2775 " local\tList local groups\n"
2776 " builtin\tList builtin groups\n"
2777 " If none of global, local or builtin is "
2778 "specified, all three options are considered "
2779 "set\n"));
2780 return NT_STATUS_OK;
2783 if (argc == 0) {
2784 global = true;
2785 local = true;
2786 builtin = true;
2789 for (i=0; i<argc; i++) {
2790 if (strequal(argv[i], "global"))
2791 global = true;
2793 if (strequal(argv[i], "local"))
2794 local = true;
2796 if (strequal(argv[i], "builtin"))
2797 builtin = true;
2800 /* Get sam policy handle */
2802 status = dcerpc_samr_Connect2(b, mem_ctx,
2803 pipe_hnd->desthost,
2804 MAXIMUM_ALLOWED_ACCESS,
2805 &connect_pol,
2806 &result);
2807 if (!NT_STATUS_IS_OK(status)) {
2808 goto done;
2810 if (!NT_STATUS_IS_OK(result)) {
2811 status = result;
2812 goto done;
2815 /* Get domain policy handle */
2817 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2818 &connect_pol,
2819 MAXIMUM_ALLOWED_ACCESS,
2820 discard_const_p(struct dom_sid2, domain_sid),
2821 &domain_pol,
2822 &result);
2823 if (!NT_STATUS_IS_OK(status)) {
2824 goto done;
2826 if (!NT_STATUS_IS_OK(result)) {
2827 status = result;
2828 goto done;
2831 /* Query domain groups */
2832 if (c->opt_long_list_entries)
2833 d_printf(_("\nGroup name Comment"
2834 "\n-----------------------------\n"));
2835 do {
2836 uint32_t max_size, total_size, returned_size;
2837 union samr_DispInfo info;
2839 if (!global) break;
2841 dcerpc_get_query_dispinfo_params(
2842 loop_count, &max_entries, &max_size);
2844 status = dcerpc_samr_QueryDisplayInfo(b, mem_ctx,
2845 &domain_pol,
2847 start_idx,
2848 max_entries,
2849 max_size,
2850 &total_size,
2851 &returned_size,
2852 &info,
2853 &result);
2854 if (!NT_STATUS_IS_OK(status)) {
2855 goto done;
2857 num_entries = info.info3.count;
2858 start_idx += info.info3.count;
2860 if (!NT_STATUS_IS_OK(result) &&
2861 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2862 break;
2864 for (i = 0; i < num_entries; i++) {
2866 const char *group = NULL;
2867 const char *desc = NULL;
2869 group = info.info3.entries[i].account_name.string;
2870 desc = info.info3.entries[i].description.string;
2872 if (c->opt_long_list_entries)
2873 printf("%-21.21s %-50.50s\n",
2874 group, desc);
2875 else
2876 printf("%s\n", group);
2878 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2879 /* query domain aliases */
2880 start_idx = 0;
2881 do {
2882 if (!local) break;
2884 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2885 &domain_pol,
2886 &start_idx,
2887 &groups,
2888 0xffff,
2889 &num_entries,
2890 &result);
2891 if (!NT_STATUS_IS_OK(status)) {
2892 goto done;
2894 if (!NT_STATUS_IS_OK(result) &&
2895 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2896 break;
2898 for (i = 0; i < num_entries; i++) {
2900 const char *description = NULL;
2902 if (c->opt_long_list_entries) {
2904 struct policy_handle alias_pol;
2905 union samr_AliasInfo *info = NULL;
2906 NTSTATUS _result;
2908 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2909 &domain_pol,
2910 0x8,
2911 groups->entries[i].idx,
2912 &alias_pol,
2913 &_result);
2914 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2915 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2916 &alias_pol,
2918 &info,
2919 &_result);
2920 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2921 status = dcerpc_samr_Close(b, mem_ctx,
2922 &alias_pol,
2923 &_result);
2924 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2925 description = info->description.string;
2931 if (description != NULL) {
2932 printf("%-21.21s %-50.50s\n",
2933 groups->entries[i].name.string,
2934 description);
2935 } else {
2936 printf("%s\n", groups->entries[i].name.string);
2939 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2940 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
2941 /* Get builtin policy handle */
2943 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2944 &connect_pol,
2945 MAXIMUM_ALLOWED_ACCESS,
2946 discard_const_p(struct dom_sid2, &global_sid_Builtin),
2947 &domain_pol,
2948 &result);
2949 if (!NT_STATUS_IS_OK(status)) {
2950 goto done;
2952 if (!NT_STATUS_IS_OK(result)) {
2953 status = result;
2954 goto done;
2957 /* query builtin aliases */
2958 start_idx = 0;
2959 do {
2960 if (!builtin) break;
2962 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2963 &domain_pol,
2964 &start_idx,
2965 &groups,
2966 max_entries,
2967 &num_entries,
2968 &result);
2969 if (!NT_STATUS_IS_OK(status)) {
2970 break;
2972 if (!NT_STATUS_IS_OK(result) &&
2973 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
2974 status = result;
2975 break;
2978 for (i = 0; i < num_entries; i++) {
2980 const char *description = NULL;
2982 if (c->opt_long_list_entries) {
2984 struct policy_handle alias_pol;
2985 union samr_AliasInfo *info = NULL;
2986 NTSTATUS _result;
2988 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2989 &domain_pol,
2990 0x8,
2991 groups->entries[i].idx,
2992 &alias_pol,
2993 &_result);
2994 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2995 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2996 &alias_pol,
2998 &info,
2999 &_result);
3000 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3001 status = dcerpc_samr_Close(b, mem_ctx,
3002 &alias_pol,
3003 &_result);
3004 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3005 description = info->description.string;
3011 if (description != NULL) {
3012 printf("%-21.21s %-50.50s\n",
3013 groups->entries[i].name.string,
3014 description);
3015 } else {
3016 printf("%s\n", groups->entries[i].name.string);
3019 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3021 status = result;
3023 done:
3024 return status;
3027 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
3029 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3030 rpc_group_list_internals,
3031 argc, argv);
3034 static NTSTATUS rpc_list_group_members(struct net_context *c,
3035 struct rpc_pipe_client *pipe_hnd,
3036 TALLOC_CTX *mem_ctx,
3037 const char *domain_name,
3038 const struct dom_sid *domain_sid,
3039 struct policy_handle *domain_pol,
3040 uint32_t rid)
3042 NTSTATUS result, status;
3043 struct policy_handle group_pol;
3044 uint32_t num_members, *group_rids;
3045 int i;
3046 struct samr_RidAttrArray *rids = NULL;
3047 struct lsa_Strings names;
3048 struct samr_Ids types;
3049 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3051 fstring sid_str;
3052 sid_to_fstring(sid_str, domain_sid);
3054 status = dcerpc_samr_OpenGroup(b, mem_ctx,
3055 domain_pol,
3056 MAXIMUM_ALLOWED_ACCESS,
3057 rid,
3058 &group_pol,
3059 &result);
3060 if (!NT_STATUS_IS_OK(status)) {
3061 return status;
3063 if (!NT_STATUS_IS_OK(result)) {
3064 return result;
3067 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
3068 &group_pol,
3069 &rids,
3070 &result);
3071 if (!NT_STATUS_IS_OK(status)) {
3072 return status;
3074 if (!NT_STATUS_IS_OK(result)) {
3075 return result;
3078 num_members = rids->count;
3079 group_rids = rids->rids;
3081 while (num_members > 0) {
3082 int this_time = 512;
3084 if (num_members < this_time)
3085 this_time = num_members;
3087 status = dcerpc_samr_LookupRids(b, mem_ctx,
3088 domain_pol,
3089 this_time,
3090 group_rids,
3091 &names,
3092 &types,
3093 &result);
3094 if (!NT_STATUS_IS_OK(status)) {
3095 return status;
3097 if (!NT_STATUS_IS_OK(result)) {
3098 return result;
3100 if (names.count != this_time) {
3101 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3103 if (types.count != this_time) {
3104 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3106 /* We only have users as members, but make the output
3107 the same as the output of alias members */
3109 for (i = 0; i < this_time; i++) {
3111 if (c->opt_long_list_entries) {
3112 printf("%s-%d %s\\%s %d\n", sid_str,
3113 group_rids[i], domain_name,
3114 names.names[i].string,
3115 SID_NAME_USER);
3116 } else {
3117 printf("%s\\%s\n", domain_name,
3118 names.names[i].string);
3122 num_members -= this_time;
3123 group_rids += 512;
3126 return NT_STATUS_OK;
3129 static NTSTATUS rpc_list_alias_members(struct net_context *c,
3130 struct rpc_pipe_client *pipe_hnd,
3131 struct cli_state *cli,
3132 TALLOC_CTX *mem_ctx,
3133 struct policy_handle *domain_pol,
3134 uint32_t rid)
3136 NTSTATUS result, status;
3137 struct rpc_pipe_client *lsa_pipe;
3138 struct policy_handle alias_pol, lsa_pol;
3139 uint32_t num_members;
3140 struct dom_sid *alias_sids;
3141 char **domains;
3142 char **names;
3143 enum lsa_SidType *types;
3144 int i;
3145 struct lsa_SidArray sid_array;
3146 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3148 status = dcerpc_samr_OpenAlias(b, mem_ctx,
3149 domain_pol,
3150 MAXIMUM_ALLOWED_ACCESS,
3151 rid,
3152 &alias_pol,
3153 &result);
3154 if (!NT_STATUS_IS_OK(status)) {
3155 return status;
3157 if (!NT_STATUS_IS_OK(result)) {
3158 return result;
3161 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
3162 &alias_pol,
3163 &sid_array,
3164 &result);
3165 if (!NT_STATUS_IS_OK(status)) {
3166 d_fprintf(stderr, _("Couldn't list alias members\n"));
3167 return status;
3169 if (!NT_STATUS_IS_OK(result)) {
3170 d_fprintf(stderr, _("Couldn't list alias members\n"));
3171 return result;
3174 num_members = sid_array.num_sids;
3176 if (num_members == 0) {
3177 return NT_STATUS_OK;
3180 result = cli_rpc_pipe_open_noauth(cli,
3181 &ndr_table_lsarpc,
3182 &lsa_pipe);
3183 if (!NT_STATUS_IS_OK(result)) {
3184 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
3185 nt_errstr(result) );
3186 return result;
3189 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
3190 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
3192 if (!NT_STATUS_IS_OK(result)) {
3193 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
3194 TALLOC_FREE(lsa_pipe);
3195 return result;
3198 alias_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
3199 if (!alias_sids) {
3200 d_fprintf(stderr, _("Out of memory\n"));
3201 TALLOC_FREE(lsa_pipe);
3202 return NT_STATUS_NO_MEMORY;
3205 for (i=0; i<num_members; i++) {
3206 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
3209 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
3210 num_members, alias_sids,
3211 &domains, &names, &types);
3213 if (!NT_STATUS_IS_OK(result) &&
3214 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
3215 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
3216 TALLOC_FREE(lsa_pipe);
3217 return result;
3220 for (i = 0; i < num_members; i++) {
3221 fstring sid_str;
3222 sid_to_fstring(sid_str, &alias_sids[i]);
3224 if (c->opt_long_list_entries) {
3225 printf("%s %s\\%s %d\n", sid_str,
3226 domains[i] ? domains[i] : _("*unknown*"),
3227 names[i] ? names[i] : _("*unknown*"), types[i]);
3228 } else {
3229 if (domains[i])
3230 printf("%s\\%s\n", domains[i], names[i]);
3231 else
3232 printf("%s\n", sid_str);
3236 TALLOC_FREE(lsa_pipe);
3237 return NT_STATUS_OK;
3240 static NTSTATUS rpc_group_members_internals(struct net_context *c,
3241 const struct dom_sid *domain_sid,
3242 const char *domain_name,
3243 struct cli_state *cli,
3244 struct rpc_pipe_client *pipe_hnd,
3245 TALLOC_CTX *mem_ctx,
3246 int argc,
3247 const char **argv)
3249 NTSTATUS result, status;
3250 struct policy_handle connect_pol, domain_pol;
3251 struct samr_Ids rids, rid_types;
3252 struct lsa_String lsa_acct_name;
3253 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3255 /* Get sam policy handle */
3257 status = dcerpc_samr_Connect2(b, mem_ctx,
3258 pipe_hnd->desthost,
3259 MAXIMUM_ALLOWED_ACCESS,
3260 &connect_pol,
3261 &result);
3262 if (!NT_STATUS_IS_OK(status)) {
3263 return status;
3265 if (!NT_STATUS_IS_OK(result)) {
3266 return result;
3269 /* Get domain policy handle */
3271 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3272 &connect_pol,
3273 MAXIMUM_ALLOWED_ACCESS,
3274 discard_const_p(struct dom_sid2, domain_sid),
3275 &domain_pol,
3276 &result);
3277 if (!NT_STATUS_IS_OK(status)) {
3278 return status;
3280 if (!NT_STATUS_IS_OK(result)) {
3281 return result;
3284 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
3286 status = dcerpc_samr_LookupNames(b, mem_ctx,
3287 &domain_pol,
3289 &lsa_acct_name,
3290 &rids,
3291 &rid_types,
3292 &result);
3293 if (!NT_STATUS_IS_OK(status)) {
3294 return status;
3297 if (!NT_STATUS_IS_OK(result)) {
3299 /* Ok, did not find it in the global sam, try with builtin */
3301 struct dom_sid sid_Builtin;
3303 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
3305 sid_copy(&sid_Builtin, &global_sid_Builtin);
3307 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3308 &connect_pol,
3309 MAXIMUM_ALLOWED_ACCESS,
3310 &sid_Builtin,
3311 &domain_pol,
3312 &result);
3313 if (!NT_STATUS_IS_OK(status)) {
3314 return status;
3316 if (!NT_STATUS_IS_OK(result)) {
3317 d_fprintf(stderr, _("Couldn't find group %s\n"),
3318 argv[0]);
3319 return result;
3322 status = dcerpc_samr_LookupNames(b, mem_ctx,
3323 &domain_pol,
3325 &lsa_acct_name,
3326 &rids,
3327 &rid_types,
3328 &result);
3329 if (!NT_STATUS_IS_OK(status)) {
3330 return status;
3332 if (!NT_STATUS_IS_OK(result)) {
3333 d_fprintf(stderr, _("Couldn't find group %s\n"),
3334 argv[0]);
3335 return result;
3339 if (rids.count != 1) {
3340 d_fprintf(stderr, _("Couldn't find group %s\n"),
3341 argv[0]);
3342 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3344 if (rid_types.count != 1) {
3345 d_fprintf(stderr, _("Couldn't find group %s\n"),
3346 argv[0]);
3347 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3351 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
3352 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
3353 domain_sid, &domain_pol,
3354 rids.ids[0]);
3357 if (rid_types.ids[0] == SID_NAME_ALIAS) {
3358 return rpc_list_alias_members(c, pipe_hnd, cli, mem_ctx, &domain_pol,
3359 rids.ids[0]);
3362 return NT_STATUS_NO_SUCH_GROUP;
3365 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
3367 if (argc != 1 || c->display_usage) {
3368 return rpc_group_usage(c, argc, argv);
3371 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3372 rpc_group_members_internals,
3373 argc, argv);
3376 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
3378 NET_API_STATUS status;
3379 struct GROUP_INFO_0 g0;
3380 uint32_t parm_err;
3382 if (argc != 2) {
3383 d_printf(_("Usage:\n"));
3384 d_printf("net rpc group rename group newname\n");
3385 return -1;
3388 g0.grpi0_name = argv[1];
3390 status = NetGroupSetInfo(c->opt_host,
3391 argv[0],
3393 (uint8_t *)&g0,
3394 &parm_err);
3396 if (status != 0) {
3397 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
3398 argv[0], libnetapi_get_error_string(c->netapi_ctx,
3399 status));
3400 return -1;
3403 return 0;
3406 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
3408 if (argc != 2 || c->display_usage) {
3409 return rpc_group_usage(c, argc, argv);
3412 return rpc_group_rename_internals(c, argc, argv);
3416 * 'net rpc group' entrypoint.
3417 * @param argc Standard main() style argc.
3418 * @param argv Standard main() style argv. Initial components are already
3419 * stripped.
3422 int net_rpc_group(struct net_context *c, int argc, const char **argv)
3424 NET_API_STATUS status;
3426 struct functable func[] = {
3428 "add",
3429 rpc_group_add,
3430 NET_TRANSPORT_RPC,
3431 N_("Create specified group"),
3432 N_("net rpc group add\n"
3433 " Create specified group")
3436 "delete",
3437 rpc_group_delete,
3438 NET_TRANSPORT_RPC,
3439 N_("Delete specified group"),
3440 N_("net rpc group delete\n"
3441 " Delete specified group")
3444 "addmem",
3445 rpc_group_addmem,
3446 NET_TRANSPORT_RPC,
3447 N_("Add member to group"),
3448 N_("net rpc group addmem\n"
3449 " Add member to group")
3452 "delmem",
3453 rpc_group_delmem,
3454 NET_TRANSPORT_RPC,
3455 N_("Remove member from group"),
3456 N_("net rpc group delmem\n"
3457 " Remove member from group")
3460 "list",
3461 rpc_group_list,
3462 NET_TRANSPORT_RPC,
3463 N_("List groups"),
3464 N_("net rpc group list\n"
3465 " List groups")
3468 "members",
3469 rpc_group_members,
3470 NET_TRANSPORT_RPC,
3471 N_("List group members"),
3472 N_("net rpc group members\n"
3473 " List group members")
3476 "rename",
3477 rpc_group_rename,
3478 NET_TRANSPORT_RPC,
3479 N_("Rename group"),
3480 N_("net rpc group rename\n"
3481 " Rename group")
3483 {NULL, NULL, 0, NULL, NULL}
3486 status = libnetapi_net_init(&c->netapi_ctx);
3487 if (status != 0) {
3488 return -1;
3490 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
3491 libnetapi_set_password(c->netapi_ctx, c->opt_password);
3492 if (c->opt_kerberos) {
3493 libnetapi_set_use_kerberos(c->netapi_ctx);
3496 if (argc == 0) {
3497 if (c->display_usage) {
3498 d_printf(_("Usage:\n"));
3499 d_printf(_("net rpc group\n"
3500 " Alias for net rpc group list global "
3501 "local builtin\n"));
3502 net_display_usage_from_functable(func);
3503 return 0;
3506 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3507 rpc_group_list_internals,
3508 argc, argv);
3511 return net_run_function(c, argc, argv, "net rpc group", func);
3514 /****************************************************************************/
3516 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
3518 return net_share_usage(c, argc, argv);
3522 * Add a share on a remote RPC server.
3524 * @param argc Standard main() style argc.
3525 * @param argv Standard main() style argv. Initial components are already
3526 * stripped.
3528 * @return A shell status integer (0 for success).
3531 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3533 NET_API_STATUS status;
3534 char *sharename;
3535 char *path;
3536 uint32_t type = STYPE_DISKTREE; /* only allow disk shares to be added */
3537 uint32_t num_users=0, perms=0;
3538 char *password=NULL; /* don't allow a share password */
3539 struct SHARE_INFO_2 i2;
3540 uint32_t parm_error = 0;
3542 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3543 return rpc_share_usage(c, argc, argv);
3546 if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
3547 return -1;
3550 path = strchr(sharename, '=');
3551 if (!path) {
3552 return -1;
3555 *path++ = '\0';
3557 i2.shi2_netname = sharename;
3558 i2.shi2_type = type;
3559 i2.shi2_remark = c->opt_comment;
3560 i2.shi2_permissions = perms;
3561 i2.shi2_max_uses = c->opt_maxusers;
3562 i2.shi2_current_uses = num_users;
3563 i2.shi2_path = path;
3564 i2.shi2_passwd = password;
3566 status = NetShareAdd(c->opt_host,
3568 (uint8_t *)&i2,
3569 &parm_error);
3570 if (status != 0) {
3571 printf(_("NetShareAdd failed with: %s\n"),
3572 libnetapi_get_error_string(c->netapi_ctx, status));
3575 return status;
3579 * Delete a share on a remote RPC server.
3581 * @param domain_sid The domain sid acquired from the remote server.
3582 * @param argc Standard main() style argc.
3583 * @param argv Standard main() style argv. Initial components are already
3584 * stripped.
3586 * @return A shell status integer (0 for success).
3588 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3590 if (argc < 1 || c->display_usage) {
3591 return rpc_share_usage(c, argc, argv);
3594 return NetShareDel(c->opt_host, argv[0], 0);
3598 * Formatted print of share info
3600 * @param r pointer to SHARE_INFO_1 to format
3603 static void display_share_info_1(struct net_context *c,
3604 struct SHARE_INFO_1 *r)
3606 if (c->opt_long_list_entries) {
3607 d_printf("%-12s %-8.8s %-50s\n",
3608 r->shi1_netname,
3609 net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3610 r->shi1_remark);
3611 } else {
3612 d_printf("%s\n", r->shi1_netname);
3616 static WERROR get_share_info(struct net_context *c,
3617 struct rpc_pipe_client *pipe_hnd,
3618 TALLOC_CTX *mem_ctx,
3619 uint32_t level,
3620 int argc,
3621 const char **argv,
3622 struct srvsvc_NetShareInfoCtr *info_ctr)
3624 WERROR result;
3625 NTSTATUS status;
3626 union srvsvc_NetShareInfo info;
3627 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3629 /* no specific share requested, enumerate all */
3630 if (argc == 0) {
3632 uint32_t preferred_len = 0xffffffff;
3633 uint32_t total_entries = 0;
3634 uint32_t resume_handle = 0;
3636 info_ctr->level = level;
3638 status = dcerpc_srvsvc_NetShareEnumAll(b, mem_ctx,
3639 pipe_hnd->desthost,
3640 info_ctr,
3641 preferred_len,
3642 &total_entries,
3643 &resume_handle,
3644 &result);
3645 if (!NT_STATUS_IS_OK(status)) {
3646 return ntstatus_to_werror(status);
3648 return result;
3651 /* request just one share */
3652 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
3653 pipe_hnd->desthost,
3654 argv[0],
3655 level,
3656 &info,
3657 &result);
3659 if (!NT_STATUS_IS_OK(status)) {
3660 result = ntstatus_to_werror(status);
3661 goto done;
3664 if (!W_ERROR_IS_OK(result)) {
3665 goto done;
3668 /* construct ctr */
3669 ZERO_STRUCTP(info_ctr);
3671 info_ctr->level = level;
3673 switch (level) {
3674 case 1:
3676 struct srvsvc_NetShareCtr1 *ctr1;
3678 ctr1 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr1);
3679 W_ERROR_HAVE_NO_MEMORY(ctr1);
3681 ctr1->count = 1;
3682 ctr1->array = info.info1;
3684 info_ctr->ctr.ctr1 = ctr1;
3686 break;
3688 case 2:
3690 struct srvsvc_NetShareCtr2 *ctr2;
3692 ctr2 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr2);
3693 W_ERROR_HAVE_NO_MEMORY(ctr2);
3695 ctr2->count = 1;
3696 ctr2->array = info.info2;
3698 info_ctr->ctr.ctr2 = ctr2;
3700 break;
3702 case 502:
3704 struct srvsvc_NetShareCtr502 *ctr502;
3706 ctr502 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr502);
3707 W_ERROR_HAVE_NO_MEMORY(ctr502);
3709 ctr502->count = 1;
3710 ctr502->array = info.info502;
3712 info_ctr->ctr.ctr502 = ctr502;
3714 break;
3716 } /* switch */
3717 done:
3718 return result;
3721 /***
3722 * 'net rpc share list' entrypoint.
3723 * @param argc Standard main() style argc.
3724 * @param argv Standard main() style argv. Initial components are already
3725 * stripped.
3727 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3729 NET_API_STATUS status;
3730 struct SHARE_INFO_1 *i1 = NULL;
3731 uint32_t entries_read = 0;
3732 uint32_t total_entries = 0;
3733 uint32_t resume_handle = 0;
3734 uint32_t i, level = 1;
3736 if (c->display_usage) {
3737 d_printf( "%s\n"
3738 "net rpc share list\n"
3739 " %s\n",
3740 _("Usage:"),
3741 _("List shares on remote server"));
3742 return 0;
3745 status = NetShareEnum(c->opt_host,
3746 level,
3747 (uint8_t **)(void *)&i1,
3748 (uint32_t)-1,
3749 &entries_read,
3750 &total_entries,
3751 &resume_handle);
3752 if (status != 0) {
3753 goto done;
3756 /* Display results */
3758 if (c->opt_long_list_entries) {
3759 d_printf(_(
3760 "\nEnumerating shared resources (exports) on remote server:\n\n"
3761 "\nShare name Type Description\n"
3762 "---------- ---- -----------\n"));
3764 for (i = 0; i < entries_read; i++)
3765 display_share_info_1(c, &i1[i]);
3766 done:
3767 return status;
3770 static bool check_share_availability(struct cli_state *cli, const char *netname)
3772 NTSTATUS status;
3774 status = cli_tree_connect(cli, netname, "A:", NULL);
3775 if (!NT_STATUS_IS_OK(status)) {
3776 d_printf(_("skipping [%s]: not a file share.\n"), netname);
3777 return false;
3780 status = cli_tdis(cli);
3781 if (!NT_STATUS_IS_OK(status)) {
3782 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3783 return false;
3786 return true;
3789 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3790 const char *netname, uint32_t type)
3792 /* only support disk shares */
3793 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3794 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3795 type);
3796 return false;
3799 /* skip builtin shares */
3800 /* FIXME: should print$ be added too ? */
3801 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3802 strequal(netname,"global"))
3803 return false;
3805 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3806 printf(_("excluding [%s]\n"), netname);
3807 return false;
3810 return check_share_availability(cli, netname);
3814 * Migrate shares from a remote RPC server to the local RPC server.
3816 * All parameters are provided by the run_rpc_command function, except for
3817 * argc, argv which are passed through.
3819 * @param domain_sid The domain sid acquired from the remote server.
3820 * @param cli A cli_state connected to the server.
3821 * @param mem_ctx Talloc context, destroyed on completion of the function.
3822 * @param argc Standard main() style argc.
3823 * @param argv Standard main() style argv. Initial components are already
3824 * stripped.
3826 * @return Normal NTSTATUS return.
3829 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3830 const struct dom_sid *domain_sid,
3831 const char *domain_name,
3832 struct cli_state *cli,
3833 struct rpc_pipe_client *pipe_hnd,
3834 TALLOC_CTX *mem_ctx,
3835 int argc,
3836 const char **argv)
3838 WERROR result;
3839 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3840 struct srvsvc_NetShareInfoCtr ctr_src;
3841 uint32_t i;
3842 struct rpc_pipe_client *srvsvc_pipe = NULL;
3843 struct cli_state *cli_dst = NULL;
3844 uint32_t level = 502; /* includes secdesc */
3845 uint32_t parm_error = 0;
3846 struct dcerpc_binding_handle *b;
3848 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3849 &ctr_src);
3850 if (!W_ERROR_IS_OK(result))
3851 goto done;
3853 /* connect destination PI_SRVSVC */
3854 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3855 &ndr_table_srvsvc);
3856 if (!NT_STATUS_IS_OK(nt_status))
3857 return nt_status;
3859 b = srvsvc_pipe->binding_handle;
3861 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3863 union srvsvc_NetShareInfo info;
3864 struct srvsvc_NetShareInfo502 info502 =
3865 ctr_src.ctr.ctr502->array[i];
3867 /* reset error-code */
3868 nt_status = NT_STATUS_UNSUCCESSFUL;
3870 if (!check_share_sanity(c, cli, info502.name, info502.type))
3871 continue;
3873 /* finally add the share on the dst server */
3875 printf(_("migrating: [%s], path: %s, comment: %s, without "
3876 "share-ACLs\n"),
3877 info502.name, info502.path, info502.comment);
3879 info.info502 = &info502;
3881 nt_status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
3882 srvsvc_pipe->desthost,
3883 502,
3884 &info,
3885 &parm_error,
3886 &result);
3887 if (!NT_STATUS_IS_OK(nt_status)) {
3888 printf(_("cannot add share: %s\n"),
3889 nt_errstr(nt_status));
3890 goto done;
3892 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3893 printf(_(" [%s] does already exist\n"),
3894 info502.name);
3895 continue;
3898 if (!W_ERROR_IS_OK(result)) {
3899 nt_status = werror_to_ntstatus(result);
3900 printf(_("cannot add share: %s\n"),
3901 win_errstr(result));
3902 goto done;
3907 nt_status = NT_STATUS_OK;
3909 done:
3910 if (cli_dst) {
3911 cli_shutdown(cli_dst);
3914 return nt_status;
3919 * Migrate shares from a RPC server to another.
3921 * @param argc Standard main() style argc.
3922 * @param argv Standard main() style argv. Initial components are already
3923 * stripped.
3925 * @return A shell status integer (0 for success).
3927 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3928 const char **argv)
3930 if (c->display_usage) {
3931 d_printf( "%s\n"
3932 "net rpc share migrate shares\n"
3933 " %s\n",
3934 _("Usage:"),
3935 _("Migrate shares to local server"));
3936 return 0;
3939 if (!c->opt_host) {
3940 printf(_("no server to migrate\n"));
3941 return -1;
3944 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
3945 rpc_share_migrate_shares_internals,
3946 argc, argv);
3950 * Copy a file/dir
3952 * @param f file_info
3953 * @param mask current search mask
3954 * @param state arg-pointer
3957 static NTSTATUS copy_fn(const char *mnt, struct file_info *f,
3958 const char *mask, void *state)
3960 static NTSTATUS nt_status;
3961 static struct copy_clistate *local_state;
3962 static fstring filename, new_mask;
3963 fstring dir;
3964 char *old_dir;
3965 struct net_context *c;
3967 local_state = (struct copy_clistate *)state;
3968 nt_status = NT_STATUS_UNSUCCESSFUL;
3970 c = local_state->c;
3972 if (strequal(f->name, ".") || strequal(f->name, ".."))
3973 return NT_STATUS_OK;
3975 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3977 /* DIRECTORY */
3978 if (f->mode & FILE_ATTRIBUTE_DIRECTORY) {
3980 DEBUG(3,("got dir: %s\n", f->name));
3982 fstrcpy(dir, local_state->cwd);
3983 fstrcat(dir, "\\");
3984 fstrcat(dir, f->name);
3986 switch (net_mode_share)
3988 case NET_MODE_SHARE_MIGRATE:
3989 /* create that directory */
3990 nt_status = net_copy_file(c, local_state->mem_ctx,
3991 local_state->cli_share_src,
3992 local_state->cli_share_dst,
3993 dir, dir,
3994 c->opt_acls? true : false,
3995 c->opt_attrs? true : false,
3996 c->opt_timestamps? true:false,
3997 false);
3998 break;
3999 default:
4000 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
4001 return NT_STATUS_INTERNAL_ERROR;
4004 if (!NT_STATUS_IS_OK(nt_status)) {
4005 printf(_("could not handle dir %s: %s\n"),
4006 dir, nt_errstr(nt_status));
4007 return nt_status;
4010 /* search below that directory */
4011 if (strlcpy(new_mask, dir, sizeof(new_mask)) >= sizeof(new_mask)) {
4012 return NT_STATUS_NO_MEMORY;
4014 if (strlcat(new_mask, "\\*", sizeof(new_mask)) >= sizeof(new_mask)) {
4015 return NT_STATUS_NO_MEMORY;
4018 old_dir = local_state->cwd;
4019 local_state->cwd = dir;
4020 nt_status = sync_files(local_state, new_mask);
4021 if (!NT_STATUS_IS_OK(nt_status)) {
4022 printf(_("could not handle files\n"));
4024 local_state->cwd = old_dir;
4026 return nt_status;
4030 /* FILE */
4031 fstrcpy(filename, local_state->cwd);
4032 fstrcat(filename, "\\");
4033 fstrcat(filename, f->name);
4035 DEBUG(3,("got file: %s\n", filename));
4037 switch (net_mode_share)
4039 case NET_MODE_SHARE_MIGRATE:
4040 nt_status = net_copy_file(c, local_state->mem_ctx,
4041 local_state->cli_share_src,
4042 local_state->cli_share_dst,
4043 filename, filename,
4044 c->opt_acls? true : false,
4045 c->opt_attrs? true : false,
4046 c->opt_timestamps? true: false,
4047 true);
4048 break;
4049 default:
4050 d_fprintf(stderr, _("Unsupported file mode %d\n"),
4051 net_mode_share);
4052 return NT_STATUS_INTERNAL_ERROR;
4055 if (!NT_STATUS_IS_OK(nt_status))
4056 printf(_("could not handle file %s: %s\n"),
4057 filename, nt_errstr(nt_status));
4058 return nt_status;
4062 * sync files, can be called recursivly to list files
4063 * and then call copy_fn for each file
4065 * @param cp_clistate pointer to the copy_clistate we work with
4066 * @param mask the current search mask
4068 * @return Boolean result
4070 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask)
4072 struct cli_state *targetcli;
4073 char *targetpath = NULL;
4074 NTSTATUS status;
4076 DEBUG(3,("calling cli_list with mask: %s\n", mask));
4078 status = cli_resolve_path(talloc_tos(), "", NULL,
4079 cp_clistate->cli_share_src,
4080 mask, &targetcli, &targetpath);
4081 if (!NT_STATUS_IS_OK(status)) {
4082 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
4083 "%s\n"),
4084 mask, nt_errstr(status));
4085 return status;
4088 status = cli_list(targetcli, targetpath, cp_clistate->attribute,
4089 copy_fn, cp_clistate);
4090 if (!NT_STATUS_IS_OK(status)) {
4091 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
4092 mask, nt_errstr(status));
4095 return status;
4100 * Set the top level directory permissions before we do any further copies.
4101 * Should set up ACL inheritance.
4104 bool copy_top_level_perms(struct net_context *c,
4105 struct copy_clistate *cp_clistate,
4106 const char *sharename)
4108 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4110 switch (net_mode_share) {
4111 case NET_MODE_SHARE_MIGRATE:
4112 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
4113 nt_status = net_copy_fileattr(c,
4114 cp_clistate->mem_ctx,
4115 cp_clistate->cli_share_src,
4116 cp_clistate->cli_share_dst,
4117 "\\", "\\",
4118 c->opt_acls? true : false,
4119 c->opt_attrs? true : false,
4120 c->opt_timestamps? true: false,
4121 false);
4122 break;
4123 default:
4124 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
4125 break;
4128 if (!NT_STATUS_IS_OK(nt_status)) {
4129 printf(_("Could handle directory attributes for top level "
4130 "directory of share %s. Error %s\n"),
4131 sharename, nt_errstr(nt_status));
4132 return false;
4135 return true;
4139 * Sync all files inside a remote share to another share (over smb).
4141 * All parameters are provided by the run_rpc_command function, except for
4142 * argc, argv which are passed through.
4144 * @param domain_sid The domain sid acquired from the remote server.
4145 * @param cli A cli_state connected to the server.
4146 * @param mem_ctx Talloc context, destroyed on completion of the function.
4147 * @param argc Standard main() style argc.
4148 * @param argv Standard main() style argv. Initial components are already
4149 * stripped.
4151 * @return Normal NTSTATUS return.
4154 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
4155 const struct dom_sid *domain_sid,
4156 const char *domain_name,
4157 struct cli_state *cli,
4158 struct rpc_pipe_client *pipe_hnd,
4159 TALLOC_CTX *mem_ctx,
4160 int argc,
4161 const char **argv)
4163 WERROR result;
4164 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4165 struct srvsvc_NetShareInfoCtr ctr_src;
4166 uint32_t i;
4167 uint32_t level = 502;
4168 struct copy_clistate cp_clistate;
4169 bool got_src_share = false;
4170 bool got_dst_share = false;
4171 const char *mask = "\\*";
4172 char *dst = NULL;
4174 dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
4175 if (dst == NULL) {
4176 nt_status = NT_STATUS_NO_MEMORY;
4177 goto done;
4180 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
4181 &ctr_src);
4183 if (!W_ERROR_IS_OK(result))
4184 goto done;
4186 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
4188 struct srvsvc_NetShareInfo502 info502 =
4189 ctr_src.ctr.ctr502->array[i];
4191 if (!check_share_sanity(c, cli, info502.name, info502.type))
4192 continue;
4194 /* one might not want to mirror whole discs :) */
4195 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
4196 d_printf(_("skipping [%s]: builtin/hidden share\n"),
4197 info502.name);
4198 continue;
4201 switch (net_mode_share)
4203 case NET_MODE_SHARE_MIGRATE:
4204 printf("syncing");
4205 break;
4206 default:
4207 d_fprintf(stderr, _("Unsupported mode %d\n"),
4208 net_mode_share);
4209 break;
4211 printf(_(" [%s] files and directories %s ACLs, %s DOS "
4212 "Attributes %s\n"),
4213 info502.name,
4214 c->opt_acls ? _("including") : _("without"),
4215 c->opt_attrs ? _("including") : _("without"),
4216 c->opt_timestamps ? _("(preserving timestamps)") : "");
4218 cp_clistate.mem_ctx = mem_ctx;
4219 cp_clistate.cli_share_src = NULL;
4220 cp_clistate.cli_share_dst = NULL;
4221 cp_clistate.cwd = NULL;
4222 cp_clistate.attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
4223 cp_clistate.c = c;
4225 /* open share source */
4226 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
4227 smbXcli_conn_remote_sockaddr(cli->conn),
4228 smbXcli_conn_remote_name(cli->conn),
4229 info502.name, "A:");
4230 if (!NT_STATUS_IS_OK(nt_status))
4231 goto done;
4233 got_src_share = true;
4235 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
4236 /* open share destination */
4237 nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
4238 NULL, dst, info502.name, "A:");
4239 if (!NT_STATUS_IS_OK(nt_status))
4240 goto done;
4242 got_dst_share = true;
4245 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
4246 d_fprintf(stderr, _("Could not handle the top level "
4247 "directory permissions for the "
4248 "share: %s\n"), info502.name);
4249 nt_status = NT_STATUS_UNSUCCESSFUL;
4250 goto done;
4253 nt_status = sync_files(&cp_clistate, mask);
4254 if (!NT_STATUS_IS_OK(nt_status)) {
4255 d_fprintf(stderr, _("could not handle files for share: "
4256 "%s\n"), info502.name);
4257 goto done;
4261 nt_status = NT_STATUS_OK;
4263 done:
4265 if (got_src_share)
4266 cli_shutdown(cp_clistate.cli_share_src);
4268 if (got_dst_share)
4269 cli_shutdown(cp_clistate.cli_share_dst);
4271 SAFE_FREE(dst);
4272 return nt_status;
4276 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
4278 if (c->display_usage) {
4279 d_printf( "%s\n"
4280 "net share migrate files\n"
4281 " %s\n",
4282 _("Usage:"),
4283 _("Migrate files to local server"));
4284 return 0;
4287 if (!c->opt_host) {
4288 d_printf(_("no server to migrate\n"));
4289 return -1;
4292 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4293 rpc_share_migrate_files_internals,
4294 argc, argv);
4298 * Migrate share-ACLs from a remote RPC server to the local RPC server.
4300 * All parameters are provided by the run_rpc_command function, except for
4301 * argc, argv which are passed through.
4303 * @param domain_sid The domain sid acquired from the remote server.
4304 * @param cli A cli_state connected to the server.
4305 * @param mem_ctx Talloc context, destroyed on completion of the function.
4306 * @param argc Standard main() style argc.
4307 * @param argv Standard main() style argv. Initial components are already
4308 * stripped.
4310 * @return Normal NTSTATUS return.
4313 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
4314 const struct dom_sid *domain_sid,
4315 const char *domain_name,
4316 struct cli_state *cli,
4317 struct rpc_pipe_client *pipe_hnd,
4318 TALLOC_CTX *mem_ctx,
4319 int argc,
4320 const char **argv)
4322 WERROR result;
4323 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4324 struct srvsvc_NetShareInfoCtr ctr_src;
4325 union srvsvc_NetShareInfo info;
4326 uint32_t i;
4327 struct rpc_pipe_client *srvsvc_pipe = NULL;
4328 struct cli_state *cli_dst = NULL;
4329 uint32_t level = 502; /* includes secdesc */
4330 uint32_t parm_error = 0;
4331 struct dcerpc_binding_handle *b;
4333 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
4334 &ctr_src);
4336 if (!W_ERROR_IS_OK(result))
4337 goto done;
4339 /* connect destination PI_SRVSVC */
4340 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
4341 &ndr_table_srvsvc);
4342 if (!NT_STATUS_IS_OK(nt_status))
4343 return nt_status;
4345 b = srvsvc_pipe->binding_handle;
4347 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
4349 struct srvsvc_NetShareInfo502 info502 =
4350 ctr_src.ctr.ctr502->array[i];
4352 /* reset error-code */
4353 nt_status = NT_STATUS_UNSUCCESSFUL;
4355 if (!check_share_sanity(c, cli, info502.name, info502.type))
4356 continue;
4358 printf(_("migrating: [%s], path: %s, comment: %s, including "
4359 "share-ACLs\n"),
4360 info502.name, info502.path, info502.comment);
4362 if (c->opt_verbose)
4363 display_sec_desc(info502.sd_buf.sd);
4365 /* FIXME: shouldn't we be able to just set the security descriptor ? */
4366 info.info502 = &info502;
4368 /* finally modify the share on the dst server */
4369 nt_status = dcerpc_srvsvc_NetShareSetInfo(b, mem_ctx,
4370 srvsvc_pipe->desthost,
4371 info502.name,
4372 level,
4373 &info,
4374 &parm_error,
4375 &result);
4376 if (!NT_STATUS_IS_OK(nt_status)) {
4377 printf(_("cannot set share-acl: %s\n"),
4378 nt_errstr(nt_status));
4379 goto done;
4381 if (!W_ERROR_IS_OK(result)) {
4382 nt_status = werror_to_ntstatus(result);
4383 printf(_("cannot set share-acl: %s\n"),
4384 win_errstr(result));
4385 goto done;
4390 nt_status = NT_STATUS_OK;
4392 done:
4393 if (cli_dst) {
4394 cli_shutdown(cli_dst);
4397 return nt_status;
4402 * Migrate share-acls from a RPC server to another.
4404 * @param argc Standard main() style argc.
4405 * @param argv Standard main() style argv. Initial components are already
4406 * stripped.
4408 * @return A shell status integer (0 for success).
4410 static int rpc_share_migrate_security(struct net_context *c, int argc,
4411 const char **argv)
4413 if (c->display_usage) {
4414 d_printf( "%s\n"
4415 "net rpc share migrate security\n"
4416 " %s\n",
4417 _("Usage:"),
4418 _("Migrate share-acls to local server"));
4419 return 0;
4422 if (!c->opt_host) {
4423 d_printf(_("no server to migrate\n"));
4424 return -1;
4427 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4428 rpc_share_migrate_security_internals,
4429 argc, argv);
4433 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
4434 * from one server to another.
4436 * @param argc Standard main() style argc.
4437 * @param argv Standard main() style argv. Initial components are already
4438 * stripped.
4440 * @return A shell status integer (0 for success).
4443 static int rpc_share_migrate_all(struct net_context *c, int argc,
4444 const char **argv)
4446 int ret;
4448 if (c->display_usage) {
4449 d_printf( "%s\n"
4450 "net rpc share migrate all\n"
4451 " %s\n",
4452 _("Usage:"),
4453 _("Migrates shares including all share settings"));
4454 return 0;
4457 if (!c->opt_host) {
4458 d_printf(_("no server to migrate\n"));
4459 return -1;
4462 /* order is important. we don't want to be locked out by the share-acl
4463 * before copying files - gd */
4465 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4466 rpc_share_migrate_shares_internals, argc, argv);
4467 if (ret)
4468 return ret;
4470 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4471 rpc_share_migrate_files_internals, argc, argv);
4472 if (ret)
4473 return ret;
4475 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4476 rpc_share_migrate_security_internals, argc,
4477 argv);
4482 * 'net rpc share migrate' entrypoint.
4483 * @param argc Standard main() style argc.
4484 * @param argv Standard main() style argv. Initial components are already
4485 * stripped.
4487 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
4490 struct functable func[] = {
4492 "all",
4493 rpc_share_migrate_all,
4494 NET_TRANSPORT_RPC,
4495 N_("Migrate shares from remote to local server"),
4496 N_("net rpc share migrate all\n"
4497 " Migrate shares from remote to local server")
4500 "files",
4501 rpc_share_migrate_files,
4502 NET_TRANSPORT_RPC,
4503 N_("Migrate files from remote to local server"),
4504 N_("net rpc share migrate files\n"
4505 " Migrate files from remote to local server")
4508 "security",
4509 rpc_share_migrate_security,
4510 NET_TRANSPORT_RPC,
4511 N_("Migrate share-ACLs from remote to local server"),
4512 N_("net rpc share migrate security\n"
4513 " Migrate share-ACLs from remote to local server")
4516 "shares",
4517 rpc_share_migrate_shares,
4518 NET_TRANSPORT_RPC,
4519 N_("Migrate shares from remote to local server"),
4520 N_("net rpc share migrate shares\n"
4521 " Migrate shares from remote to local server")
4523 {NULL, NULL, 0, NULL, NULL}
4526 net_mode_share = NET_MODE_SHARE_MIGRATE;
4528 return net_run_function(c, argc, argv, "net rpc share migrate", func);
4531 struct full_alias {
4532 struct dom_sid sid;
4533 uint32_t num_members;
4534 struct dom_sid *members;
4537 static int num_server_aliases;
4538 static struct full_alias *server_aliases;
4541 * Add an alias to the static list.
4543 static void push_alias(struct full_alias *alias)
4545 size_t array_size;
4547 if (server_aliases == NULL) {
4548 server_aliases = talloc_array(NULL, struct full_alias, 100);
4549 if (server_aliases == NULL) {
4550 smb_panic("talloc_array failed");
4554 array_size = talloc_array_length(server_aliases);
4555 if (array_size == num_server_aliases) {
4556 server_aliases = talloc_realloc(NULL, server_aliases,
4557 struct full_alias, array_size + 100);
4558 if (server_aliases == NULL) {
4559 smb_panic("talloc_realloc failed");
4563 server_aliases[num_server_aliases] = *alias;
4564 num_server_aliases += 1;
4568 * For a specific domain on the server, fetch all the aliases
4569 * and their members. Add all of them to the server_aliases.
4572 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4573 TALLOC_CTX *mem_ctx,
4574 struct policy_handle *connect_pol,
4575 const struct dom_sid *domain_sid)
4577 uint32_t start_idx, max_entries, num_entries, i;
4578 struct samr_SamArray *groups = NULL;
4579 NTSTATUS result, status;
4580 struct policy_handle domain_pol;
4581 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4583 /* Get domain policy handle */
4585 status = dcerpc_samr_OpenDomain(b, mem_ctx,
4586 connect_pol,
4587 MAXIMUM_ALLOWED_ACCESS,
4588 discard_const_p(struct dom_sid2, domain_sid),
4589 &domain_pol,
4590 &result);
4591 if (!NT_STATUS_IS_OK(status)) {
4592 return status;
4594 if (!NT_STATUS_IS_OK(result)) {
4595 return result;
4598 start_idx = 0;
4599 max_entries = 250;
4601 do {
4602 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
4603 &domain_pol,
4604 &start_idx,
4605 &groups,
4606 max_entries,
4607 &num_entries,
4608 &result);
4609 if (!NT_STATUS_IS_OK(status)) {
4610 goto done;
4612 for (i = 0; i < num_entries; i++) {
4614 struct policy_handle alias_pol;
4615 struct full_alias alias;
4616 struct lsa_SidArray sid_array;
4617 int j;
4618 NTSTATUS _result;
4620 status = dcerpc_samr_OpenAlias(b, mem_ctx,
4621 &domain_pol,
4622 MAXIMUM_ALLOWED_ACCESS,
4623 groups->entries[i].idx,
4624 &alias_pol,
4625 &_result);
4626 if (!NT_STATUS_IS_OK(status)) {
4627 goto done;
4629 if (!NT_STATUS_IS_OK(_result)) {
4630 status = _result;
4631 goto done;
4634 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
4635 &alias_pol,
4636 &sid_array,
4637 &_result);
4638 if (!NT_STATUS_IS_OK(status)) {
4639 goto done;
4641 if (!NT_STATUS_IS_OK(_result)) {
4642 status = _result;
4643 goto done;
4646 alias.num_members = sid_array.num_sids;
4648 status = dcerpc_samr_Close(b, mem_ctx, &alias_pol, &_result);
4649 if (!NT_STATUS_IS_OK(status)) {
4650 goto done;
4652 if (!NT_STATUS_IS_OK(_result)) {
4653 status = _result;
4654 goto done;
4657 alias.members = NULL;
4659 if (alias.num_members > 0) {
4660 alias.members = SMB_MALLOC_ARRAY(struct dom_sid, alias.num_members);
4662 for (j = 0; j < alias.num_members; j++)
4663 sid_copy(&alias.members[j],
4664 sid_array.sids[j].sid);
4667 sid_compose(&alias.sid, domain_sid,
4668 groups->entries[i].idx);
4670 push_alias(&alias);
4672 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4674 status = NT_STATUS_OK;
4676 done:
4677 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
4679 return status;
4683 * Dump server_aliases as names for debugging purposes.
4686 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4687 const struct dom_sid *domain_sid,
4688 const char *domain_name,
4689 struct cli_state *cli,
4690 struct rpc_pipe_client *pipe_hnd,
4691 TALLOC_CTX *mem_ctx,
4692 int argc,
4693 const char **argv)
4695 int i;
4696 NTSTATUS result;
4697 struct policy_handle lsa_pol;
4698 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4700 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4701 SEC_FLAG_MAXIMUM_ALLOWED,
4702 &lsa_pol);
4703 if (!NT_STATUS_IS_OK(result))
4704 return result;
4706 for (i=0; i<num_server_aliases; i++) {
4707 char **names;
4708 char **domains;
4709 enum lsa_SidType *types;
4710 int j;
4712 struct full_alias *alias = &server_aliases[i];
4714 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4715 &alias->sid,
4716 &domains, &names, &types);
4717 if (!NT_STATUS_IS_OK(result))
4718 continue;
4720 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4722 if (alias->num_members == 0) {
4723 DEBUG(1, ("\n"));
4724 continue;
4727 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4728 alias->num_members,
4729 alias->members,
4730 &domains, &names, &types);
4732 if (!NT_STATUS_IS_OK(result) &&
4733 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4734 continue;
4736 for (j=0; j<alias->num_members; j++)
4737 DEBUG(1, ("%s\\%s (%d); ",
4738 domains[j] ? domains[j] : "*unknown*",
4739 names[j] ? names[j] : "*unknown*",types[j]));
4740 DEBUG(1, ("\n"));
4743 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
4745 return NT_STATUS_OK;
4749 * Fetch a list of all server aliases and their members into
4750 * server_aliases.
4753 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4754 const struct dom_sid *domain_sid,
4755 const char *domain_name,
4756 struct cli_state *cli,
4757 struct rpc_pipe_client *pipe_hnd,
4758 TALLOC_CTX *mem_ctx,
4759 int argc,
4760 const char **argv)
4762 NTSTATUS result, status;
4763 struct policy_handle connect_pol;
4764 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4766 status = dcerpc_samr_Connect2(b, mem_ctx,
4767 pipe_hnd->desthost,
4768 MAXIMUM_ALLOWED_ACCESS,
4769 &connect_pol,
4770 &result);
4771 if (!NT_STATUS_IS_OK(status)) {
4772 goto done;
4774 if (!NT_STATUS_IS_OK(result)) {
4775 status = result;
4776 goto done;
4779 status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4780 &global_sid_Builtin);
4781 if (!NT_STATUS_IS_OK(status)) {
4782 goto done;
4785 status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4786 domain_sid);
4788 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
4789 done:
4790 return status;
4793 static void init_user_token(struct security_token *token, struct dom_sid *user_sid)
4795 token->num_sids = 4;
4797 if (!(token->sids = SMB_MALLOC_ARRAY(struct dom_sid, 4))) {
4798 d_fprintf(stderr, "malloc %s\n",_("failed"));
4799 token->num_sids = 0;
4800 return;
4803 token->sids[0] = *user_sid;
4804 sid_copy(&token->sids[1], &global_sid_World);
4805 sid_copy(&token->sids[2], &global_sid_Network);
4806 sid_copy(&token->sids[3], &global_sid_Authenticated_Users);
4809 static void free_user_token(struct security_token *token)
4811 SAFE_FREE(token->sids);
4814 static void add_sid_to_token(struct security_token *token, struct dom_sid *sid)
4816 if (security_token_has_sid(token, sid))
4817 return;
4819 token->sids = SMB_REALLOC_ARRAY(token->sids, struct dom_sid, token->num_sids+1);
4820 if (!token->sids) {
4821 return;
4824 sid_copy(&token->sids[token->num_sids], sid);
4826 token->num_sids += 1;
4829 struct user_token {
4830 fstring name;
4831 struct security_token token;
4834 static void dump_user_token(struct user_token *token)
4836 int i;
4838 d_printf("%s\n", token->name);
4840 for (i=0; i<token->token.num_sids; i++) {
4841 d_printf(" %s\n", sid_string_tos(&token->token.sids[i]));
4845 static bool is_alias_member(struct dom_sid *sid, struct full_alias *alias)
4847 int i;
4849 for (i=0; i<alias->num_members; i++) {
4850 if (dom_sid_compare(sid, &alias->members[i]) == 0)
4851 return true;
4854 return false;
4857 static void collect_sid_memberships(struct security_token *token, struct dom_sid sid)
4859 int i;
4861 for (i=0; i<num_server_aliases; i++) {
4862 if (is_alias_member(&sid, &server_aliases[i]))
4863 add_sid_to_token(token, &server_aliases[i].sid);
4868 * We got a user token with all the SIDs we can know about without asking the
4869 * server directly. These are the user and domain group sids. All of these can
4870 * be members of aliases. So scan the list of aliases for each of the SIDs and
4871 * add them to the token.
4874 static void collect_alias_memberships(struct security_token *token)
4876 int num_global_sids = token->num_sids;
4877 int i;
4879 for (i=0; i<num_global_sids; i++) {
4880 collect_sid_memberships(token, token->sids[i]);
4884 static bool get_user_sids(const char *domain, const char *user, struct security_token *token)
4886 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4887 enum wbcSidType type;
4888 fstring full_name;
4889 struct wbcDomainSid wsid;
4890 char sid_str[WBC_SID_STRING_BUFLEN];
4891 struct dom_sid user_sid;
4892 uint32_t num_groups;
4893 gid_t *groups = NULL;
4894 uint32_t i;
4896 fstr_sprintf(full_name, "%s%c%s",
4897 domain, *lp_winbind_separator(), user);
4899 /* First let's find out the user sid */
4901 wbc_status = wbcLookupName(domain, user, &wsid, &type);
4903 if (!WBC_ERROR_IS_OK(wbc_status)) {
4904 DEBUG(1, ("winbind could not find %s: %s\n",
4905 full_name, wbcErrorString(wbc_status)));
4906 return false;
4909 wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4911 if (type != WBC_SID_NAME_USER) {
4912 DEBUG(1, ("%s is not a user\n", full_name));
4913 return false;
4916 if (!string_to_sid(&user_sid, sid_str)) {
4917 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4918 return false;
4921 init_user_token(token, &user_sid);
4923 /* And now the groups winbind knows about */
4925 wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4926 if (!WBC_ERROR_IS_OK(wbc_status)) {
4927 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4928 full_name, wbcErrorString(wbc_status)));
4929 return false;
4932 for (i = 0; i < num_groups; i++) {
4933 gid_t gid = groups[i];
4934 struct dom_sid sid;
4935 bool ok;
4937 wbc_status = wbcGidToSid(gid, &wsid);
4938 if (!WBC_ERROR_IS_OK(wbc_status)) {
4939 DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4940 (unsigned int)gid, wbcErrorString(wbc_status)));
4941 wbcFreeMemory(groups);
4942 return false;
4945 wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4947 DEBUG(3, (" %s\n", sid_str));
4949 ok = string_to_sid(&sid, sid_str);
4950 if (!ok) {
4951 DEBUG(1, ("Failed to convert string to SID\n"));
4952 wbcFreeMemory(groups);
4953 return false;
4955 add_sid_to_token(token, &sid);
4957 wbcFreeMemory(groups);
4959 return true;
4963 * Get a list of all user tokens we want to look at
4966 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4967 struct user_token **user_tokens)
4969 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4970 uint32_t i, num_users;
4971 const char **users;
4972 struct user_token *result;
4973 TALLOC_CTX *frame = NULL;
4975 if (lp_winbind_use_default_domain() &&
4976 (c->opt_target_workgroup == NULL)) {
4977 d_fprintf(stderr, _("winbind use default domain = yes set, "
4978 "please specify a workgroup\n"));
4979 return false;
4982 /* Send request to winbind daemon */
4984 wbc_status = wbcListUsers(NULL, &num_users, &users);
4985 if (!WBC_ERROR_IS_OK(wbc_status)) {
4986 DEBUG(1, (_("winbind could not list users: %s\n"),
4987 wbcErrorString(wbc_status)));
4988 return false;
4991 result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4993 if (result == NULL) {
4994 DEBUG(1, ("Could not malloc sid array\n"));
4995 wbcFreeMemory(users);
4996 return false;
4999 frame = talloc_stackframe();
5000 for (i=0; i < num_users; i++) {
5001 fstring domain, user;
5002 char *p;
5004 fstrcpy(result[i].name, users[i]);
5006 p = strchr(users[i], *lp_winbind_separator());
5008 DEBUG(3, ("%s\n", users[i]));
5010 if (p == NULL) {
5011 fstrcpy(domain, c->opt_target_workgroup);
5012 fstrcpy(user, users[i]);
5013 } else {
5014 *p++ = '\0';
5015 fstrcpy(domain, users[i]);
5016 if (!strupper_m(domain)) {
5017 DEBUG(1, ("strupper_m %s failed\n", domain));
5018 wbcFreeMemory(users);
5019 return false;
5021 fstrcpy(user, p);
5024 get_user_sids(domain, user, &(result[i].token));
5026 TALLOC_FREE(frame);
5027 wbcFreeMemory(users);
5029 *num_tokens = num_users;
5030 *user_tokens = result;
5032 return true;
5035 static bool get_user_tokens_from_file(FILE *f,
5036 int *num_tokens,
5037 struct user_token **tokens)
5039 struct user_token *token = NULL;
5041 while (!feof(f)) {
5042 fstring line;
5044 if (fgets(line, sizeof(line)-1, f) == NULL) {
5045 return true;
5048 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
5049 line[strlen(line)-1] = '\0';
5052 if (line[0] == ' ') {
5053 /* We have a SID */
5055 struct dom_sid sid;
5056 if(!string_to_sid(&sid, &line[1])) {
5057 DEBUG(1,("get_user_tokens_from_file: Could "
5058 "not convert sid %s \n",&line[1]));
5059 return false;
5062 if (token == NULL) {
5063 DEBUG(0, ("File does not begin with username"));
5064 return false;
5067 add_sid_to_token(&token->token, &sid);
5068 continue;
5071 /* And a new user... */
5073 *num_tokens += 1;
5074 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
5075 if (*tokens == NULL) {
5076 DEBUG(0, ("Could not realloc tokens\n"));
5077 return false;
5080 token = &((*tokens)[*num_tokens-1]);
5082 if (strlcpy(token->name, line, sizeof(token->name)) >= sizeof(token->name)) {
5083 return false;
5085 token->token.num_sids = 0;
5086 token->token.sids = NULL;
5087 continue;
5090 return false;
5095 * Show the list of all users that have access to a share
5098 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
5099 struct cli_state *cli,
5100 TALLOC_CTX *mem_ctx,
5101 const char *netname,
5102 int num_tokens,
5103 struct user_token *tokens)
5105 uint16_t fnum;
5106 struct security_descriptor *share_sd = NULL;
5107 struct security_descriptor *root_sd = NULL;
5108 int i;
5109 union srvsvc_NetShareInfo info;
5110 WERROR result;
5111 NTSTATUS status;
5112 struct smbXcli_tcon *orig_tcon = NULL;
5113 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5115 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5116 pipe_hnd->desthost,
5117 netname,
5118 502,
5119 &info,
5120 &result);
5122 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
5123 DEBUG(1, ("Could not query secdesc for share %s\n",
5124 netname));
5125 return;
5128 share_sd = info.info502->sd_buf.sd;
5129 if (share_sd == NULL) {
5130 DEBUG(1, ("Got no secdesc for share %s\n",
5131 netname));
5134 if (cli_state_has_tcon(cli)) {
5135 orig_tcon = cli_state_save_tcon(cli);
5136 if (orig_tcon == NULL) {
5137 return;
5141 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, netname, "A:", NULL))) {
5142 cli_state_restore_tcon(cli, orig_tcon);
5143 return;
5146 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
5147 FILE_SHARE_READ|FILE_SHARE_WRITE,
5148 FILE_OPEN, 0x0, 0x0, &fnum, NULL))) {
5149 cli_query_secdesc(cli, fnum, mem_ctx, &root_sd);
5152 for (i=0; i<num_tokens; i++) {
5153 uint32_t acc_granted;
5155 if (share_sd != NULL) {
5156 status = se_access_check(share_sd, &tokens[i].token,
5157 1, &acc_granted);
5159 if (!NT_STATUS_IS_OK(status)) {
5160 DEBUG(1, ("Could not check share_sd for "
5161 "user %s\n",
5162 tokens[i].name));
5163 continue;
5167 if (root_sd == NULL) {
5168 d_printf(" %s\n", tokens[i].name);
5169 continue;
5172 status = se_access_check(root_sd, &tokens[i].token,
5173 1, &acc_granted);
5174 if (!NT_STATUS_IS_OK(status)) {
5175 DEBUG(1, ("Could not check root_sd for user %s\n",
5176 tokens[i].name));
5177 continue;
5179 d_printf(" %s\n", tokens[i].name);
5182 if (fnum != (uint16_t)-1)
5183 cli_close(cli, fnum);
5184 cli_tdis(cli);
5185 cli_state_restore_tcon(cli, orig_tcon);
5187 return;
5191 * List shares on a remote RPC server, including the security descriptors.
5193 * All parameters are provided by the run_rpc_command function, except for
5194 * argc, argv which are passed through.
5196 * @param domain_sid The domain sid acquired from the remote server.
5197 * @param cli A cli_state connected to the server.
5198 * @param mem_ctx Talloc context, destroyed on completion of the function.
5199 * @param argc Standard main() style argc.
5200 * @param argv Standard main() style argv. Initial components are already
5201 * stripped.
5203 * @return Normal NTSTATUS return.
5206 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
5207 const struct dom_sid *domain_sid,
5208 const char *domain_name,
5209 struct cli_state *cli,
5210 struct rpc_pipe_client *pipe_hnd,
5211 TALLOC_CTX *mem_ctx,
5212 int argc,
5213 const char **argv)
5215 bool r;
5216 FILE *f;
5217 NTSTATUS nt_status = NT_STATUS_OK;
5218 uint32_t total_entries = 0;
5219 uint32_t resume_handle = 0;
5220 uint32_t preferred_len = 0xffffffff;
5221 uint32_t i;
5222 struct dcerpc_binding_handle *b = NULL;
5223 struct srvsvc_NetShareInfoCtr info_ctr;
5224 struct srvsvc_NetShareCtr1 ctr1;
5225 WERROR result;
5227 struct user_token *tokens = NULL;
5228 int num_tokens = 0;
5230 if (argc == 0) {
5231 f = stdin;
5232 } else {
5233 f = fopen(argv[0], "r");
5236 if (f == NULL) {
5237 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
5238 return NT_STATUS_UNSUCCESSFUL;
5241 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
5243 if (f != stdin)
5244 fclose(f);
5246 if (!r) {
5247 DEBUG(0, ("Could not read users from file\n"));
5248 return NT_STATUS_UNSUCCESSFUL;
5251 for (i=0; i<num_tokens; i++)
5252 collect_alias_memberships(&tokens[i].token);
5254 ZERO_STRUCT(info_ctr);
5255 ZERO_STRUCT(ctr1);
5257 info_ctr.level = 1;
5258 info_ctr.ctr.ctr1 = &ctr1;
5260 b = pipe_hnd->binding_handle;
5262 /* Issue the NetShareEnum RPC call and retrieve the response */
5263 nt_status = dcerpc_srvsvc_NetShareEnumAll(b,
5264 talloc_tos(),
5265 pipe_hnd->desthost,
5266 &info_ctr,
5267 preferred_len,
5268 &total_entries,
5269 &resume_handle,
5270 &result);
5272 /* Was it successful? */
5273 if (!NT_STATUS_IS_OK(nt_status)) {
5274 /* Nope. Go clean up. */
5275 goto done;
5278 if (!W_ERROR_IS_OK(result)) {
5279 /* Nope. Go clean up. */
5280 nt_status = werror_to_ntstatus(result);
5281 goto done;
5284 if (total_entries == 0) {
5285 goto done;
5288 /* For each returned entry... */
5289 for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {
5290 const char *netname = info_ctr.ctr.ctr1->array[i].name;
5292 if (info_ctr.ctr.ctr1->array[i].type != STYPE_DISKTREE) {
5293 continue;
5296 d_printf("%s\n", netname);
5298 show_userlist(pipe_hnd, cli, mem_ctx, netname,
5299 num_tokens, tokens);
5301 done:
5302 for (i=0; i<num_tokens; i++) {
5303 free_user_token(&tokens[i].token);
5305 SAFE_FREE(tokens);
5306 TALLOC_FREE(server_aliases);
5308 return nt_status;
5311 static int rpc_share_allowedusers(struct net_context *c, int argc,
5312 const char **argv)
5314 int result;
5316 if (c->display_usage) {
5317 d_printf( "%s\n"
5318 "net rpc share allowedusers\n"
5319 " %s\n",
5320 _("Usage:"),
5321 _("List allowed users"));
5322 return 0;
5325 result = run_rpc_command(c, NULL, &ndr_table_samr, 0,
5326 rpc_aliaslist_internals,
5327 argc, argv);
5328 if (result != 0)
5329 return result;
5331 result = run_rpc_command(c, NULL, &ndr_table_lsarpc, 0,
5332 rpc_aliaslist_dump,
5333 argc, argv);
5334 if (result != 0)
5335 return result;
5337 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
5338 rpc_share_allowedusers_internals,
5339 argc, argv);
5342 int net_usersidlist(struct net_context *c, int argc, const char **argv)
5344 int num_tokens = 0;
5345 struct user_token *tokens = NULL;
5346 int i;
5348 if (argc != 0) {
5349 net_usersidlist_usage(c, argc, argv);
5350 return 0;
5353 if (!get_user_tokens(c, &num_tokens, &tokens)) {
5354 DEBUG(0, ("Could not get the user/sid list\n"));
5355 return -1;
5358 for (i=0; i<num_tokens; i++) {
5359 dump_user_token(&tokens[i]);
5360 free_user_token(&tokens[i].token);
5363 SAFE_FREE(tokens);
5364 return 0;
5367 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
5369 d_printf(_("net usersidlist\n"
5370 "\tprints out a list of all users the running winbind knows\n"
5371 "\tabout, together with all their SIDs. This is used as\n"
5372 "\tinput to the 'net rpc share allowedusers' command.\n\n"));
5374 net_common_flags_usage(c, argc, argv);
5375 return -1;
5379 * 'net rpc share' entrypoint.
5380 * @param argc Standard main() style argc.
5381 * @param argv Standard main() style argv. Initial components are already
5382 * stripped.
5385 int net_rpc_share(struct net_context *c, int argc, const char **argv)
5387 NET_API_STATUS status;
5389 struct functable func[] = {
5391 "add",
5392 rpc_share_add,
5393 NET_TRANSPORT_RPC,
5394 N_("Add share"),
5395 N_("net rpc share add\n"
5396 " Add share")
5399 "delete",
5400 rpc_share_delete,
5401 NET_TRANSPORT_RPC,
5402 N_("Remove share"),
5403 N_("net rpc share delete\n"
5404 " Remove share")
5407 "allowedusers",
5408 rpc_share_allowedusers,
5409 NET_TRANSPORT_RPC,
5410 N_("Modify allowed users"),
5411 N_("net rpc share allowedusers\n"
5412 " Modify allowed users")
5415 "migrate",
5416 rpc_share_migrate,
5417 NET_TRANSPORT_RPC,
5418 N_("Migrate share to local server"),
5419 N_("net rpc share migrate\n"
5420 " Migrate share to local server")
5423 "list",
5424 rpc_share_list,
5425 NET_TRANSPORT_RPC,
5426 N_("List shares"),
5427 N_("net rpc share list\n"
5428 " List shares")
5430 {NULL, NULL, 0, NULL, NULL}
5433 status = libnetapi_net_init(&c->netapi_ctx);
5434 if (status != 0) {
5435 return -1;
5437 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5438 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5439 if (c->opt_kerberos) {
5440 libnetapi_set_use_kerberos(c->netapi_ctx);
5443 if (argc == 0) {
5444 if (c->display_usage) {
5445 d_printf("%s\n%s",
5446 _("Usage:"),
5447 _("net rpc share\n"
5448 " List shares\n"
5449 " Alias for net rpc share list\n"));
5450 net_display_usage_from_functable(func);
5451 return 0;
5454 return rpc_share_list(c, argc, argv);
5457 return net_run_function(c, argc, argv, "net rpc share", func);
5460 static NTSTATUS rpc_sh_share_list(struct net_context *c,
5461 TALLOC_CTX *mem_ctx,
5462 struct rpc_sh_ctx *ctx,
5463 struct rpc_pipe_client *pipe_hnd,
5464 int argc, const char **argv)
5467 return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
5470 static NTSTATUS rpc_sh_share_add(struct net_context *c,
5471 TALLOC_CTX *mem_ctx,
5472 struct rpc_sh_ctx *ctx,
5473 struct rpc_pipe_client *pipe_hnd,
5474 int argc, const char **argv)
5476 NET_API_STATUS status;
5477 uint32_t parm_err = 0;
5478 struct SHARE_INFO_2 i2;
5480 if ((argc < 2) || (argc > 3)) {
5481 d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
5482 ctx->whoami);
5483 return NT_STATUS_INVALID_PARAMETER;
5486 i2.shi2_netname = argv[0];
5487 i2.shi2_type = STYPE_DISKTREE;
5488 i2.shi2_remark = (argc == 3) ? argv[2] : "";
5489 i2.shi2_permissions = 0;
5490 i2.shi2_max_uses = 0;
5491 i2.shi2_current_uses = 0;
5492 i2.shi2_path = argv[1];
5493 i2.shi2_passwd = NULL;
5495 status = NetShareAdd(pipe_hnd->desthost,
5497 (uint8_t *)&i2,
5498 &parm_err);
5500 return werror_to_ntstatus(W_ERROR(status));
5503 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
5504 TALLOC_CTX *mem_ctx,
5505 struct rpc_sh_ctx *ctx,
5506 struct rpc_pipe_client *pipe_hnd,
5507 int argc, const char **argv)
5509 if (argc != 1) {
5510 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5511 return NT_STATUS_INVALID_PARAMETER;
5514 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
5517 static NTSTATUS rpc_sh_share_info(struct net_context *c,
5518 TALLOC_CTX *mem_ctx,
5519 struct rpc_sh_ctx *ctx,
5520 struct rpc_pipe_client *pipe_hnd,
5521 int argc, const char **argv)
5523 union srvsvc_NetShareInfo info;
5524 WERROR result;
5525 NTSTATUS status;
5526 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5528 if (argc != 1) {
5529 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5530 return NT_STATUS_INVALID_PARAMETER;
5533 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5534 pipe_hnd->desthost,
5535 argv[0],
5537 &info,
5538 &result);
5539 if (!NT_STATUS_IS_OK(status)) {
5540 result = ntstatus_to_werror(status);
5541 goto done;
5543 if (!W_ERROR_IS_OK(result)) {
5544 goto done;
5547 d_printf(_("Name: %s\n"), info.info2->name);
5548 d_printf(_("Comment: %s\n"), info.info2->comment);
5549 d_printf(_("Path: %s\n"), info.info2->path);
5550 d_printf(_("Password: %s\n"), info.info2->password);
5552 done:
5553 return werror_to_ntstatus(result);
5556 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
5557 struct rpc_sh_ctx *ctx)
5559 static struct rpc_sh_cmd cmds[] = {
5561 { "list", NULL, &ndr_table_srvsvc, rpc_sh_share_list,
5562 N_("List available shares") },
5564 { "add", NULL, &ndr_table_srvsvc, rpc_sh_share_add,
5565 N_("Add a share") },
5567 { "delete", NULL, &ndr_table_srvsvc, rpc_sh_share_delete,
5568 N_("Delete a share") },
5570 { "info", NULL, &ndr_table_srvsvc, rpc_sh_share_info,
5571 N_("Get information about a share") },
5573 { NULL, NULL, 0, NULL, NULL }
5576 return cmds;
5579 /****************************************************************************/
5581 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
5583 return net_file_usage(c, argc, argv);
5587 * Close a file on a remote RPC server.
5589 * @param argc Standard main() style argc.
5590 * @param argv Standard main() style argv. Initial components are already
5591 * stripped.
5593 * @return A shell status integer (0 for success).
5595 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5597 if (argc < 1 || c->display_usage) {
5598 return rpc_file_usage(c, argc, argv);
5601 return NetFileClose(c->opt_host, atoi(argv[0]));
5605 * Formatted print of open file info
5607 * @param r struct FILE_INFO_3 contents
5610 static void display_file_info_3(struct FILE_INFO_3 *r)
5612 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5613 r->fi3_id, r->fi3_username, r->fi3_permissions,
5614 r->fi3_num_locks, r->fi3_pathname);
5618 * List files for a user on a remote RPC server.
5620 * @param argc Standard main() style argc.
5621 * @param argv Standard main() style argv. Initial components are already
5622 * stripped.
5624 * @return A shell status integer (0 for success)..
5627 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5629 NET_API_STATUS status;
5630 uint32_t preferred_len = 0xffffffff, i;
5631 char *username=NULL;
5632 uint32_t total_entries = 0;
5633 uint32_t entries_read = 0;
5634 uint32_t resume_handle = 0;
5635 struct FILE_INFO_3 *i3 = NULL;
5637 if (c->display_usage) {
5638 return rpc_file_usage(c, argc, argv);
5641 /* if argc > 0, must be user command */
5642 if (argc > 0) {
5643 username = smb_xstrdup(argv[0]);
5646 status = NetFileEnum(c->opt_host,
5647 NULL,
5648 username,
5650 (uint8_t **)(void *)&i3,
5651 preferred_len,
5652 &entries_read,
5653 &total_entries,
5654 &resume_handle);
5656 if (status != 0) {
5657 goto done;
5660 /* Display results */
5662 d_printf(_(
5663 "\nEnumerating open files on remote server:\n\n"
5664 "\nFileId Opened by Perms Locks Path"
5665 "\n------ --------- ----- ----- ---- \n"));
5666 for (i = 0; i < entries_read; i++) {
5667 display_file_info_3(&i3[i]);
5669 done:
5670 SAFE_FREE(username);
5671 return status;
5675 * 'net rpc file' entrypoint.
5676 * @param argc Standard main() style argc.
5677 * @param argv Standard main() style argv. Initial components are already
5678 * stripped.
5681 int net_rpc_file(struct net_context *c, int argc, const char **argv)
5683 NET_API_STATUS status;
5685 struct functable func[] = {
5687 "close",
5688 rpc_file_close,
5689 NET_TRANSPORT_RPC,
5690 N_("Close opened file"),
5691 N_("net rpc file close\n"
5692 " Close opened file")
5695 "user",
5696 rpc_file_user,
5697 NET_TRANSPORT_RPC,
5698 N_("List files opened by user"),
5699 N_("net rpc file user\n"
5700 " List files opened by user")
5702 #if 0
5704 "info",
5705 rpc_file_info,
5706 NET_TRANSPORT_RPC,
5707 N_("Display information about opened file"),
5708 N_("net rpc file info\n"
5709 " Display information about opened file")
5711 #endif
5712 {NULL, NULL, 0, NULL, NULL}
5715 status = libnetapi_net_init(&c->netapi_ctx);
5716 if (status != 0) {
5717 return -1;
5719 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5720 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5721 if (c->opt_kerberos) {
5722 libnetapi_set_use_kerberos(c->netapi_ctx);
5725 if (argc == 0) {
5726 if (c->display_usage) {
5727 d_printf(_("Usage:\n"));
5728 d_printf(_("net rpc file\n"
5729 " List opened files\n"));
5730 net_display_usage_from_functable(func);
5731 return 0;
5734 return rpc_file_user(c, argc, argv);
5737 return net_run_function(c, argc, argv, "net rpc file", func);
5741 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5743 * All parameters are provided by the run_rpc_command function, except for
5744 * argc, argv which are passed through.
5746 * @param c A net_context structure.
5747 * @param domain_sid The domain sid acquired from the remote server.
5748 * @param cli A cli_state connected to the server.
5749 * @param mem_ctx Talloc context, destroyed on completion of the function.
5750 * @param argc Standard main() style argc.
5751 * @param argv Standard main() style argv. Initial components are already
5752 * stripped.
5754 * @return Normal NTSTATUS return.
5757 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5758 const struct dom_sid *domain_sid,
5759 const char *domain_name,
5760 struct cli_state *cli,
5761 struct rpc_pipe_client *pipe_hnd,
5762 TALLOC_CTX *mem_ctx,
5763 int argc,
5764 const char **argv)
5766 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5767 WERROR result;
5768 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5770 status = dcerpc_initshutdown_Abort(b, mem_ctx, NULL, &result);
5771 if (!NT_STATUS_IS_OK(status)) {
5772 return status;
5774 if (W_ERROR_IS_OK(result)) {
5775 d_printf(_("\nShutdown successfully aborted\n"));
5776 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5777 } else
5778 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5780 return werror_to_ntstatus(result);
5784 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5786 * All parameters are provided by the run_rpc_command function, except for
5787 * argc, argv which are passed through.
5789 * @param c A net_context structure.
5790 * @param domain_sid The domain sid acquired from the remote server.
5791 * @param cli A cli_state connected to the server.
5792 * @param mem_ctx Talloc context, destroyed on completion of the function.
5793 * @param argc Standard main() style argc.
5794 * @param argv Standard main() style argv. Initial components are already
5795 * stripped.
5797 * @return Normal NTSTATUS return.
5800 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5801 const struct dom_sid *domain_sid,
5802 const char *domain_name,
5803 struct cli_state *cli,
5804 struct rpc_pipe_client *pipe_hnd,
5805 TALLOC_CTX *mem_ctx,
5806 int argc,
5807 const char **argv)
5809 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5810 WERROR werr;
5811 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5813 result = dcerpc_winreg_AbortSystemShutdown(b, mem_ctx, NULL, &werr);
5815 if (!NT_STATUS_IS_OK(result)) {
5816 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5817 return result;
5819 if (W_ERROR_IS_OK(werr)) {
5820 d_printf(_("\nShutdown successfully aborted\n"));
5821 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5822 } else
5823 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5825 return werror_to_ntstatus(werr);
5829 * ABORT the shutdown of a remote RPC server.
5831 * @param argc Standard main() style argc.
5832 * @param argv Standard main() style argv. Initial components are already
5833 * stripped.
5835 * @return A shell status integer (0 for success).
5838 static int rpc_shutdown_abort(struct net_context *c, int argc,
5839 const char **argv)
5841 int rc = -1;
5843 if (c->display_usage) {
5844 d_printf( "%s\n"
5845 "net rpc abortshutdown\n"
5846 " %s\n",
5847 _("Usage:"),
5848 _("Abort a scheduled shutdown"));
5849 return 0;
5852 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5853 rpc_shutdown_abort_internals, argc, argv);
5855 if (rc == 0)
5856 return rc;
5858 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5860 return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5861 rpc_reg_shutdown_abort_internals,
5862 argc, argv);
5866 * Shut down a remote RPC Server via initshutdown pipe.
5868 * All parameters are provided by the run_rpc_command function, except for
5869 * argc, argv which are passed through.
5871 * @param c A net_context structure.
5872 * @param domain_sid The domain sid acquired from the remote server.
5873 * @param cli A cli_state connected to the server.
5874 * @param mem_ctx Talloc context, destroyed on completion of the function.
5875 * @param argc Standard main() style argc.
5876 * @param argv Standard main() style argv. Initial components are already
5877 * stripped.
5879 * @return Normal NTSTATUS return.
5882 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5883 const struct dom_sid *domain_sid,
5884 const char *domain_name,
5885 struct cli_state *cli,
5886 struct rpc_pipe_client *pipe_hnd,
5887 TALLOC_CTX *mem_ctx,
5888 int argc,
5889 const char **argv)
5891 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5892 WERROR result;
5893 const char *msg = N_("This machine will be shutdown shortly");
5894 uint32_t timeout = 20;
5895 struct lsa_StringLarge msg_string;
5896 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5898 if (c->opt_comment) {
5899 msg = c->opt_comment;
5901 if (c->opt_timeout) {
5902 timeout = c->opt_timeout;
5905 msg_string.string = msg;
5907 /* create an entry */
5908 status = dcerpc_initshutdown_Init(b, mem_ctx, NULL,
5909 &msg_string, timeout, c->opt_force, c->opt_reboot,
5910 &result);
5911 if (!NT_STATUS_IS_OK(status)) {
5912 return status;
5914 if (W_ERROR_IS_OK(result)) {
5915 d_printf(_("\nShutdown of remote machine succeeded\n"));
5916 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5917 } else {
5918 DEBUG(1,("Shutdown of remote machine failed!\n"));
5920 return werror_to_ntstatus(result);
5924 * Shut down a remote RPC Server via winreg pipe.
5926 * All parameters are provided by the run_rpc_command function, except for
5927 * argc, argv which are passed through.
5929 * @param c A net_context structure.
5930 * @param domain_sid The domain sid acquired from the remote server.
5931 * @param cli A cli_state connected to the server.
5932 * @param mem_ctx Talloc context, destroyed on completion of the function.
5933 * @param argc Standard main() style argc.
5934 * @param argv Standard main() style argv. Initial components are already
5935 * stripped.
5937 * @return Normal NTSTATUS return.
5940 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5941 const struct dom_sid *domain_sid,
5942 const char *domain_name,
5943 struct cli_state *cli,
5944 struct rpc_pipe_client *pipe_hnd,
5945 TALLOC_CTX *mem_ctx,
5946 int argc,
5947 const char **argv)
5949 const char *msg = N_("This machine will be shutdown shortly");
5950 uint32_t timeout = 20;
5951 struct lsa_StringLarge msg_string;
5952 NTSTATUS result;
5953 WERROR werr;
5954 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5956 if (c->opt_comment) {
5957 msg = c->opt_comment;
5959 msg_string.string = msg;
5961 if (c->opt_timeout) {
5962 timeout = c->opt_timeout;
5965 /* create an entry */
5966 result = dcerpc_winreg_InitiateSystemShutdown(b, mem_ctx, NULL,
5967 &msg_string, timeout, c->opt_force, c->opt_reboot,
5968 &werr);
5969 if (!NT_STATUS_IS_OK(result)) {
5970 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5971 return result;
5974 if (W_ERROR_IS_OK(werr)) {
5975 d_printf(_("\nShutdown of remote machine succeeded\n"));
5976 } else {
5977 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5978 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5979 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5980 else
5981 d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5984 return werror_to_ntstatus(werr);
5988 * Shut down a remote RPC server.
5990 * @param argc Standard main() style argc.
5991 * @param argv Standard main() style argv. Initial components are already
5992 * stripped.
5994 * @return A shell status integer (0 for success).
5997 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5999 int rc = -1;
6001 if (c->display_usage) {
6002 d_printf( "%s\n"
6003 "net rpc shutdown\n"
6004 " %s\n",
6005 _("Usage:"),
6006 _("Shut down a remote RPC server"));
6007 return 0;
6010 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
6011 rpc_init_shutdown_internals, argc, argv);
6013 if (rc) {
6014 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
6015 rc = run_rpc_command(c, NULL, &ndr_table_winreg, 0,
6016 rpc_reg_shutdown_internals, argc, argv);
6019 return rc;
6022 /***************************************************************************
6023 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
6024 ***************************************************************************/
6027 * Add interdomain trust account to the RPC server.
6028 * All parameters (except for argc and argv) are passed by run_rpc_command
6029 * function.
6031 * @param c A net_context structure.
6032 * @param domain_sid The domain sid acquired from the server.
6033 * @param cli A cli_state connected to the server.
6034 * @param mem_ctx Talloc context, destroyed on completion of the function.
6035 * @param argc Standard main() style argc.
6036 * @param argv Standard main() style argv. Initial components are already
6037 * stripped.
6039 * @return normal NTSTATUS return code.
6042 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
6043 const struct dom_sid *domain_sid,
6044 const char *domain_name,
6045 struct cli_state *cli,
6046 struct rpc_pipe_client *pipe_hnd,
6047 TALLOC_CTX *mem_ctx,
6048 int argc,
6049 const char **argv)
6051 struct policy_handle connect_pol, domain_pol, user_pol;
6052 NTSTATUS status, result;
6053 char *acct_name;
6054 struct lsa_String lsa_acct_name;
6055 uint32_t acb_info;
6056 uint32_t acct_flags=0;
6057 uint32_t user_rid;
6058 uint32_t access_granted = 0;
6059 union samr_UserInfo info;
6060 unsigned int orig_timeout;
6061 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6062 DATA_BLOB session_key = data_blob_null;
6064 if (argc != 2) {
6065 d_printf("%s\n%s",
6066 _("Usage:"),
6067 _(" net rpc trustdom add <domain_name> "
6068 "<trust password>\n"));
6069 return NT_STATUS_INVALID_PARAMETER;
6073 * Make valid trusting domain account (ie. uppercased and with '$' appended)
6076 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
6077 return NT_STATUS_NO_MEMORY;
6080 if (!strupper_m(acct_name)) {
6081 SAFE_FREE(acct_name);
6082 return NT_STATUS_INVALID_PARAMETER;
6085 init_lsa_String(&lsa_acct_name, acct_name);
6087 status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
6088 if (!NT_STATUS_IS_OK(status)) {
6089 DEBUG(0,("Error getting session_key of SAM pipe. Error was %s\n",
6090 nt_errstr(status)));
6091 goto done;
6094 /* Get samr policy handle */
6095 status = dcerpc_samr_Connect2(b, mem_ctx,
6096 pipe_hnd->desthost,
6097 MAXIMUM_ALLOWED_ACCESS,
6098 &connect_pol,
6099 &result);
6100 if (!NT_STATUS_IS_OK(status)) {
6101 goto done;
6103 if (!NT_STATUS_IS_OK(result)) {
6104 status = result;
6105 goto done;
6108 /* Get domain policy handle */
6109 status = dcerpc_samr_OpenDomain(b, mem_ctx,
6110 &connect_pol,
6111 MAXIMUM_ALLOWED_ACCESS,
6112 discard_const_p(struct dom_sid2, domain_sid),
6113 &domain_pol,
6114 &result);
6115 if (!NT_STATUS_IS_OK(status)) {
6116 goto done;
6118 if (!NT_STATUS_IS_OK(result)) {
6119 status = result;
6120 goto done;
6123 /* This call can take a long time - allow the server to time out.
6124 * 35 seconds should do it. */
6126 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
6128 /* Create trusting domain's account */
6129 acb_info = ACB_NORMAL;
6130 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
6131 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
6132 SAMR_USER_ACCESS_SET_PASSWORD |
6133 SAMR_USER_ACCESS_GET_ATTRIBUTES |
6134 SAMR_USER_ACCESS_SET_ATTRIBUTES;
6136 status = dcerpc_samr_CreateUser2(b, mem_ctx,
6137 &domain_pol,
6138 &lsa_acct_name,
6139 acb_info,
6140 acct_flags,
6141 &user_pol,
6142 &access_granted,
6143 &user_rid,
6144 &result);
6145 if (!NT_STATUS_IS_OK(status)) {
6146 goto done;
6148 /* And restore our original timeout. */
6149 rpccli_set_timeout(pipe_hnd, orig_timeout);
6151 if (!NT_STATUS_IS_OK(result)) {
6152 status = result;
6153 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
6154 acct_name, nt_errstr(result));
6155 goto done;
6159 struct samr_CryptPassword crypt_pwd;
6161 ZERO_STRUCT(info.info23);
6163 init_samr_CryptPassword(argv[1],
6164 &session_key,
6165 &crypt_pwd);
6167 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
6168 SAMR_FIELD_NT_PASSWORD_PRESENT;
6169 info.info23.info.acct_flags = ACB_DOMTRUST;
6170 info.info23.password = crypt_pwd;
6172 status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
6173 &user_pol,
6175 &info,
6176 &result);
6177 if (!NT_STATUS_IS_OK(status)) {
6178 goto done;
6181 if (!NT_STATUS_IS_OK(result)) {
6182 status = result;
6183 DEBUG(0,("Could not set trust account password: %s\n",
6184 nt_errstr(result)));
6185 goto done;
6189 done:
6190 SAFE_FREE(acct_name);
6191 data_blob_clear_free(&session_key);
6192 return status;
6196 * Create interdomain trust account for a remote domain.
6198 * @param argc Standard argc.
6199 * @param argv Standard argv without initial components.
6201 * @return Integer status (0 means success).
6204 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
6206 if (argc > 0 && !c->display_usage) {
6207 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6208 rpc_trustdom_add_internals, argc, argv);
6209 } else {
6210 d_printf("%s\n%s",
6211 _("Usage:"),
6212 _("net rpc trustdom add <domain_name> <trust "
6213 "password>\n"));
6214 return -1;
6220 * Remove interdomain trust account from the RPC server.
6221 * All parameters (except for argc and argv) are passed by run_rpc_command
6222 * function.
6224 * @param c A net_context structure.
6225 * @param domain_sid The domain sid acquired from the server.
6226 * @param cli A cli_state connected to the server.
6227 * @param mem_ctx Talloc context, destroyed on completion of the function.
6228 * @param argc Standard main() style argc.
6229 * @param argv Standard main() style argv. Initial components are already
6230 * stripped.
6232 * @return normal NTSTATUS return code.
6235 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
6236 const struct dom_sid *domain_sid,
6237 const char *domain_name,
6238 struct cli_state *cli,
6239 struct rpc_pipe_client *pipe_hnd,
6240 TALLOC_CTX *mem_ctx,
6241 int argc,
6242 const char **argv)
6244 struct policy_handle connect_pol, domain_pol, user_pol;
6245 NTSTATUS status, result;
6246 char *acct_name;
6247 struct dom_sid trust_acct_sid;
6248 struct samr_Ids user_rids, name_types;
6249 struct lsa_String lsa_acct_name;
6250 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6252 if (argc != 1) {
6253 d_printf("%s\n%s",
6254 _("Usage:"),
6255 _(" net rpc trustdom del <domain_name>\n"));
6256 return NT_STATUS_INVALID_PARAMETER;
6260 * Make valid trusting domain account (ie. uppercased and with '$' appended)
6262 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
6264 if (acct_name == NULL)
6265 return NT_STATUS_NO_MEMORY;
6267 if (!strupper_m(acct_name)) {
6268 TALLOC_FREE(acct_name);
6269 return NT_STATUS_INVALID_PARAMETER;
6272 /* Get samr policy handle */
6273 status = dcerpc_samr_Connect2(b, mem_ctx,
6274 pipe_hnd->desthost,
6275 MAXIMUM_ALLOWED_ACCESS,
6276 &connect_pol,
6277 &result);
6278 if (!NT_STATUS_IS_OK(status)) {
6279 goto done;
6281 if (!NT_STATUS_IS_OK(result)) {
6282 status = result;
6283 goto done;
6286 /* Get domain policy handle */
6287 status = dcerpc_samr_OpenDomain(b, mem_ctx,
6288 &connect_pol,
6289 MAXIMUM_ALLOWED_ACCESS,
6290 discard_const_p(struct dom_sid2, domain_sid),
6291 &domain_pol,
6292 &result);
6293 if (!NT_STATUS_IS_OK(status)) {
6294 goto done;
6296 if (!NT_STATUS_IS_OK(result)) {
6297 status = result;
6298 goto done;
6301 init_lsa_String(&lsa_acct_name, acct_name);
6303 status = dcerpc_samr_LookupNames(b, mem_ctx,
6304 &domain_pol,
6306 &lsa_acct_name,
6307 &user_rids,
6308 &name_types,
6309 &result);
6310 if (!NT_STATUS_IS_OK(status)) {
6311 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6312 "failed %s\n"),
6313 acct_name, nt_errstr(status));
6314 goto done;
6316 if (!NT_STATUS_IS_OK(result)) {
6317 status = result;
6318 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6319 "failed %s\n"),
6320 acct_name, nt_errstr(result) );
6321 goto done;
6323 if (user_rids.count != 1) {
6324 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6325 goto done;
6327 if (name_types.count != 1) {
6328 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6329 goto done;
6332 status = dcerpc_samr_OpenUser(b, mem_ctx,
6333 &domain_pol,
6334 MAXIMUM_ALLOWED_ACCESS,
6335 user_rids.ids[0],
6336 &user_pol,
6337 &result);
6338 if (!NT_STATUS_IS_OK(status)) {
6339 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6340 "%s\n"),
6341 acct_name, nt_errstr(status) );
6342 goto done;
6345 if (!NT_STATUS_IS_OK(result)) {
6346 status = result;
6347 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6348 "%s\n"),
6349 acct_name, nt_errstr(result) );
6350 goto done;
6353 /* append the rid to the domain sid */
6354 if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
6355 goto done;
6358 /* remove the sid */
6360 status = dcerpc_samr_RemoveMemberFromForeignDomain(b, mem_ctx,
6361 &user_pol,
6362 &trust_acct_sid,
6363 &result);
6364 if (!NT_STATUS_IS_OK(status)) {
6365 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6366 " on user %s failed %s\n"),
6367 acct_name, nt_errstr(status));
6368 goto done;
6370 if (!NT_STATUS_IS_OK(result)) {
6371 status = result;
6372 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6373 " on user %s failed %s\n"),
6374 acct_name, nt_errstr(result) );
6375 goto done;
6379 /* Delete user */
6381 status = dcerpc_samr_DeleteUser(b, mem_ctx,
6382 &user_pol,
6383 &result);
6384 if (!NT_STATUS_IS_OK(status)) {
6385 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6386 "%s\n"),
6387 acct_name, nt_errstr(status));
6388 goto done;
6391 if (!NT_STATUS_IS_OK(result)) {
6392 result = status;
6393 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6394 "%s\n"),
6395 acct_name, nt_errstr(result) );
6396 goto done;
6399 if (!NT_STATUS_IS_OK(result)) {
6400 d_printf(_("Could not set trust account password: %s\n"),
6401 nt_errstr(result));
6402 goto done;
6405 done:
6406 return status;
6410 * Delete interdomain trust account for a remote domain.
6412 * @param argc Standard argc.
6413 * @param argv Standard argv without initial components.
6415 * @return Integer status (0 means success).
6418 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
6420 if (argc > 0 && !c->display_usage) {
6421 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6422 rpc_trustdom_del_internals, argc, argv);
6423 } else {
6424 d_printf("%s\n%s",
6425 _("Usage:"),
6426 _("net rpc trustdom del <domain>\n"));
6427 return -1;
6431 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
6432 struct cli_state *cli,
6433 TALLOC_CTX *mem_ctx,
6434 const char *domain_name)
6436 char *dc_name = NULL;
6437 const char *buffer = NULL;
6438 struct rpc_pipe_client *netr;
6439 NTSTATUS status;
6440 WERROR result;
6441 struct dcerpc_binding_handle *b;
6443 /* Use NetServerEnum2 */
6445 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
6446 SAFE_FREE(dc_name);
6447 return NT_STATUS_OK;
6450 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
6451 for domain %s\n", domain_name));
6453 /* Try netr_GetDcName */
6455 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon,
6456 &netr);
6457 if (!NT_STATUS_IS_OK(status)) {
6458 return status;
6461 b = netr->binding_handle;
6463 status = dcerpc_netr_GetDcName(b, mem_ctx,
6464 netr->desthost,
6465 domain_name,
6466 &buffer,
6467 &result);
6468 TALLOC_FREE(netr);
6470 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
6471 return status;
6474 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
6475 for domain %s\n", domain_name));
6477 if (!NT_STATUS_IS_OK(status)) {
6478 return status;
6481 return werror_to_ntstatus(result);
6485 * Establish trust relationship to a trusting domain.
6486 * Interdomain account must already be created on remote PDC.
6488 * @param c A net_context structure.
6489 * @param argc Standard argc.
6490 * @param argv Standard argv without initial components.
6492 * @return Integer status (0 means success).
6495 static int rpc_trustdom_establish(struct net_context *c, int argc,
6496 const char **argv)
6498 struct cli_state *cli = NULL;
6499 struct sockaddr_storage server_ss;
6500 struct rpc_pipe_client *pipe_hnd = NULL;
6501 struct policy_handle connect_hnd;
6502 TALLOC_CTX *mem_ctx;
6503 NTSTATUS nt_status, result;
6504 struct dom_sid *domain_sid;
6506 char* domain_name;
6507 char* acct_name;
6508 fstring pdc_name;
6509 union lsa_PolicyInformation *info = NULL;
6510 struct dcerpc_binding_handle *b;
6513 * Connect to \\server\ipc$ as 'our domain' account with password
6516 if (argc != 1 || c->display_usage) {
6517 d_printf("%s\n%s",
6518 _("Usage:"),
6519 _("net rpc trustdom establish <domain_name>\n"));
6520 return -1;
6523 domain_name = smb_xstrdup(argv[0]);
6524 if (!strupper_m(domain_name)) {
6525 SAFE_FREE(domain_name);
6526 return -1;
6529 /* account name used at first is our domain's name with '$' */
6530 if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
6531 return -1;
6533 if (!strupper_m(acct_name)) {
6534 SAFE_FREE(domain_name);
6535 SAFE_FREE(acct_name);
6536 return -1;
6540 * opt_workgroup will be used by connection functions further,
6541 * hence it should be set to remote domain name instead of ours
6543 if (c->opt_workgroup) {
6544 c->opt_workgroup = smb_xstrdup(domain_name);
6547 c->opt_user_name = acct_name;
6549 /* find the domain controller */
6550 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
6551 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
6552 return -1;
6555 /* connect to ipc$ as username/password */
6556 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
6557 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
6559 /* Is it trusting domain account for sure ? */
6560 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
6561 nt_errstr(nt_status)));
6562 return -1;
6565 /* store who we connected to */
6567 saf_store( domain_name, pdc_name );
6570 * Connect to \\server\ipc$ again (this time anonymously)
6573 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
6574 (char*)pdc_name);
6576 if (NT_STATUS_IS_ERR(nt_status)) {
6577 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
6578 domain_name, nt_errstr(nt_status)));
6579 return -1;
6582 if (!(mem_ctx = talloc_init("establishing trust relationship to "
6583 "domain %s", domain_name))) {
6584 DEBUG(0, ("talloc_init() failed\n"));
6585 cli_shutdown(cli);
6586 return -1;
6589 /* Make sure we're talking to a proper server */
6591 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
6592 if (!NT_STATUS_IS_OK(nt_status)) {
6593 cli_shutdown(cli);
6594 talloc_destroy(mem_ctx);
6595 return -1;
6599 * Call LsaOpenPolicy and LsaQueryInfo
6602 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
6603 &pipe_hnd);
6604 if (!NT_STATUS_IS_OK(nt_status)) {
6605 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
6606 cli_shutdown(cli);
6607 talloc_destroy(mem_ctx);
6608 return -1;
6611 b = pipe_hnd->binding_handle;
6613 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
6614 &connect_hnd);
6615 if (NT_STATUS_IS_ERR(nt_status)) {
6616 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6617 nt_errstr(nt_status)));
6618 cli_shutdown(cli);
6619 talloc_destroy(mem_ctx);
6620 return -1;
6623 /* Querying info level 5 */
6625 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6626 &connect_hnd,
6627 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6628 &info,
6629 &result);
6630 if (NT_STATUS_IS_ERR(nt_status)) {
6631 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6632 nt_errstr(nt_status)));
6633 cli_shutdown(cli);
6634 talloc_destroy(mem_ctx);
6635 return -1;
6637 if (NT_STATUS_IS_ERR(result)) {
6638 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6639 nt_errstr(result)));
6640 cli_shutdown(cli);
6641 talloc_destroy(mem_ctx);
6642 return -1;
6645 domain_sid = info->account_domain.sid;
6647 /* There should be actually query info level 3 (following nt serv behaviour),
6648 but I still don't know if it's _really_ necessary */
6651 * Store the password in secrets db
6654 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6655 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6656 cli_shutdown(cli);
6657 talloc_destroy(mem_ctx);
6658 return -1;
6662 * Close the pipes and clean up
6665 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6666 if (NT_STATUS_IS_ERR(nt_status)) {
6667 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6668 nt_errstr(nt_status)));
6669 cli_shutdown(cli);
6670 talloc_destroy(mem_ctx);
6671 return -1;
6674 cli_shutdown(cli);
6676 talloc_destroy(mem_ctx);
6678 d_printf(_("Trust to domain %s established\n"), domain_name);
6679 return 0;
6683 * Revoke trust relationship to the remote domain.
6685 * @param c A net_context structure.
6686 * @param argc Standard argc.
6687 * @param argv Standard argv without initial components.
6689 * @return Integer status (0 means success).
6692 static int rpc_trustdom_revoke(struct net_context *c, int argc,
6693 const char **argv)
6695 char* domain_name;
6696 int rc = -1;
6698 if (argc < 1 || c->display_usage) {
6699 d_printf("%s\n%s",
6700 _("Usage:"),
6701 _("net rpc trustdom revoke <domain_name>\n"
6702 " Revoke trust relationship\n"
6703 " domain_name\tName of domain to revoke trust\n"));
6704 return -1;
6707 /* generate upper cased domain name */
6708 domain_name = smb_xstrdup(argv[0]);
6709 if (!strupper_m(domain_name)) {
6710 SAFE_FREE(domain_name);
6711 return -1;
6714 /* delete password of the trust */
6715 if (!pdb_del_trusteddom_pw(domain_name)) {
6716 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6717 domain_name));
6718 goto done;
6721 rc = 0;
6722 done:
6723 SAFE_FREE(domain_name);
6724 return rc;
6727 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6728 const struct dom_sid *domain_sid,
6729 const char *domain_name,
6730 struct cli_state *cli,
6731 struct rpc_pipe_client *pipe_hnd,
6732 TALLOC_CTX *mem_ctx,
6733 int argc,
6734 const char **argv)
6736 fstring str_sid;
6737 if (!sid_to_fstring(str_sid, domain_sid)) {
6738 return NT_STATUS_UNSUCCESSFUL;
6740 d_printf("%s\n", str_sid);
6741 return NT_STATUS_OK;
6744 static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
6746 fstring ascii_sid;
6748 /* convert sid into ascii string */
6749 sid_to_fstring(ascii_sid, dom_sid);
6751 d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
6754 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6755 TALLOC_CTX *mem_ctx,
6756 struct policy_handle *pol,
6757 struct dom_sid dom_sid,
6758 const char *trusted_dom_name)
6760 NTSTATUS nt_status, result;
6761 union lsa_TrustedDomainInfo *info = NULL;
6762 char *cleartextpwd = NULL;
6763 DATA_BLOB session_key;
6764 DATA_BLOB data = data_blob_null;
6765 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6767 nt_status = dcerpc_lsa_QueryTrustedDomainInfoBySid(b, mem_ctx,
6768 pol,
6769 &dom_sid,
6770 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6771 &info,
6772 &result);
6773 if (NT_STATUS_IS_ERR(nt_status)) {
6774 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6775 nt_errstr(nt_status)));
6776 goto done;
6778 if (NT_STATUS_IS_ERR(result)) {
6779 nt_status = result;
6780 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6781 nt_errstr(result)));
6782 goto done;
6785 data = data_blob(info->password.password->data,
6786 info->password.password->length);
6788 nt_status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
6789 if (!NT_STATUS_IS_OK(nt_status)) {
6790 DEBUG(0, ("Could not retrieve session key: %s\n", nt_errstr(nt_status)));
6791 goto done;
6794 cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key);
6795 data_blob_free(&session_key);
6797 if (cleartextpwd == NULL) {
6798 DEBUG(0,("retrieved NULL password\n"));
6799 nt_status = NT_STATUS_UNSUCCESSFUL;
6800 goto done;
6803 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6804 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6805 nt_status = NT_STATUS_UNSUCCESSFUL;
6806 goto done;
6809 #ifdef DEBUG_PASSWORD
6810 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
6811 "password: [%s]\n", trusted_dom_name,
6812 sid_string_dbg(&dom_sid), cleartextpwd));
6813 #endif
6815 done:
6816 SAFE_FREE(cleartextpwd);
6817 data_blob_free(&data);
6819 return nt_status;
6822 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6823 const char **argv)
6825 /* common variables */
6826 TALLOC_CTX* mem_ctx;
6827 struct cli_state *cli = NULL;
6828 struct rpc_pipe_client *pipe_hnd = NULL;
6829 NTSTATUS nt_status, result;
6830 const char *domain_name = NULL;
6831 struct policy_handle connect_hnd;
6832 union lsa_PolicyInformation *info = NULL;
6834 /* trusted domains listing variables */
6835 unsigned int enum_ctx = 0;
6836 int i;
6837 struct lsa_DomainList dom_list;
6838 fstring pdc_name;
6839 struct dcerpc_binding_handle *b;
6841 if (c->display_usage) {
6842 d_printf( "%s\n"
6843 "net rpc trustdom vampire\n"
6844 " %s\n",
6845 _("Usage:"),
6846 _("Vampire trust relationship from remote server"));
6847 return 0;
6851 * Listing trusted domains (stored in secrets.tdb, if local)
6854 mem_ctx = talloc_init("trust relationships vampire");
6857 * set domain and pdc name to local samba server (default)
6858 * or to remote one given in command line
6861 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6862 domain_name = c->opt_workgroup;
6863 c->opt_target_workgroup = c->opt_workgroup;
6864 } else {
6865 fstrcpy(pdc_name, lp_netbios_name());
6866 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6867 c->opt_target_workgroup = domain_name;
6870 /* open \PIPE\lsarpc and open policy handle */
6871 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6872 if (!NT_STATUS_IS_OK(nt_status)) {
6873 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6874 nt_errstr(nt_status)));
6875 talloc_destroy(mem_ctx);
6876 return -1;
6879 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
6880 &pipe_hnd);
6881 if (!NT_STATUS_IS_OK(nt_status)) {
6882 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6883 nt_errstr(nt_status) ));
6884 cli_shutdown(cli);
6885 talloc_destroy(mem_ctx);
6886 return -1;
6889 b = pipe_hnd->binding_handle;
6891 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6892 &connect_hnd);
6893 if (NT_STATUS_IS_ERR(nt_status)) {
6894 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6895 nt_errstr(nt_status)));
6896 cli_shutdown(cli);
6897 talloc_destroy(mem_ctx);
6898 return -1;
6901 /* query info level 5 to obtain sid of a domain being queried */
6902 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6903 &connect_hnd,
6904 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6905 &info,
6906 &result);
6908 if (NT_STATUS_IS_ERR(nt_status)) {
6909 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6910 nt_errstr(nt_status)));
6911 cli_shutdown(cli);
6912 talloc_destroy(mem_ctx);
6913 return -1;
6915 if (NT_STATUS_IS_ERR(result)) {
6916 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6917 nt_errstr(result)));
6918 cli_shutdown(cli);
6919 talloc_destroy(mem_ctx);
6920 return -1;
6924 * Keep calling LsaEnumTrustdom over opened pipe until
6925 * the end of enumeration is reached
6928 d_printf(_("Vampire trusted domains:\n\n"));
6930 do {
6931 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
6932 &connect_hnd,
6933 &enum_ctx,
6934 &dom_list,
6935 (uint32_t)-1,
6936 &result);
6937 if (NT_STATUS_IS_ERR(nt_status)) {
6938 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6939 nt_errstr(nt_status)));
6940 cli_shutdown(cli);
6941 talloc_destroy(mem_ctx);
6942 return -1;
6944 if (NT_STATUS_IS_ERR(result)) {
6945 nt_status = result;
6946 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6947 nt_errstr(result)));
6948 cli_shutdown(cli);
6949 talloc_destroy(mem_ctx);
6950 return -1;
6954 for (i = 0; i < dom_list.count; i++) {
6956 print_trusted_domain(dom_list.domains[i].sid,
6957 dom_list.domains[i].name.string);
6959 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
6960 *dom_list.domains[i].sid,
6961 dom_list.domains[i].name.string);
6962 if (!NT_STATUS_IS_OK(nt_status)) {
6963 cli_shutdown(cli);
6964 talloc_destroy(mem_ctx);
6965 return -1;
6970 * in case of no trusted domains say something rather
6971 * than just display blank line
6973 if (!dom_list.count) d_printf(_("none\n"));
6975 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6977 /* close this connection before doing next one */
6978 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6979 if (NT_STATUS_IS_ERR(nt_status)) {
6980 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6981 nt_errstr(nt_status)));
6982 cli_shutdown(cli);
6983 talloc_destroy(mem_ctx);
6984 return -1;
6987 /* close lsarpc pipe and connection to IPC$ */
6988 cli_shutdown(cli);
6990 talloc_destroy(mem_ctx);
6991 return 0;
6994 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6996 /* common variables */
6997 TALLOC_CTX* mem_ctx;
6998 struct cli_state *cli = NULL, *remote_cli = NULL;
6999 struct rpc_pipe_client *pipe_hnd = NULL;
7000 NTSTATUS nt_status, result;
7001 const char *domain_name = NULL;
7002 struct dom_sid *queried_dom_sid;
7003 int ascii_dom_name_len;
7004 struct policy_handle connect_hnd;
7005 union lsa_PolicyInformation *info = NULL;
7006 struct dcerpc_binding_handle *b = NULL;
7008 /* trusted domains listing variables */
7009 unsigned int num_domains, enum_ctx = 0;
7010 int i;
7011 struct lsa_DomainList dom_list;
7012 fstring pdc_name;
7013 bool found_domain;
7015 /* trusting domains listing variables */
7016 struct policy_handle domain_hnd;
7017 struct samr_SamArray *trusts = NULL;
7019 if (c->display_usage) {
7020 d_printf( "%s\n"
7021 "net rpc trustdom list\n"
7022 " %s\n",
7023 _("Usage:"),
7024 _("List incoming and outgoing trust relationships"));
7025 return 0;
7029 * Listing trusted domains (stored in secrets.tdb, if local)
7032 mem_ctx = talloc_init("trust relationships listing");
7035 * set domain and pdc name to local samba server (default)
7036 * or to remote one given in command line
7039 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
7040 domain_name = c->opt_workgroup;
7041 c->opt_target_workgroup = c->opt_workgroup;
7042 } else {
7043 fstrcpy(pdc_name, lp_netbios_name());
7044 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
7045 c->opt_target_workgroup = domain_name;
7048 /* open \PIPE\lsarpc and open policy handle */
7049 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
7050 if (!NT_STATUS_IS_OK(nt_status)) {
7051 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
7052 nt_errstr(nt_status)));
7053 talloc_destroy(mem_ctx);
7054 return -1;
7057 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
7058 &pipe_hnd);
7059 if (!NT_STATUS_IS_OK(nt_status)) {
7060 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
7061 nt_errstr(nt_status) ));
7062 cli_shutdown(cli);
7063 talloc_destroy(mem_ctx);
7064 return -1;
7067 b = pipe_hnd->binding_handle;
7069 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
7070 &connect_hnd);
7071 if (NT_STATUS_IS_ERR(nt_status)) {
7072 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
7073 nt_errstr(nt_status)));
7074 cli_shutdown(cli);
7075 talloc_destroy(mem_ctx);
7076 return -1;
7079 /* query info level 5 to obtain sid of a domain being queried */
7080 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
7081 &connect_hnd,
7082 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
7083 &info,
7084 &result);
7086 if (NT_STATUS_IS_ERR(nt_status)) {
7087 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
7088 nt_errstr(nt_status)));
7089 cli_shutdown(cli);
7090 talloc_destroy(mem_ctx);
7091 return -1;
7093 if (NT_STATUS_IS_ERR(result)) {
7094 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
7095 nt_errstr(result)));
7096 cli_shutdown(cli);
7097 talloc_destroy(mem_ctx);
7098 return -1;
7101 queried_dom_sid = info->account_domain.sid;
7104 * Keep calling LsaEnumTrustdom over opened pipe until
7105 * the end of enumeration is reached
7108 d_printf(_("Trusted domains list:\n\n"));
7110 found_domain = false;
7112 do {
7113 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
7114 &connect_hnd,
7115 &enum_ctx,
7116 &dom_list,
7117 (uint32_t)-1,
7118 &result);
7119 if (NT_STATUS_IS_ERR(nt_status)) {
7120 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7121 nt_errstr(nt_status)));
7122 cli_shutdown(cli);
7123 talloc_destroy(mem_ctx);
7124 return -1;
7126 if (NT_STATUS_IS_ERR(result)) {
7127 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7128 nt_errstr(result)));
7129 cli_shutdown(cli);
7130 talloc_destroy(mem_ctx);
7131 return -1;
7135 for (i = 0; i < dom_list.count; i++) {
7136 print_trusted_domain(dom_list.domains[i].sid,
7137 dom_list.domains[i].name.string);
7138 found_domain = true;
7142 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
7145 * in case of no trusted domains say something rather
7146 * than just display blank line
7148 if (!found_domain) {
7149 d_printf(_("none\n"));
7152 /* close this connection before doing next one */
7153 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
7154 if (NT_STATUS_IS_ERR(nt_status)) {
7155 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
7156 nt_errstr(nt_status)));
7157 cli_shutdown(cli);
7158 talloc_destroy(mem_ctx);
7159 return -1;
7162 TALLOC_FREE(pipe_hnd);
7165 * Listing trusting domains (stored in passdb backend, if local)
7168 d_printf(_("\nTrusting domains list:\n\n"));
7171 * Open \PIPE\samr and get needed policy handles
7173 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr,
7174 &pipe_hnd);
7175 if (!NT_STATUS_IS_OK(nt_status)) {
7176 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
7177 cli_shutdown(cli);
7178 talloc_destroy(mem_ctx);
7179 return -1;
7182 b = pipe_hnd->binding_handle;
7184 /* SamrConnect2 */
7185 nt_status = dcerpc_samr_Connect2(b, mem_ctx,
7186 pipe_hnd->desthost,
7187 SAMR_ACCESS_LOOKUP_DOMAIN,
7188 &connect_hnd,
7189 &result);
7190 if (!NT_STATUS_IS_OK(nt_status)) {
7191 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
7192 nt_errstr(nt_status)));
7193 cli_shutdown(cli);
7194 talloc_destroy(mem_ctx);
7195 return -1;
7197 if (!NT_STATUS_IS_OK(result)) {
7198 nt_status = result;
7199 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
7200 nt_errstr(result)));
7201 cli_shutdown(cli);
7202 talloc_destroy(mem_ctx);
7203 return -1;
7206 /* SamrOpenDomain - we have to open domain policy handle in order to be
7207 able to enumerate accounts*/
7208 nt_status = dcerpc_samr_OpenDomain(b, mem_ctx,
7209 &connect_hnd,
7210 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
7211 queried_dom_sid,
7212 &domain_hnd,
7213 &result);
7214 if (!NT_STATUS_IS_OK(nt_status)) {
7215 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7216 nt_errstr(nt_status)));
7217 cli_shutdown(cli);
7218 talloc_destroy(mem_ctx);
7219 return -1;
7221 if (!NT_STATUS_IS_OK(result)) {
7222 nt_status = result;
7223 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7224 nt_errstr(result)));
7225 cli_shutdown(cli);
7226 talloc_destroy(mem_ctx);
7227 return -1;
7231 * perform actual enumeration
7234 found_domain = false;
7236 enum_ctx = 0; /* reset enumeration context from last enumeration */
7237 do {
7239 nt_status = dcerpc_samr_EnumDomainUsers(b, mem_ctx,
7240 &domain_hnd,
7241 &enum_ctx,
7242 ACB_DOMTRUST,
7243 &trusts,
7244 0xffff,
7245 &num_domains,
7246 &result);
7247 if (NT_STATUS_IS_ERR(nt_status)) {
7248 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7249 nt_errstr(nt_status)));
7250 cli_shutdown(cli);
7251 talloc_destroy(mem_ctx);
7252 return -1;
7254 if (NT_STATUS_IS_ERR(result)) {
7255 nt_status = result;
7256 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7257 nt_errstr(result)));
7258 cli_shutdown(cli);
7259 talloc_destroy(mem_ctx);
7260 return -1;
7263 for (i = 0; i < num_domains; i++) {
7265 char *str = discard_const_p(char, trusts->entries[i].name.string);
7267 found_domain = true;
7270 * get each single domain's sid (do we _really_ need this ?):
7271 * 1) connect to domain's pdc
7272 * 2) query the pdc for domain's sid
7275 /* get rid of '$' tail */
7276 ascii_dom_name_len = strlen(str);
7277 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
7278 str[ascii_dom_name_len - 1] = '\0';
7280 /* set opt_* variables to remote domain */
7281 if (!strupper_m(str)) {
7282 cli_shutdown(cli);
7283 talloc_destroy(mem_ctx);
7284 return -1;
7286 c->opt_workgroup = talloc_strdup(mem_ctx, str);
7287 c->opt_target_workgroup = c->opt_workgroup;
7289 d_printf("%-20s", str);
7291 /* connect to remote domain controller */
7292 nt_status = net_make_ipc_connection(c,
7293 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
7294 &remote_cli);
7295 if (NT_STATUS_IS_OK(nt_status)) {
7296 /* query for domain's sid */
7297 if (run_rpc_command(
7298 c, remote_cli,
7299 &ndr_table_lsarpc, 0,
7300 rpc_query_domain_sid, argc,
7301 argv))
7302 d_printf(_("strange - couldn't get domain's sid\n"));
7304 cli_shutdown(remote_cli);
7306 } else {
7307 d_fprintf(stderr, _("domain controller is not "
7308 "responding: %s\n"),
7309 nt_errstr(nt_status));
7310 d_printf(_("couldn't get domain's sid\n"));
7314 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
7316 if (!found_domain) {
7317 d_printf("none\n");
7320 /* close opened samr and domain policy handles */
7321 nt_status = dcerpc_samr_Close(b, mem_ctx, &domain_hnd, &result);
7322 if (!NT_STATUS_IS_OK(nt_status)) {
7323 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
7326 nt_status = dcerpc_samr_Close(b, mem_ctx, &connect_hnd, &result);
7327 if (!NT_STATUS_IS_OK(nt_status)) {
7328 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
7331 /* close samr pipe and connection to IPC$ */
7332 cli_shutdown(cli);
7334 talloc_destroy(mem_ctx);
7335 return 0;
7339 * Entrypoint for 'net rpc trustdom' code.
7341 * @param argc Standard argc.
7342 * @param argv Standard argv without initial components.
7344 * @return Integer status (0 means success).
7347 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
7349 struct functable func[] = {
7351 "add",
7352 rpc_trustdom_add,
7353 NET_TRANSPORT_RPC,
7354 N_("Add trusting domain's account"),
7355 N_("net rpc trustdom add\n"
7356 " Add trusting domain's account")
7359 "del",
7360 rpc_trustdom_del,
7361 NET_TRANSPORT_RPC,
7362 N_("Remove trusting domain's account"),
7363 N_("net rpc trustdom del\n"
7364 " Remove trusting domain's account")
7367 "establish",
7368 rpc_trustdom_establish,
7369 NET_TRANSPORT_RPC,
7370 N_("Establish outgoing trust relationship"),
7371 N_("net rpc trustdom establish\n"
7372 " Establish outgoing trust relationship")
7375 "revoke",
7376 rpc_trustdom_revoke,
7377 NET_TRANSPORT_RPC,
7378 N_("Revoke outgoing trust relationship"),
7379 N_("net rpc trustdom revoke\n"
7380 " Revoke outgoing trust relationship")
7383 "list",
7384 rpc_trustdom_list,
7385 NET_TRANSPORT_RPC,
7386 N_("List in- and outgoing domain trusts"),
7387 N_("net rpc trustdom list\n"
7388 " List in- and outgoing domain trusts")
7391 "vampire",
7392 rpc_trustdom_vampire,
7393 NET_TRANSPORT_RPC,
7394 N_("Vampire trusts from remote server"),
7395 N_("net rpc trustdom vampire\n"
7396 " Vampire trusts from remote server")
7398 {NULL, NULL, 0, NULL, NULL}
7401 return net_run_function(c, argc, argv, "net rpc trustdom", func);
7405 * Check if a server will take rpc commands
7406 * @param flags Type of server to connect to (PDC, DMB, localhost)
7407 * if the host is not explicitly specified
7408 * @return bool (true means rpc supported)
7410 bool net_rpc_check(struct net_context *c, unsigned flags)
7412 struct cli_state *cli;
7413 bool ret = false;
7414 struct sockaddr_storage server_ss;
7415 char *server_name = NULL;
7416 NTSTATUS status;
7418 /* flags (i.e. server type) may depend on command */
7419 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
7420 return false;
7422 status = cli_connect_nb(server_name, &server_ss, 0, 0x20,
7423 lp_netbios_name(), SMB_SIGNING_IPC_DEFAULT,
7424 0, &cli);
7425 if (!NT_STATUS_IS_OK(status)) {
7426 return false;
7428 status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
7429 PROTOCOL_NT1);
7430 if (!NT_STATUS_IS_OK(status))
7431 goto done;
7432 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1)
7433 goto done;
7435 ret = true;
7436 done:
7437 cli_shutdown(cli);
7438 return ret;
7441 /* dump sam database via samsync rpc calls */
7442 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
7443 if (c->display_usage) {
7444 d_printf( "%s\n"
7445 "net rpc samdump\n"
7446 " %s\n",
7447 _("Usage:"),
7448 _("Dump remote SAM database"));
7449 return 0;
7452 return run_rpc_command(c, NULL, &ndr_table_netlogon,
7453 NET_FLAGS_ANONYMOUS,
7454 rpc_samdump_internals, argc, argv);
7457 /* syncronise sam database via samsync rpc calls */
7458 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
7460 struct functable func[] = {
7462 "ldif",
7463 rpc_vampire_ldif,
7464 NET_TRANSPORT_RPC,
7465 N_("Dump remote SAM database to ldif"),
7466 N_("net rpc vampire ldif\n"
7467 " Dump remote SAM database to LDIF file or "
7468 "stdout")
7471 "keytab",
7472 rpc_vampire_keytab,
7473 NET_TRANSPORT_RPC,
7474 N_("Dump remote SAM database to Kerberos Keytab"),
7475 N_("net rpc vampire keytab\n"
7476 " Dump remote SAM database to Kerberos keytab "
7477 "file")
7480 "passdb",
7481 rpc_vampire_passdb,
7482 NET_TRANSPORT_RPC,
7483 N_("Dump remote SAM database to passdb"),
7484 N_("net rpc vampire passdb\n"
7485 " Dump remote SAM database to passdb")
7488 {NULL, NULL, 0, NULL, NULL}
7491 if (argc == 0) {
7492 if (c->display_usage) {
7493 d_printf( "%s\n"
7494 "net rpc vampire\n"
7495 " %s\n",
7496 _("Usage:"),
7497 _("Vampire remote SAM database"));
7498 return 0;
7501 return rpc_vampire_passdb(c, argc, argv);
7504 return net_run_function(c, argc, argv, "net rpc vampire", func);
7508 * Migrate everything from a print server.
7510 * @param c A net_context structure.
7511 * @param argc Standard main() style argc.
7512 * @param argv Standard main() style argv. Initial components are already
7513 * stripped.
7515 * @return A shell status integer (0 for success).
7517 * The order is important !
7518 * To successfully add drivers the print queues have to exist !
7519 * Applying ACLs should be the last step, because you're easily locked out.
7522 static int rpc_printer_migrate_all(struct net_context *c, int argc,
7523 const char **argv)
7525 int ret;
7527 if (c->display_usage) {
7528 d_printf( "%s\n"
7529 "net rpc printer migrate all\n"
7530 " %s\n",
7531 _("Usage:"),
7532 _("Migrate everything from a print server"));
7533 return 0;
7536 if (!c->opt_host) {
7537 d_printf(_("no server to migrate\n"));
7538 return -1;
7541 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7542 rpc_printer_migrate_printers_internals, argc,
7543 argv);
7544 if (ret)
7545 return ret;
7547 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7548 rpc_printer_migrate_drivers_internals, argc,
7549 argv);
7550 if (ret)
7551 return ret;
7553 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7554 rpc_printer_migrate_forms_internals, argc, argv);
7555 if (ret)
7556 return ret;
7558 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7559 rpc_printer_migrate_settings_internals, argc,
7560 argv);
7561 if (ret)
7562 return ret;
7564 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7565 rpc_printer_migrate_security_internals, argc,
7566 argv);
7571 * Migrate print drivers from a print server.
7573 * @param c A net_context structure.
7574 * @param argc Standard main() style argc.
7575 * @param argv Standard main() style argv. Initial components are already
7576 * stripped.
7578 * @return A shell status integer (0 for success).
7580 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
7581 const char **argv)
7583 if (c->display_usage) {
7584 d_printf( "%s\n"
7585 "net rpc printer migrate drivers\n"
7586 " %s\n",
7587 _("Usage:"),
7588 _("Migrate print-drivers from a print-server"));
7589 return 0;
7592 if (!c->opt_host) {
7593 d_printf(_("no server to migrate\n"));
7594 return -1;
7597 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7598 rpc_printer_migrate_drivers_internals,
7599 argc, argv);
7603 * Migrate print-forms from a print-server.
7605 * @param c A net_context structure.
7606 * @param argc Standard main() style argc.
7607 * @param argv Standard main() style argv. Initial components are already
7608 * stripped.
7610 * @return A shell status integer (0 for success).
7612 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
7613 const char **argv)
7615 if (c->display_usage) {
7616 d_printf( "%s\n"
7617 "net rpc printer migrate forms\n"
7618 " %s\n",
7619 _("Usage:"),
7620 _("Migrate print-forms from a print-server"));
7621 return 0;
7624 if (!c->opt_host) {
7625 d_printf(_("no server to migrate\n"));
7626 return -1;
7629 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7630 rpc_printer_migrate_forms_internals,
7631 argc, argv);
7635 * Migrate printers from a print-server.
7637 * @param c A net_context structure.
7638 * @param argc Standard main() style argc.
7639 * @param argv Standard main() style argv. Initial components are already
7640 * stripped.
7642 * @return A shell status integer (0 for success).
7644 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
7645 const char **argv)
7647 if (c->display_usage) {
7648 d_printf( "%s\n"
7649 "net rpc printer migrate printers\n"
7650 " %s\n",
7651 _("Usage:"),
7652 _("Migrate printers from a print-server"));
7653 return 0;
7656 if (!c->opt_host) {
7657 d_printf(_("no server to migrate\n"));
7658 return -1;
7661 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7662 rpc_printer_migrate_printers_internals,
7663 argc, argv);
7667 * Migrate printer-ACLs from a print-server
7669 * @param c A net_context structure.
7670 * @param argc Standard main() style argc.
7671 * @param argv Standard main() style argv. Initial components are already
7672 * stripped.
7674 * @return A shell status integer (0 for success).
7676 static int rpc_printer_migrate_security(struct net_context *c, int argc,
7677 const char **argv)
7679 if (c->display_usage) {
7680 d_printf( "%s\n"
7681 "net rpc printer migrate security\n"
7682 " %s\n",
7683 _("Usage:"),
7684 _("Migrate printer-ACLs from a print-server"));
7685 return 0;
7688 if (!c->opt_host) {
7689 d_printf(_("no server to migrate\n"));
7690 return -1;
7693 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7694 rpc_printer_migrate_security_internals,
7695 argc, argv);
7699 * Migrate printer-settings from a print-server.
7701 * @param c A net_context structure.
7702 * @param argc Standard main() style argc.
7703 * @param argv Standard main() style argv. Initial components are already
7704 * stripped.
7706 * @return A shell status integer (0 for success).
7708 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
7709 const char **argv)
7711 if (c->display_usage) {
7712 d_printf( "%s\n"
7713 "net rpc printer migrate settings\n"
7714 " %s\n",
7715 _("Usage:"),
7716 _("Migrate printer-settings from a "
7717 "print-server"));
7718 return 0;
7721 if (!c->opt_host) {
7722 d_printf(_("no server to migrate\n"));
7723 return -1;
7726 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7727 rpc_printer_migrate_settings_internals,
7728 argc, argv);
7732 * 'net rpc printer' entrypoint.
7734 * @param c A net_context structure.
7735 * @param argc Standard main() style argc.
7736 * @param argv Standard main() style argv. Initial components are already
7737 * stripped.
7740 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
7743 /* ouch: when addriver and setdriver are called from within
7744 rpc_printer_migrate_drivers_internals, the printer-queue already
7745 *has* to exist */
7747 struct functable func[] = {
7749 "all",
7750 rpc_printer_migrate_all,
7751 NET_TRANSPORT_RPC,
7752 N_("Migrate all from remote to local print server"),
7753 N_("net rpc printer migrate all\n"
7754 " Migrate all from remote to local print server")
7757 "drivers",
7758 rpc_printer_migrate_drivers,
7759 NET_TRANSPORT_RPC,
7760 N_("Migrate drivers to local server"),
7761 N_("net rpc printer migrate drivers\n"
7762 " Migrate drivers to local server")
7765 "forms",
7766 rpc_printer_migrate_forms,
7767 NET_TRANSPORT_RPC,
7768 N_("Migrate froms to local server"),
7769 N_("net rpc printer migrate forms\n"
7770 " Migrate froms to local server")
7773 "printers",
7774 rpc_printer_migrate_printers,
7775 NET_TRANSPORT_RPC,
7776 N_("Migrate printers to local server"),
7777 N_("net rpc printer migrate printers\n"
7778 " Migrate printers to local server")
7781 "security",
7782 rpc_printer_migrate_security,
7783 NET_TRANSPORT_RPC,
7784 N_("Mirgate printer ACLs to local server"),
7785 N_("net rpc printer migrate security\n"
7786 " Mirgate printer ACLs to local server")
7789 "settings",
7790 rpc_printer_migrate_settings,
7791 NET_TRANSPORT_RPC,
7792 N_("Migrate printer settings to local server"),
7793 N_("net rpc printer migrate settings\n"
7794 " Migrate printer settings to local server")
7796 {NULL, NULL, 0, NULL, NULL}
7799 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7804 * List printers on a remote RPC server.
7806 * @param c A net_context structure.
7807 * @param argc Standard main() style argc.
7808 * @param argv Standard main() style argv. Initial components are already
7809 * stripped.
7811 * @return A shell status integer (0 for success).
7813 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7815 if (c->display_usage) {
7816 d_printf( "%s\n"
7817 "net rpc printer list\n"
7818 " %s\n",
7819 _("Usage:"),
7820 _("List printers on a remote RPC server"));
7821 return 0;
7824 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7825 rpc_printer_list_internals,
7826 argc, argv);
7830 * List printer-drivers on a remote RPC server.
7832 * @param c A net_context structure.
7833 * @param argc Standard main() style argc.
7834 * @param argv Standard main() style argv. Initial components are already
7835 * stripped.
7837 * @return A shell status integer (0 for success).
7839 static int rpc_printer_driver_list(struct net_context *c, int argc,
7840 const char **argv)
7842 if (c->display_usage) {
7843 d_printf( "%s\n"
7844 "net rpc printer driver\n"
7845 " %s\n",
7846 _("Usage:"),
7847 _("List printer-drivers on a remote RPC server"));
7848 return 0;
7851 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7852 rpc_printer_driver_list_internals,
7853 argc, argv);
7857 * Publish printer in ADS via MSRPC.
7859 * @param c A net_context structure.
7860 * @param argc Standard main() style argc.
7861 * @param argv Standard main() style argv. Initial components are already
7862 * stripped.
7864 * @return A shell status integer (0 for success).
7866 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7867 const char **argv)
7869 if (c->display_usage) {
7870 d_printf( "%s\n"
7871 "net rpc printer publish publish\n"
7872 " %s\n",
7873 _("Usage:"),
7874 _("Publish printer in ADS via MSRPC"));
7875 return 0;
7878 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7879 rpc_printer_publish_publish_internals,
7880 argc, argv);
7884 * Update printer in ADS via MSRPC.
7886 * @param c A net_context structure.
7887 * @param argc Standard main() style argc.
7888 * @param argv Standard main() style argv. Initial components are already
7889 * stripped.
7891 * @return A shell status integer (0 for success).
7893 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7895 if (c->display_usage) {
7896 d_printf( "%s\n"
7897 "net rpc printer publish update\n"
7898 " %s\n",
7899 _("Usage:"),
7900 _("Update printer in ADS via MSRPC"));
7901 return 0;
7904 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7905 rpc_printer_publish_update_internals,
7906 argc, argv);
7910 * UnPublish printer in ADS via MSRPC.
7912 * @param c A net_context structure.
7913 * @param argc Standard main() style argc.
7914 * @param argv Standard main() style argv. Initial components are already
7915 * stripped.
7917 * @return A shell status integer (0 for success).
7919 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7920 const char **argv)
7922 if (c->display_usage) {
7923 d_printf( "%s\n"
7924 "net rpc printer publish unpublish\n"
7925 " %s\n",
7926 _("Usage:\n"),
7927 _("UnPublish printer in ADS via MSRPC"));
7928 return 0;
7931 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7932 rpc_printer_publish_unpublish_internals,
7933 argc, argv);
7937 * List published printers via MSRPC.
7939 * @param c A net_context structure.
7940 * @param argc Standard main() style argc.
7941 * @param argv Standard main() style argv. Initial components are already
7942 * stripped.
7944 * @return A shell status integer (0 for success).
7946 static int rpc_printer_publish_list(struct net_context *c, int argc,
7947 const char **argv)
7949 if (c->display_usage) {
7950 d_printf( "%s\n"
7951 "net rpc printer publish list\n"
7952 " %s\n",
7953 _("Usage:"),
7954 _("List published printers via MSRPC"));
7955 return 0;
7958 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7959 rpc_printer_publish_list_internals,
7960 argc, argv);
7965 * Publish printer in ADS.
7967 * @param c A net_context structure.
7968 * @param argc Standard main() style argc.
7969 * @param argv Standard main() style argv. Initial components are already
7970 * stripped.
7972 * @return A shell status integer (0 for success).
7974 static int rpc_printer_publish(struct net_context *c, int argc,
7975 const char **argv)
7978 struct functable func[] = {
7980 "publish",
7981 rpc_printer_publish_publish,
7982 NET_TRANSPORT_RPC,
7983 N_("Publish printer in AD"),
7984 N_("net rpc printer publish publish\n"
7985 " Publish printer in AD")
7988 "update",
7989 rpc_printer_publish_update,
7990 NET_TRANSPORT_RPC,
7991 N_("Update printer in AD"),
7992 N_("net rpc printer publish update\n"
7993 " Update printer in AD")
7996 "unpublish",
7997 rpc_printer_publish_unpublish,
7998 NET_TRANSPORT_RPC,
7999 N_("Unpublish printer"),
8000 N_("net rpc printer publish unpublish\n"
8001 " Unpublish printer")
8004 "list",
8005 rpc_printer_publish_list,
8006 NET_TRANSPORT_RPC,
8007 N_("List published printers"),
8008 N_("net rpc printer publish list\n"
8009 " List published printers")
8011 {NULL, NULL, 0, NULL, NULL}
8014 if (argc == 0) {
8015 if (c->display_usage) {
8016 d_printf(_("Usage:\n"));
8017 d_printf(_("net rpc printer publish\n"
8018 " List published printers\n"
8019 " Alias of net rpc printer publish "
8020 "list\n"));
8021 net_display_usage_from_functable(func);
8022 return 0;
8024 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
8025 rpc_printer_publish_list_internals,
8026 argc, argv);
8029 return net_run_function(c, argc, argv, "net rpc printer publish",func);
8035 * Display rpc printer help page.
8037 * @param c A net_context structure.
8038 * @param argc Standard main() style argc.
8039 * @param argv Standard main() style argv. Initial components are already
8040 * stripped.
8042 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
8044 d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
8045 "\tlists all printers on print-server\n\n"));
8046 d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
8047 "\tlists all printer-drivers on print-server\n\n"));
8048 d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
8049 "\tpublishes printer settings in Active Directory\n"
8050 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
8051 d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
8052 "\n\tmigrates printers from remote to local server\n\n"));
8053 d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
8054 "\n\tmigrates printer-settings from remote to local server\n\n"));
8055 d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
8056 "\n\tmigrates printer-drivers from remote to local server\n\n"));
8057 d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
8058 "\n\tmigrates printer-forms from remote to local server\n\n"));
8059 d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
8060 "\n\tmigrates printer-ACLs from remote to local server\n\n"));
8061 d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
8062 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
8063 "\tremote to local print-server\n\n"));
8064 net_common_methods_usage(c, argc, argv);
8065 net_common_flags_usage(c, argc, argv);
8066 d_printf(_(
8067 "\t-v or --verbose\t\t\tgive verbose output\n"
8068 "\t --destination\t\tmigration target server (default: localhost)\n"));
8070 return -1;
8074 * 'net rpc printer' entrypoint.
8076 * @param c A net_context structure.
8077 * @param argc Standard main() style argc.
8078 * @param argv Standard main() style argv. Initial components are already
8079 * stripped.
8081 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
8083 struct functable func[] = {
8085 "list",
8086 rpc_printer_list,
8087 NET_TRANSPORT_RPC,
8088 N_("List all printers on print server"),
8089 N_("net rpc printer list\n"
8090 " List all printers on print server")
8093 "migrate",
8094 rpc_printer_migrate,
8095 NET_TRANSPORT_RPC,
8096 N_("Migrate printer to local server"),
8097 N_("net rpc printer migrate\n"
8098 " Migrate printer to local server")
8101 "driver",
8102 rpc_printer_driver_list,
8103 NET_TRANSPORT_RPC,
8104 N_("List printer drivers"),
8105 N_("net rpc printer driver\n"
8106 " List printer drivers")
8109 "publish",
8110 rpc_printer_publish,
8111 NET_TRANSPORT_RPC,
8112 N_("Publish printer in AD"),
8113 N_("net rpc printer publish\n"
8114 " Publish printer in AD")
8116 {NULL, NULL, 0, NULL, NULL}
8119 if (argc == 0) {
8120 if (c->display_usage) {
8121 d_printf(_("Usage:\n"));
8122 d_printf(_("net rpc printer\n"
8123 " List printers\n"));
8124 net_display_usage_from_functable(func);
8125 return 0;
8127 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
8128 rpc_printer_list_internals,
8129 argc, argv);
8132 return net_run_function(c, argc, argv, "net rpc printer", func);
8136 * 'net rpc' entrypoint.
8138 * @param c A net_context structure.
8139 * @param argc Standard main() style argc.
8140 * @param argv Standard main() style argv. Initial components are already
8141 * stripped.
8144 int net_rpc(struct net_context *c, int argc, const char **argv)
8146 NET_API_STATUS status;
8148 struct functable func[] = {
8150 "audit",
8151 net_rpc_audit,
8152 NET_TRANSPORT_RPC,
8153 N_("Modify global audit settings"),
8154 N_("net rpc audit\n"
8155 " Modify global audit settings")
8158 "info",
8159 net_rpc_info,
8160 NET_TRANSPORT_RPC,
8161 N_("Show basic info about a domain"),
8162 N_("net rpc info\n"
8163 " Show basic info about a domain")
8166 "join",
8167 net_rpc_join,
8168 NET_TRANSPORT_RPC,
8169 N_("Join a domain"),
8170 N_("net rpc join\n"
8171 " Join a domain")
8174 "oldjoin",
8175 net_rpc_oldjoin,
8176 NET_TRANSPORT_RPC,
8177 N_("Join a domain created in server manager"),
8178 N_("net rpc oldjoin\n"
8179 " Join a domain created in server manager")
8182 "testjoin",
8183 net_rpc_testjoin,
8184 NET_TRANSPORT_RPC,
8185 N_("Test that a join is valid"),
8186 N_("net rpc testjoin\n"
8187 " Test that a join is valid")
8190 "user",
8191 net_rpc_user,
8192 NET_TRANSPORT_RPC,
8193 N_("List/modify users"),
8194 N_("net rpc user\n"
8195 " List/modify users")
8198 "password",
8199 rpc_user_password,
8200 NET_TRANSPORT_RPC,
8201 N_("Change a user password"),
8202 N_("net rpc password\n"
8203 " Change a user password\n"
8204 " Alias for net rpc user password")
8207 "group",
8208 net_rpc_group,
8209 NET_TRANSPORT_RPC,
8210 N_("List/modify groups"),
8211 N_("net rpc group\n"
8212 " List/modify groups")
8215 "share",
8216 net_rpc_share,
8217 NET_TRANSPORT_RPC,
8218 N_("List/modify shares"),
8219 N_("net rpc share\n"
8220 " List/modify shares")
8223 "file",
8224 net_rpc_file,
8225 NET_TRANSPORT_RPC,
8226 N_("List open files"),
8227 N_("net rpc file\n"
8228 " List open files")
8231 "printer",
8232 net_rpc_printer,
8233 NET_TRANSPORT_RPC,
8234 N_("List/modify printers"),
8235 N_("net rpc printer\n"
8236 " List/modify printers")
8239 "changetrustpw",
8240 net_rpc_changetrustpw,
8241 NET_TRANSPORT_RPC,
8242 N_("Change trust account password"),
8243 N_("net rpc changetrustpw\n"
8244 " Change trust account password")
8247 "trustdom",
8248 rpc_trustdom,
8249 NET_TRANSPORT_RPC,
8250 N_("Modify domain trusts"),
8251 N_("net rpc trustdom\n"
8252 " Modify domain trusts")
8255 "abortshutdown",
8256 rpc_shutdown_abort,
8257 NET_TRANSPORT_RPC,
8258 N_("Abort a remote shutdown"),
8259 N_("net rpc abortshutdown\n"
8260 " Abort a remote shutdown")
8263 "shutdown",
8264 rpc_shutdown,
8265 NET_TRANSPORT_RPC,
8266 N_("Shutdown a remote server"),
8267 N_("net rpc shutdown\n"
8268 " Shutdown a remote server")
8271 "samdump",
8272 rpc_samdump,
8273 NET_TRANSPORT_RPC,
8274 N_("Dump SAM data of remote NT PDC"),
8275 N_("net rpc samdump\n"
8276 " Dump SAM data of remote NT PDC")
8279 "vampire",
8280 rpc_vampire,
8281 NET_TRANSPORT_RPC,
8282 N_("Sync a remote NT PDC's data into local passdb"),
8283 N_("net rpc vampire\n"
8284 " Sync a remote NT PDC's data into local passdb")
8287 "getsid",
8288 net_rpc_getsid,
8289 NET_TRANSPORT_RPC,
8290 N_("Fetch the domain sid into local secrets.tdb"),
8291 N_("net rpc getsid\n"
8292 " Fetch the domain sid into local secrets.tdb")
8295 "rights",
8296 net_rpc_rights,
8297 NET_TRANSPORT_RPC,
8298 N_("Manage privileges assigned to SID"),
8299 N_("net rpc rights\n"
8300 " Manage privileges assigned to SID")
8303 "service",
8304 net_rpc_service,
8305 NET_TRANSPORT_RPC,
8306 N_("Start/stop/query remote services"),
8307 N_("net rpc service\n"
8308 " Start/stop/query remote services")
8311 "registry",
8312 net_rpc_registry,
8313 NET_TRANSPORT_RPC,
8314 N_("Manage registry hives"),
8315 N_("net rpc registry\n"
8316 " Manage registry hives")
8319 "shell",
8320 net_rpc_shell,
8321 NET_TRANSPORT_RPC,
8322 N_("Open interactive shell on remote server"),
8323 N_("net rpc shell\n"
8324 " Open interactive shell on remote server")
8327 "trust",
8328 net_rpc_trust,
8329 NET_TRANSPORT_RPC,
8330 N_("Manage trusts"),
8331 N_("net rpc trust\n"
8332 " Manage trusts")
8335 "conf",
8336 net_rpc_conf,
8337 NET_TRANSPORT_RPC,
8338 N_("Configure a remote samba server"),
8339 N_("net rpc conf\n"
8340 " Configure a remote samba server")
8342 {NULL, NULL, 0, NULL, NULL}
8345 status = libnetapi_net_init(&c->netapi_ctx);
8346 if (status != 0) {
8347 return -1;
8349 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
8350 libnetapi_set_password(c->netapi_ctx, c->opt_password);
8351 if (c->opt_kerberos) {
8352 libnetapi_set_use_kerberos(c->netapi_ctx);
8354 if (c->opt_ccache) {
8355 libnetapi_set_use_ccache(c->netapi_ctx);
8358 return net_run_function(c, argc, argv, "net rpc", func);