vfstext: Use just one messaging_context in vfstest
[Samba.git] / source3 / utils / net_rpc.c
blob778e888950eaba0dbb1ef1ce8ebad6ff62c41e13
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 DCERPC_AUTH_LEVEL_PRIVACY, 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 DCERPC_AUTH_TYPE_NTLMSSP,
212 DCERPC_AUTH_LEVEL_PRIVACY,
213 smbXcli_conn_remote_name(cli->conn),
214 lp_workgroup(), c->opt_user_name,
215 c->opt_password, &pipe_hnd);
216 } else {
217 nt_status = cli_rpc_pipe_open_noauth(
218 cli, table,
219 &pipe_hnd);
221 if (!NT_STATUS_IS_OK(nt_status)) {
222 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
223 table->name,
224 nt_errstr(nt_status) ));
225 goto fail;
230 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
232 if (!NT_STATUS_IS_OK(nt_status)) {
233 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
234 } else {
235 ret = 0;
236 DEBUG(5, ("rpc command function succedded\n"));
239 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
240 if (pipe_hnd) {
241 TALLOC_FREE(pipe_hnd);
245 fail:
246 /* close the connection only if it was opened here */
247 if (!cli_arg) {
248 cli_shutdown(cli);
251 talloc_destroy(mem_ctx);
252 return ret;
256 * Force a change of the trust acccount password.
258 * All parameters are provided by the run_rpc_command function, except for
259 * argc, argv which are passed through.
261 * @param domain_sid The domain sid acquired from the remote server.
262 * @param cli A cli_state connected to the server.
263 * @param mem_ctx Talloc context, destroyed on completion of the function.
264 * @param argc Standard main() style argc.
265 * @param argv Standard main() style argv. Initial components are already
266 * stripped.
268 * @return Normal NTSTATUS return.
271 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
272 const struct dom_sid *domain_sid,
273 const char *domain_name,
274 struct cli_state *cli,
275 struct rpc_pipe_client *pipe_hnd,
276 TALLOC_CTX *mem_ctx,
277 int argc,
278 const char **argv)
280 NTSTATUS status;
282 status = trust_pw_change(c->netlogon_creds,
283 c->msg_ctx,
284 pipe_hnd->binding_handle,
285 c->opt_target_workgroup,
286 true); /* force */
287 if (!NT_STATUS_IS_OK(status)) {
288 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
289 nt_errstr(status));
290 return status;
293 return NT_STATUS_OK;
297 * Force a change of the trust acccount password.
299 * @param argc Standard main() style argc.
300 * @param argv Standard main() style argv. Initial components are already
301 * stripped.
303 * @return A shell status integer (0 for success).
306 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
308 if (c->display_usage) {
309 d_printf( "%s\n"
310 "net rpc changetrustpw\n"
311 " %s\n",
312 _("Usage:"),
313 _("Change the machine trust password"));
314 return 0;
317 return run_rpc_command(c, NULL, &ndr_table_netlogon,
318 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
319 rpc_changetrustpw_internals,
320 argc, argv);
324 * Join a domain, the old way. This function exists to allow
325 * the message to be displayed when oldjoin was explicitly
326 * requested, but not when it was implied by "net rpc join".
328 * This uses 'machinename' as the inital password, and changes it.
330 * The password should be created with 'server manager' or equiv first.
332 * @param argc Standard main() style argc.
333 * @param argv Standard main() style argv. Initial components are already
334 * stripped.
336 * @return A shell status integer (0 for success).
339 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
341 struct libnet_JoinCtx *r = NULL;
342 TALLOC_CTX *mem_ctx;
343 WERROR werr;
344 const char *domain = lp_workgroup(); /* FIXME */
345 bool modify_config = lp_config_backend_is_registry();
346 enum netr_SchannelType sec_chan_type;
347 char *pw = NULL;
349 if (c->display_usage) {
350 d_printf("Usage:\n"
351 "net rpc oldjoin\n"
352 " Join a domain the old way\n");
353 return 0;
356 mem_ctx = talloc_init("net_rpc_oldjoin");
357 if (!mem_ctx) {
358 return -1;
361 werr = libnet_init_JoinCtx(mem_ctx, &r);
362 if (!W_ERROR_IS_OK(werr)) {
363 goto fail;
367 check what type of join - if the user want's to join as
368 a BDC, the server must agree that we are a BDC.
370 if (argc >= 0) {
371 sec_chan_type = get_sec_channel_type(argv[0]);
372 } else {
373 sec_chan_type = get_sec_channel_type(NULL);
376 if (!c->msg_ctx) {
377 d_fprintf(stderr, _("Could not initialise message context. "
378 "Try running as root\n"));
379 werr = WERR_ACCESS_DENIED;
380 goto fail;
383 pw = talloc_strndup(r, lp_netbios_name(), 14);
384 if (pw == NULL) {
385 werr = WERR_NOMEM;
386 goto fail;
389 r->in.msg_ctx = c->msg_ctx;
390 r->in.domain_name = domain;
391 r->in.secure_channel_type = sec_chan_type;
392 r->in.dc_name = c->opt_host;
393 r->in.admin_account = "";
394 r->in.admin_password = strlower_talloc(r, pw);
395 if (r->in.admin_password == NULL) {
396 werr = WERR_NOMEM;
397 goto fail;
399 r->in.debug = true;
400 r->in.modify_config = modify_config;
401 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
402 WKSSVC_JOIN_FLAGS_JOIN_UNSECURE |
403 WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
405 werr = libnet_Join(mem_ctx, r);
406 if (!W_ERROR_IS_OK(werr)) {
407 goto fail;
410 /* Check the short name of the domain */
412 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
413 d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE());
414 d_printf("domain name obtained from the server.\n");
415 d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name);
416 d_printf("You should set \"workgroup = %s\" in %s.\n",
417 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
420 d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name);
422 if (r->out.dns_domain_name) {
423 d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name,
424 r->out.dns_domain_name);
425 } else {
426 d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name,
427 r->out.netbios_domain_name);
430 TALLOC_FREE(mem_ctx);
432 return 0;
434 fail:
435 if (c->opt_flags & NET_FLAGS_EXPECT_FALLBACK) {
436 goto cleanup;
439 /* issue an overall failure message at the end. */
440 d_fprintf(stderr, _("Failed to join domain: %s\n"),
441 r && r->out.error_string ? r->out.error_string :
442 get_friendly_werror_msg(werr));
444 cleanup:
445 TALLOC_FREE(mem_ctx);
447 return -1;
451 * check that a join is OK
453 * @return A shell status integer (0 for success)
456 int net_rpc_testjoin(struct net_context *c, int argc, const char **argv)
458 NTSTATUS status;
459 TALLOC_CTX *mem_ctx;
460 const char *domain = c->opt_target_workgroup;
461 const char *dc = c->opt_host;
463 if (c->display_usage) {
464 d_printf("Usage\n"
465 "net rpc testjoin\n"
466 " Test if a join is OK\n");
467 return 0;
470 mem_ctx = talloc_init("net_rpc_testjoin");
471 if (!mem_ctx) {
472 return -1;
475 if (!dc) {
476 struct netr_DsRGetDCNameInfo *info;
478 if (!c->msg_ctx) {
479 d_fprintf(stderr, _("Could not initialise message context. "
480 "Try running as root\n"));
481 talloc_destroy(mem_ctx);
482 return -1;
485 status = dsgetdcname(mem_ctx,
486 c->msg_ctx,
487 domain,
488 NULL,
489 NULL,
490 DS_RETURN_DNS_NAME,
491 &info);
492 if (!NT_STATUS_IS_OK(status)) {
493 talloc_destroy(mem_ctx);
494 return -1;
497 dc = strip_hostname(info->dc_unc);
500 /* Display success or failure */
501 status = libnet_join_ok(c->msg_ctx,
502 c->opt_workgroup,
504 c->opt_kerberos);
505 if (!NT_STATUS_IS_OK(status)) {
506 fprintf(stderr,"Join to domain '%s' is not valid: %s\n",
507 domain, nt_errstr(status));
508 talloc_destroy(mem_ctx);
509 return -1;
512 printf("Join to '%s' is OK\n",domain);
513 talloc_destroy(mem_ctx);
515 return 0;
519 * Join a domain using the administrator username and password
521 * @param argc Standard main() style argc
522 * @param argc Standard main() style argv. Initial components are already
523 * stripped. Currently not used.
524 * @return A shell status integer (0 for success)
528 static int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
530 struct libnet_JoinCtx *r = NULL;
531 TALLOC_CTX *mem_ctx;
532 WERROR werr;
533 const char *domain = lp_workgroup(); /* FIXME */
534 bool modify_config = lp_config_backend_is_registry();
535 enum netr_SchannelType sec_chan_type;
537 if (c->display_usage) {
538 d_printf("Usage:\n"
539 "net rpc join\n"
540 " Join a domain the new way\n");
541 return 0;
544 mem_ctx = talloc_init("net_rpc_join_newstyle");
545 if (!mem_ctx) {
546 return -1;
549 werr = libnet_init_JoinCtx(mem_ctx, &r);
550 if (!W_ERROR_IS_OK(werr)) {
551 goto fail;
555 check what type of join - if the user want's to join as
556 a BDC, the server must agree that we are a BDC.
558 if (argc >= 0) {
559 sec_chan_type = get_sec_channel_type(argv[0]);
560 } else {
561 sec_chan_type = get_sec_channel_type(NULL);
564 if (!c->msg_ctx) {
565 d_fprintf(stderr, _("Could not initialise message context. "
566 "Try running as root\n"));
567 werr = WERR_ACCESS_DENIED;
568 goto fail;
571 r->in.msg_ctx = c->msg_ctx;
572 r->in.domain_name = domain;
573 r->in.secure_channel_type = sec_chan_type;
574 r->in.dc_name = c->opt_host;
575 r->in.admin_account = c->opt_user_name;
576 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
577 r->in.debug = true;
578 r->in.use_kerberos = c->opt_kerberos;
579 r->in.modify_config = modify_config;
580 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
581 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
582 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
584 werr = libnet_Join(mem_ctx, r);
585 if (!W_ERROR_IS_OK(werr)) {
586 goto fail;
589 /* Check the short name of the domain */
591 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
592 d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE());
593 d_printf("domain name obtained from the server.\n");
594 d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name);
595 d_printf("You should set \"workgroup = %s\" in %s.\n",
596 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
599 d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name);
601 if (r->out.dns_domain_name) {
602 d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name,
603 r->out.dns_domain_name);
604 } else {
605 d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name,
606 r->out.netbios_domain_name);
609 TALLOC_FREE(mem_ctx);
611 return 0;
613 fail:
614 /* issue an overall failure message at the end. */
615 d_printf("Failed to join domain: %s\n",
616 r && r->out.error_string ? r->out.error_string :
617 get_friendly_werror_msg(werr));
619 TALLOC_FREE(mem_ctx);
621 return -1;
625 * 'net rpc join' entrypoint.
626 * @param argc Standard main() style argc.
627 * @param argv Standard main() style argv. Initial components are already
628 * stripped
630 * Main 'net_rpc_join()' (where the admin username/password is used) is
631 * in net_rpc_join.c.
632 * Try to just change the password, but if that doesn't work, use/prompt
633 * for a username/password.
636 int net_rpc_join(struct net_context *c, int argc, const char **argv)
638 int ret;
640 if (c->display_usage) {
641 d_printf("%s\n%s",
642 _("Usage:"),
643 _("net rpc join -U <username>[%%password] <type>\n"
644 " Join a domain\n"
645 " username\tName of the admin user"
646 " password\tPassword of the admin user, will "
647 "prompt if not specified\n"
648 " type\tCan be one of the following:\n"
649 "\t\tMEMBER\tJoin as member server (default)\n"
650 "\t\tBDC\tJoin as BDC\n"
651 "\t\tPDC\tJoin as PDC\n"));
652 return 0;
655 if (lp_server_role() == ROLE_STANDALONE) {
656 d_printf(_("cannot join as standalone machine\n"));
657 return -1;
660 if (strlen(lp_netbios_name()) > 15) {
661 d_printf(_("Our netbios name can be at most 15 chars long, "
662 "\"%s\" is %u chars long\n"),
663 lp_netbios_name(), (unsigned int)strlen(lp_netbios_name()));
664 return -1;
667 c->opt_flags |= NET_FLAGS_EXPECT_FALLBACK;
668 ret = net_rpc_oldjoin(c, argc, argv);
669 c->opt_flags &= ~NET_FLAGS_EXPECT_FALLBACK;
670 if (ret == 0) {
671 return 0;
674 return net_rpc_join_newstyle(c, argc, argv);
678 * display info about a rpc domain
680 * All parameters are provided by the run_rpc_command function, except for
681 * argc, argv which are passed through.
683 * @param domain_sid The domain sid acquired from the remote server
684 * @param cli A cli_state connected to the server.
685 * @param mem_ctx Talloc context, destroyed on completion of the function.
686 * @param argc Standard main() style argc.
687 * @param argv Standard main() style argv. Initial components are already
688 * stripped.
690 * @return Normal NTSTATUS return.
693 NTSTATUS rpc_info_internals(struct net_context *c,
694 const struct dom_sid *domain_sid,
695 const char *domain_name,
696 struct cli_state *cli,
697 struct rpc_pipe_client *pipe_hnd,
698 TALLOC_CTX *mem_ctx,
699 int argc,
700 const char **argv)
702 struct policy_handle connect_pol, domain_pol;
703 NTSTATUS status, result;
704 union samr_DomainInfo *info = NULL;
705 fstring sid_str;
706 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
708 sid_to_fstring(sid_str, domain_sid);
710 /* Get sam policy handle */
711 status = dcerpc_samr_Connect2(b, mem_ctx,
712 pipe_hnd->desthost,
713 MAXIMUM_ALLOWED_ACCESS,
714 &connect_pol,
715 &result);
716 if (!NT_STATUS_IS_OK(status)) {
717 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
718 nt_errstr(status));
719 goto done;
722 if (!NT_STATUS_IS_OK(result)) {
723 status = result;
724 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
725 nt_errstr(result));
726 goto done;
729 /* Get domain policy handle */
730 status = dcerpc_samr_OpenDomain(b, mem_ctx,
731 &connect_pol,
732 MAXIMUM_ALLOWED_ACCESS,
733 discard_const_p(struct dom_sid2, domain_sid),
734 &domain_pol,
735 &result);
736 if (!NT_STATUS_IS_OK(status)) {
737 d_fprintf(stderr, _("Could not open domain: %s\n"),
738 nt_errstr(status));
739 goto done;
741 if (!NT_STATUS_IS_OK(result)) {
742 status = result;
743 d_fprintf(stderr, _("Could not open domain: %s\n"),
744 nt_errstr(result));
745 goto done;
748 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
749 &domain_pol,
751 &info,
752 &result);
753 if (!NT_STATUS_IS_OK(status)) {
754 goto done;
756 status = result;
757 if (NT_STATUS_IS_OK(result)) {
758 d_printf(_("Domain Name: %s\n"),
759 info->general.domain_name.string);
760 d_printf(_("Domain SID: %s\n"), sid_str);
761 d_printf(_("Sequence number: %llu\n"),
762 (unsigned long long)info->general.sequence_num);
763 d_printf(_("Num users: %u\n"), info->general.num_users);
764 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
765 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
768 done:
769 return status;
773 * 'net rpc info' entrypoint.
774 * @param argc Standard main() style argc.
775 * @param argv Standard main() style argv. Initial components are already
776 * stripped.
779 int net_rpc_info(struct net_context *c, int argc, const char **argv)
781 if (c->display_usage) {
782 d_printf( "%s\n"
783 "net rpc info\n"
784 " %s\n",
785 _("Usage:"),
786 _("Display information about the domain"));
787 return 0;
790 return run_rpc_command(c, NULL, &ndr_table_samr,
791 NET_FLAGS_PDC, rpc_info_internals,
792 argc, argv);
796 * Fetch domain SID into the local secrets.tdb.
798 * All parameters are provided by the run_rpc_command function, except for
799 * argc, argv which are passed through.
801 * @param domain_sid The domain sid acquired from the remote server.
802 * @param cli A cli_state connected to the server.
803 * @param mem_ctx Talloc context, destroyed on completion of the function.
804 * @param argc Standard main() style argc.
805 * @param argv Standard main() style argv. Initial components are already
806 * stripped.
808 * @return Normal NTSTATUS return.
811 static NTSTATUS rpc_getsid_internals(struct net_context *c,
812 const struct dom_sid *domain_sid,
813 const char *domain_name,
814 struct cli_state *cli,
815 struct rpc_pipe_client *pipe_hnd,
816 TALLOC_CTX *mem_ctx,
817 int argc,
818 const char **argv)
820 fstring sid_str;
822 sid_to_fstring(sid_str, domain_sid);
823 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
824 sid_str, domain_name);
826 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
827 DEBUG(0,("Can't store domain SID\n"));
828 return NT_STATUS_UNSUCCESSFUL;
831 return NT_STATUS_OK;
835 * 'net rpc getsid' entrypoint.
836 * @param argc Standard main() style argc.
837 * @param argv Standard main() style argv. Initial components are already
838 * stripped.
841 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
843 int conn_flags = NET_FLAGS_PDC;
845 if (!c->opt_user_specified) {
846 conn_flags |= NET_FLAGS_ANONYMOUS;
849 if (c->display_usage) {
850 d_printf( "%s\n"
851 "net rpc getsid\n"
852 " %s\n",
853 _("Usage:"),
854 _("Fetch domain SID into local secrets.tdb"));
855 return 0;
858 return run_rpc_command(c, NULL, &ndr_table_samr,
859 conn_flags,
860 rpc_getsid_internals,
861 argc, argv);
864 /****************************************************************************/
867 * Basic usage function for 'net rpc user'.
868 * @param argc Standard main() style argc.
869 * @param argv Standard main() style argv. Initial components are already
870 * stripped.
873 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
875 return net_user_usage(c, argc, argv);
879 * Add a new user to a remote RPC server.
881 * @param argc Standard main() style argc.
882 * @param argv Standard main() style argv. Initial components are already
883 * stripped.
885 * @return A shell status integer (0 for success).
888 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
890 NET_API_STATUS status;
891 struct USER_INFO_1 info1;
892 uint32_t parm_error = 0;
894 if (argc < 1 || c->display_usage) {
895 rpc_user_usage(c, argc, argv);
896 return 0;
899 ZERO_STRUCT(info1);
901 info1.usri1_name = argv[0];
902 if (argc == 2) {
903 info1.usri1_password = argv[1];
906 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
908 if (status != 0) {
909 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
910 argv[0], libnetapi_get_error_string(c->netapi_ctx,
911 status));
912 return -1;
913 } else {
914 d_printf(_("Added user '%s'.\n"), argv[0]);
917 return 0;
921 * Rename a user on a remote RPC server.
923 * @param argc Standard main() style argc.
924 * @param argv Standard main() style argv. Initial components are already
925 * stripped.
927 * @return A shell status integer (0 for success).
930 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
932 NET_API_STATUS status;
933 struct USER_INFO_0 u0;
934 uint32_t parm_err = 0;
936 if (argc != 2 || c->display_usage) {
937 rpc_user_usage(c, argc, argv);
938 return 0;
941 u0.usri0_name = argv[1];
943 status = NetUserSetInfo(c->opt_host, argv[0],
944 0, (uint8_t *)&u0, &parm_err);
945 if (status) {
946 d_fprintf(stderr,
947 _("Failed to rename user from %s to %s - %s\n"),
948 argv[0], argv[1],
949 libnetapi_get_error_string(c->netapi_ctx, status));
950 } else {
951 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
954 return status;
958 * Set a user's primary group
960 * @param argc Standard main() style argc.
961 * @param argv Standard main() style argv. Initial components are already
962 * stripped.
964 * @return A shell status integer (0 for success).
967 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
968 const char **argv)
970 NET_API_STATUS status;
971 uint8_t *buffer;
972 struct GROUP_INFO_2 *g2;
973 struct USER_INFO_1051 u1051;
974 uint32_t parm_err = 0;
976 if (argc != 2 || c->display_usage) {
977 rpc_user_usage(c, argc, argv);
978 return 0;
981 status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
982 if (status) {
983 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
984 argv[1],
985 libnetapi_get_error_string(c->netapi_ctx, status));
986 return status;
988 g2 = (struct GROUP_INFO_2 *)buffer;
990 u1051.usri1051_primary_group_id = g2->grpi2_group_id;
992 NetApiBufferFree(buffer);
994 status = NetUserSetInfo(c->opt_host, argv[0], 1051,
995 (uint8_t *)&u1051, &parm_err);
996 if (status) {
997 d_fprintf(stderr,
998 _("Failed to set user's primary group %s to %s - "
999 "%s\n"), argv[0], argv[1],
1000 libnetapi_get_error_string(c->netapi_ctx, status));
1001 } else {
1002 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
1003 argv[1]);
1005 return status;
1009 * Delete a user from a remote RPC server.
1011 * @param argc Standard main() style argc.
1012 * @param argv Standard main() style argv. Initial components are already
1013 * stripped.
1015 * @return A shell status integer (0 for success).
1018 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
1020 NET_API_STATUS status;
1022 if (argc < 1 || c->display_usage) {
1023 rpc_user_usage(c, argc, argv);
1024 return 0;
1027 status = NetUserDel(c->opt_host, argv[0]);
1029 if (status != 0) {
1030 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
1031 argv[0],
1032 libnetapi_get_error_string(c->netapi_ctx, status));
1033 return -1;
1034 } else {
1035 d_printf(_("Deleted user '%s'.\n"), argv[0]);
1038 return 0;
1042 * Set a user's password on a remote RPC server.
1044 * @param argc Standard main() style argc.
1045 * @param argv Standard main() style argv. Initial components are already
1046 * stripped.
1048 * @return A shell status integer (0 for success).
1051 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
1053 NET_API_STATUS status;
1054 char *prompt = NULL;
1055 struct USER_INFO_1003 u1003;
1056 uint32_t parm_err = 0;
1057 int ret;
1059 if (argc < 1 || c->display_usage) {
1060 rpc_user_usage(c, argc, argv);
1061 return 0;
1064 if (argv[1]) {
1065 u1003.usri1003_password = argv[1];
1066 } else {
1067 char pwd[256] = {0};
1068 ret = asprintf(&prompt, _("Enter new password for %s:"),
1069 argv[0]);
1070 if (ret == -1) {
1071 return -1;
1074 ret = samba_getpass(prompt, pwd, sizeof(pwd), false, false);
1075 SAFE_FREE(prompt);
1076 if (ret < 0) {
1077 return -1;
1080 u1003.usri1003_password = talloc_strdup(c, pwd);
1081 if (u1003.usri1003_password == NULL) {
1082 return -1;
1086 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
1088 /* Display results */
1089 if (status != 0) {
1090 d_fprintf(stderr,
1091 _("Failed to set password for '%s' with error: %s.\n"),
1092 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1093 status));
1094 return -1;
1097 return 0;
1101 * List a user's groups from a remote RPC server.
1103 * @param argc Standard main() style argc.
1104 * @param argv Standard main() style argv. Initial components are already
1105 * stripped.
1107 * @return A shell status integer (0 for success)
1110 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
1113 NET_API_STATUS status;
1114 struct GROUP_USERS_INFO_0 *u0 = NULL;
1115 uint32_t entries_read = 0;
1116 uint32_t total_entries = 0;
1117 int i;
1120 if (argc < 1 || c->display_usage) {
1121 rpc_user_usage(c, argc, argv);
1122 return 0;
1125 status = NetUserGetGroups(c->opt_host,
1126 argv[0],
1128 (uint8_t **)(void *)&u0,
1129 (uint32_t)-1,
1130 &entries_read,
1131 &total_entries);
1132 if (status != 0) {
1133 d_fprintf(stderr,
1134 _("Failed to get groups for '%s' with error: %s.\n"),
1135 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1136 status));
1137 return -1;
1140 for (i=0; i < entries_read; i++) {
1141 printf("%s\n", u0->grui0_name);
1142 u0++;
1145 return 0;
1149 * List users on a remote RPC server.
1151 * All parameters are provided by the run_rpc_command function, except for
1152 * argc, argv which are passed through.
1154 * @param domain_sid The domain sid acquired from the remote server.
1155 * @param cli A cli_state connected to the server.
1156 * @param mem_ctx Talloc context, destroyed on completion of the function.
1157 * @param argc Standard main() style argc.
1158 * @param argv Standard main() style argv. Initial components are already
1159 * stripped.
1161 * @return Normal NTSTATUS return.
1164 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
1166 NET_API_STATUS status;
1167 uint32_t start_idx=0, num_entries, i, loop_count = 0;
1168 struct NET_DISPLAY_USER *info = NULL;
1169 void *buffer = NULL;
1171 /* Query domain users */
1172 if (c->opt_long_list_entries)
1173 d_printf(_("\nUser name Comment"
1174 "\n-----------------------------\n"));
1175 do {
1176 uint32_t max_entries, max_size;
1178 dcerpc_get_query_dispinfo_params(
1179 loop_count, &max_entries, &max_size);
1181 status = NetQueryDisplayInformation(c->opt_host,
1183 start_idx,
1184 max_entries,
1185 max_size,
1186 &num_entries,
1187 &buffer);
1188 if (status != 0 && status != ERROR_MORE_DATA) {
1189 return status;
1192 info = (struct NET_DISPLAY_USER *)buffer;
1194 for (i = 0; i < num_entries; i++) {
1196 if (c->opt_long_list_entries)
1197 printf("%-21.21s %s\n", info->usri1_name,
1198 info->usri1_comment);
1199 else
1200 printf("%s\n", info->usri1_name);
1201 info++;
1204 NetApiBufferFree(buffer);
1206 loop_count++;
1207 start_idx += num_entries;
1209 } while (status == ERROR_MORE_DATA);
1211 return status;
1215 * 'net rpc user' entrypoint.
1216 * @param argc Standard main() style argc.
1217 * @param argv Standard main() style argv. Initial components are already
1218 * stripped.
1221 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1223 NET_API_STATUS status;
1225 struct functable func[] = {
1227 "add",
1228 rpc_user_add,
1229 NET_TRANSPORT_RPC,
1230 N_("Add specified user"),
1231 N_("net rpc user add\n"
1232 " Add specified user")
1235 "info",
1236 rpc_user_info,
1237 NET_TRANSPORT_RPC,
1238 N_("List domain groups of user"),
1239 N_("net rpc user info\n"
1240 " List domain groups of user")
1243 "delete",
1244 rpc_user_delete,
1245 NET_TRANSPORT_RPC,
1246 N_("Remove specified user"),
1247 N_("net rpc user delete\n"
1248 " Remove specified user")
1251 "password",
1252 rpc_user_password,
1253 NET_TRANSPORT_RPC,
1254 N_("Change user password"),
1255 N_("net rpc user password\n"
1256 " Change user password")
1259 "rename",
1260 rpc_user_rename,
1261 NET_TRANSPORT_RPC,
1262 N_("Rename specified user"),
1263 N_("net rpc user rename\n"
1264 " Rename specified user")
1267 "setprimarygroup",
1268 rpc_user_setprimarygroup,
1269 NET_TRANSPORT_RPC,
1270 "Set a user's primary group",
1271 "net rpc user setprimarygroup\n"
1272 " Set a user's primary group"
1274 {NULL, NULL, 0, NULL, NULL}
1277 status = libnetapi_net_init(&c->netapi_ctx);
1278 if (status != 0) {
1279 return -1;
1281 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1282 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1283 if (c->opt_kerberos) {
1284 libnetapi_set_use_kerberos(c->netapi_ctx);
1287 if (argc == 0) {
1288 if (c->display_usage) {
1289 d_printf( "%s\n"
1290 "net rpc user\n"
1291 " %s\n",
1292 _("Usage:"),
1293 _("List all users"));
1294 net_display_usage_from_functable(func);
1295 return 0;
1298 return rpc_user_list(c, argc, argv);
1301 return net_run_function(c, argc, argv, "net rpc user", func);
1304 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1305 TALLOC_CTX *mem_ctx,
1306 struct rpc_sh_ctx *ctx,
1307 struct rpc_pipe_client *pipe_hnd,
1308 int argc, const char **argv)
1310 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1313 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1314 TALLOC_CTX *mem_ctx,
1315 struct rpc_sh_ctx *ctx,
1316 struct rpc_pipe_client *pipe_hnd,
1317 int argc, const char **argv)
1319 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1322 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1323 TALLOC_CTX *mem_ctx,
1324 struct rpc_sh_ctx *ctx,
1325 struct rpc_pipe_client *pipe_hnd,
1326 int argc, const char **argv,
1327 NTSTATUS (*fn)(
1328 struct net_context *c,
1329 TALLOC_CTX *mem_ctx,
1330 struct rpc_sh_ctx *ctx,
1331 struct rpc_pipe_client *pipe_hnd,
1332 struct policy_handle *user_hnd,
1333 int argc, const char **argv))
1335 struct policy_handle connect_pol, domain_pol, user_pol;
1336 NTSTATUS status, result;
1337 struct dom_sid sid;
1338 uint32 rid;
1339 enum lsa_SidType type;
1340 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1342 if (argc == 0) {
1343 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1344 ctx->whoami);
1345 return NT_STATUS_INVALID_PARAMETER;
1348 ZERO_STRUCT(connect_pol);
1349 ZERO_STRUCT(domain_pol);
1350 ZERO_STRUCT(user_pol);
1352 status = net_rpc_lookup_name(c, mem_ctx, ctx->cli,
1353 argv[0], NULL, NULL, &sid, &type);
1354 if (!NT_STATUS_IS_OK(status)) {
1355 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1356 nt_errstr(status));
1357 goto done;
1360 if (type != SID_NAME_USER) {
1361 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1362 sid_type_lookup(type));
1363 status = NT_STATUS_NO_SUCH_USER;
1364 goto done;
1367 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1368 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1369 status = NT_STATUS_NO_SUCH_USER;
1370 goto done;
1373 status = dcerpc_samr_Connect2(b, mem_ctx,
1374 pipe_hnd->desthost,
1375 MAXIMUM_ALLOWED_ACCESS,
1376 &connect_pol,
1377 &result);
1378 if (!NT_STATUS_IS_OK(status)) {
1379 goto done;
1381 if (!NT_STATUS_IS_OK(result)) {
1382 status = result;
1383 goto done;
1386 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1387 &connect_pol,
1388 MAXIMUM_ALLOWED_ACCESS,
1389 ctx->domain_sid,
1390 &domain_pol,
1391 &result);
1392 if (!NT_STATUS_IS_OK(status)) {
1393 goto done;
1395 if (!NT_STATUS_IS_OK(result)) {
1396 status = result;
1397 goto done;
1400 status = dcerpc_samr_OpenUser(b, mem_ctx,
1401 &domain_pol,
1402 MAXIMUM_ALLOWED_ACCESS,
1403 rid,
1404 &user_pol,
1405 &result);
1406 if (!NT_STATUS_IS_OK(status)) {
1407 goto done;
1409 if (!NT_STATUS_IS_OK(result)) {
1410 status = result;
1411 goto done;
1414 status = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1416 done:
1417 if (is_valid_policy_hnd(&user_pol)) {
1418 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1420 if (is_valid_policy_hnd(&domain_pol)) {
1421 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1423 if (is_valid_policy_hnd(&connect_pol)) {
1424 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
1426 return status;
1429 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1430 TALLOC_CTX *mem_ctx,
1431 struct rpc_sh_ctx *ctx,
1432 struct rpc_pipe_client *pipe_hnd,
1433 struct policy_handle *user_hnd,
1434 int argc, const char **argv)
1436 NTSTATUS status, result;
1437 union samr_UserInfo *info = NULL;
1438 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1440 if (argc != 0) {
1441 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1442 ctx->whoami);
1443 return NT_STATUS_INVALID_PARAMETER;
1446 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1447 user_hnd,
1449 &info,
1450 &result);
1451 if (!NT_STATUS_IS_OK(status)) {
1452 return status;
1454 if (!NT_STATUS_IS_OK(result)) {
1455 return result;
1458 d_printf(_("user rid: %d, group rid: %d\n"),
1459 info->info21.rid,
1460 info->info21.primary_gid);
1462 return result;
1465 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1466 TALLOC_CTX *mem_ctx,
1467 struct rpc_sh_ctx *ctx,
1468 struct rpc_pipe_client *pipe_hnd,
1469 int argc, const char **argv)
1471 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1472 rpc_sh_user_show_internals);
1475 #define FETCHSTR(name, rec) \
1476 do { if (strequal(ctx->thiscmd, name)) { \
1477 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1478 } while (0);
1480 #define SETSTR(name, rec, flag) \
1481 do { if (strequal(ctx->thiscmd, name)) { \
1482 init_lsa_String(&(info->info21.rec), argv[0]); \
1483 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1484 } while (0);
1486 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1487 TALLOC_CTX *mem_ctx,
1488 struct rpc_sh_ctx *ctx,
1489 struct rpc_pipe_client *pipe_hnd,
1490 struct policy_handle *user_hnd,
1491 int argc, const char **argv)
1493 NTSTATUS status, result;
1494 const char *username;
1495 const char *oldval = "";
1496 union samr_UserInfo *info = NULL;
1497 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1499 if (argc > 1) {
1500 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1501 _("Usage:"), ctx->whoami);
1502 return NT_STATUS_INVALID_PARAMETER;
1505 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1506 user_hnd,
1508 &info,
1509 &result);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 return status;
1513 if (!NT_STATUS_IS_OK(result)) {
1514 return result;
1517 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1519 FETCHSTR("fullname", full_name);
1520 FETCHSTR("homedir", home_directory);
1521 FETCHSTR("homedrive", home_drive);
1522 FETCHSTR("logonscript", logon_script);
1523 FETCHSTR("profilepath", profile_path);
1524 FETCHSTR("description", description);
1526 if (argc == 0) {
1527 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1528 goto done;
1531 if (strcmp(argv[0], "NULL") == 0) {
1532 argv[0] = "";
1535 ZERO_STRUCT(info->info21);
1537 SETSTR("fullname", full_name, FULL_NAME);
1538 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1539 SETSTR("homedrive", home_drive, HOME_DRIVE);
1540 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1541 SETSTR("profilepath", profile_path, PROFILE_PATH);
1542 SETSTR("description", description, DESCRIPTION);
1544 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1545 user_hnd,
1547 info,
1548 &result);
1549 if (!NT_STATUS_IS_OK(status)) {
1550 return status;
1553 status = result;
1555 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1556 ctx->thiscmd, oldval, argv[0]);
1558 done:
1560 return status;
1563 #define HANDLEFLG(name, rec) \
1564 do { if (strequal(ctx->thiscmd, name)) { \
1565 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1566 if (newval) { \
1567 newflags = oldflags | ACB_##rec; \
1568 } else { \
1569 newflags = oldflags & ~ACB_##rec; \
1570 } } } while (0);
1572 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1573 TALLOC_CTX *mem_ctx,
1574 struct rpc_sh_ctx *ctx,
1575 struct rpc_pipe_client *pipe_hnd,
1576 int argc, const char **argv)
1578 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1579 rpc_sh_user_str_edit_internals);
1582 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1583 TALLOC_CTX *mem_ctx,
1584 struct rpc_sh_ctx *ctx,
1585 struct rpc_pipe_client *pipe_hnd,
1586 struct policy_handle *user_hnd,
1587 int argc, const char **argv)
1589 NTSTATUS status, result;
1590 const char *username;
1591 const char *oldval = "unknown";
1592 uint32 oldflags, newflags;
1593 bool newval;
1594 union samr_UserInfo *info = NULL;
1595 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1597 if ((argc > 1) ||
1598 ((argc == 1) && !strequal(argv[0], "yes") &&
1599 !strequal(argv[0], "no"))) {
1600 /* TRANSATORS: The yes|no here are program keywords. Please do
1601 not translate. */
1602 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1603 ctx->whoami);
1604 return NT_STATUS_INVALID_PARAMETER;
1607 newval = strequal(argv[0], "yes");
1609 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1610 user_hnd,
1612 &info,
1613 &result);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 return status;
1617 if (!NT_STATUS_IS_OK(result)) {
1618 return result;
1621 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1622 oldflags = info->info21.acct_flags;
1623 newflags = info->info21.acct_flags;
1625 HANDLEFLG("disabled", DISABLED);
1626 HANDLEFLG("pwnotreq", PWNOTREQ);
1627 HANDLEFLG("autolock", AUTOLOCK);
1628 HANDLEFLG("pwnoexp", PWNOEXP);
1630 if (argc == 0) {
1631 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1632 oldval);
1633 goto done;
1636 ZERO_STRUCT(info->info21);
1638 info->info21.acct_flags = newflags;
1639 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1641 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1642 user_hnd,
1644 info,
1645 &result);
1646 if (!NT_STATUS_IS_OK(status)) {
1647 goto done;
1649 status = result;
1650 if (NT_STATUS_IS_OK(result)) {
1651 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1652 ctx->thiscmd, oldval, argv[0]);
1655 done:
1657 return status;
1660 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1661 TALLOC_CTX *mem_ctx,
1662 struct rpc_sh_ctx *ctx,
1663 struct rpc_pipe_client *pipe_hnd,
1664 int argc, const char **argv)
1666 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1667 rpc_sh_user_flag_edit_internals);
1670 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1671 TALLOC_CTX *mem_ctx,
1672 struct rpc_sh_ctx *ctx)
1674 static struct rpc_sh_cmd cmds[] = {
1676 { "fullname", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1677 N_("Show/Set a user's full name") },
1679 { "homedir", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1680 N_("Show/Set a user's home directory") },
1682 { "homedrive", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1683 N_("Show/Set a user's home drive") },
1685 { "logonscript", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1686 N_("Show/Set a user's logon script") },
1688 { "profilepath", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1689 N_("Show/Set a user's profile path") },
1691 { "description", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1692 N_("Show/Set a user's description") },
1694 { "disabled", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1695 N_("Show/Set whether a user is disabled") },
1697 { "autolock", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1698 N_("Show/Set whether a user locked out") },
1700 { "pwnotreq", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1701 N_("Show/Set whether a user does not need a password") },
1703 { "pwnoexp", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1704 N_("Show/Set whether a user's password does not expire") },
1706 { NULL, NULL, 0, NULL, NULL }
1709 return cmds;
1712 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1713 TALLOC_CTX *mem_ctx,
1714 struct rpc_sh_ctx *ctx)
1716 static struct rpc_sh_cmd cmds[] = {
1718 { "list", NULL, &ndr_table_samr, rpc_sh_user_list,
1719 N_("List available users") },
1721 { "info", NULL, &ndr_table_samr, rpc_sh_user_info,
1722 N_("List the domain groups a user is member of") },
1724 { "show", NULL, &ndr_table_samr, rpc_sh_user_show,
1725 N_("Show info about a user") },
1727 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1728 N_("Show/Modify a user's fields") },
1730 { NULL, NULL, 0, NULL, NULL }
1733 return cmds;
1736 /****************************************************************************/
1739 * Basic usage function for 'net rpc group'.
1740 * @param argc Standard main() style argc.
1741 * @param argv Standard main() style argv. Initial components are already
1742 * stripped.
1745 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1747 return net_group_usage(c, argc, argv);
1751 * Delete group on a remote RPC server.
1753 * All parameters are provided by the run_rpc_command function, except for
1754 * argc, argv which are passed through.
1756 * @param domain_sid The domain sid acquired from the remote server.
1757 * @param cli A cli_state connected to the server.
1758 * @param mem_ctx Talloc context, destroyed on completion of the function.
1759 * @param argc Standard main() style argc.
1760 * @param argv Standard main() style argv. Initial components are already
1761 * stripped.
1763 * @return Normal NTSTATUS return.
1766 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1767 const struct dom_sid *domain_sid,
1768 const char *domain_name,
1769 struct cli_state *cli,
1770 struct rpc_pipe_client *pipe_hnd,
1771 TALLOC_CTX *mem_ctx,
1772 int argc,
1773 const char **argv)
1775 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1776 bool group_is_primary = false;
1777 NTSTATUS status, result;
1778 uint32_t group_rid;
1779 struct samr_RidAttrArray *rids = NULL;
1780 /* char **names; */
1781 int i;
1782 /* struct samr_RidWithAttribute *user_gids; */
1783 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1785 struct samr_Ids group_rids, name_types;
1786 struct lsa_String lsa_acct_name;
1787 union samr_UserInfo *info = NULL;
1789 if (argc < 1 || c->display_usage) {
1790 rpc_group_usage(c, argc,argv);
1791 return NT_STATUS_OK; /* ok? */
1794 status = dcerpc_samr_Connect2(b, mem_ctx,
1795 pipe_hnd->desthost,
1796 MAXIMUM_ALLOWED_ACCESS,
1797 &connect_pol,
1798 &result);
1799 if (!NT_STATUS_IS_OK(status)) {
1800 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1801 goto done;
1804 if (!NT_STATUS_IS_OK(result)) {
1805 status = result;
1806 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1807 goto done;
1810 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1811 &connect_pol,
1812 MAXIMUM_ALLOWED_ACCESS,
1813 discard_const_p(struct dom_sid2, domain_sid),
1814 &domain_pol,
1815 &result);
1816 if (!NT_STATUS_IS_OK(status)) {
1817 d_fprintf(stderr, _("Request open_domain failed\n"));
1818 goto done;
1821 if (!NT_STATUS_IS_OK(result)) {
1822 status = result;
1823 d_fprintf(stderr, _("Request open_domain failed\n"));
1824 goto done;
1827 init_lsa_String(&lsa_acct_name, argv[0]);
1829 status = dcerpc_samr_LookupNames(b, mem_ctx,
1830 &domain_pol,
1832 &lsa_acct_name,
1833 &group_rids,
1834 &name_types,
1835 &result);
1836 if (!NT_STATUS_IS_OK(status)) {
1837 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1838 goto done;
1841 if (!NT_STATUS_IS_OK(result)) {
1842 status = result;
1843 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1844 goto done;
1846 if (group_rids.count != 1) {
1847 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1848 goto done;
1850 if (name_types.count != 1) {
1851 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1852 goto done;
1855 switch (name_types.ids[0])
1857 case SID_NAME_DOM_GRP:
1858 status = dcerpc_samr_OpenGroup(b, mem_ctx,
1859 &domain_pol,
1860 MAXIMUM_ALLOWED_ACCESS,
1861 group_rids.ids[0],
1862 &group_pol,
1863 &result);
1864 if (!NT_STATUS_IS_OK(status)) {
1865 d_fprintf(stderr, _("Request open_group failed"));
1866 goto done;
1869 if (!NT_STATUS_IS_OK(result)) {
1870 status = result;
1871 d_fprintf(stderr, _("Request open_group failed"));
1872 goto done;
1875 group_rid = group_rids.ids[0];
1877 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
1878 &group_pol,
1879 &rids,
1880 &result);
1881 if (!NT_STATUS_IS_OK(status)) {
1882 d_fprintf(stderr,
1883 _("Unable to query group members of %s"),
1884 argv[0]);
1885 goto done;
1888 if (!NT_STATUS_IS_OK(result)) {
1889 status = result;
1890 d_fprintf(stderr,
1891 _("Unable to query group members of %s"),
1892 argv[0]);
1893 goto done;
1896 if (c->opt_verbose) {
1897 d_printf(
1898 _("Domain Group %s (rid: %d) has %d members\n"),
1899 argv[0],group_rid, rids->count);
1902 /* Check if group is anyone's primary group */
1903 for (i = 0; i < rids->count; i++)
1905 status = dcerpc_samr_OpenUser(b, mem_ctx,
1906 &domain_pol,
1907 MAXIMUM_ALLOWED_ACCESS,
1908 rids->rids[i],
1909 &user_pol,
1910 &result);
1911 if (!NT_STATUS_IS_OK(status)) {
1912 d_fprintf(stderr,
1913 _("Unable to open group member %d\n"),
1914 rids->rids[i]);
1915 goto done;
1918 if (!NT_STATUS_IS_OK(result)) {
1919 status = result;
1920 d_fprintf(stderr,
1921 _("Unable to open group member %d\n"),
1922 rids->rids[i]);
1923 goto done;
1926 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1927 &user_pol,
1929 &info,
1930 &result);
1931 if (!NT_STATUS_IS_OK(status)) {
1932 d_fprintf(stderr,
1933 _("Unable to lookup userinfo for group "
1934 "member %d\n"),
1935 rids->rids[i]);
1936 goto done;
1939 if (!NT_STATUS_IS_OK(result)) {
1940 status = result;
1941 d_fprintf(stderr,
1942 _("Unable to lookup userinfo for group "
1943 "member %d\n"),
1944 rids->rids[i]);
1945 goto done;
1948 if (info->info21.primary_gid == group_rid) {
1949 if (c->opt_verbose) {
1950 d_printf(_("Group is primary group "
1951 "of %s\n"),
1952 info->info21.account_name.string);
1954 group_is_primary = true;
1957 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1960 if (group_is_primary) {
1961 d_fprintf(stderr, _("Unable to delete group because "
1962 "some of it's members have it as primary "
1963 "group\n"));
1964 status = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1965 goto done;
1968 /* remove all group members */
1969 for (i = 0; i < rids->count; i++)
1971 if (c->opt_verbose)
1972 d_printf(_("Remove group member %d..."),
1973 rids->rids[i]);
1974 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
1975 &group_pol,
1976 rids->rids[i],
1977 &result);
1978 if (!NT_STATUS_IS_OK(status)) {
1979 goto done;
1981 status = result;
1982 if (NT_STATUS_IS_OK(result)) {
1983 if (c->opt_verbose)
1984 d_printf(_("ok\n"));
1985 } else {
1986 if (c->opt_verbose)
1987 d_printf("%s\n", _("failed"));
1988 goto done;
1992 status = dcerpc_samr_DeleteDomainGroup(b, mem_ctx,
1993 &group_pol,
1994 &result);
1995 if (!NT_STATUS_IS_OK(status)) {
1996 break;
1999 status = result;
2001 break;
2002 /* removing a local group is easier... */
2003 case SID_NAME_ALIAS:
2004 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2005 &domain_pol,
2006 MAXIMUM_ALLOWED_ACCESS,
2007 group_rids.ids[0],
2008 &group_pol,
2009 &result);
2010 if (!NT_STATUS_IS_OK(status)) {
2011 d_fprintf(stderr, _("Request open_alias failed\n"));
2012 goto done;
2014 if (!NT_STATUS_IS_OK(result)) {
2015 status = result;
2016 d_fprintf(stderr, _("Request open_alias failed\n"));
2017 goto done;
2020 status = dcerpc_samr_DeleteDomAlias(b, mem_ctx,
2021 &group_pol,
2022 &result);
2023 if (!NT_STATUS_IS_OK(status)) {
2024 break;
2027 status = result;
2029 break;
2030 default:
2031 d_fprintf(stderr, _("%s is of type %s. This command is only "
2032 "for deleting local or global groups\n"),
2033 argv[0],sid_type_lookup(name_types.ids[0]));
2034 status = NT_STATUS_UNSUCCESSFUL;
2035 goto done;
2038 if (NT_STATUS_IS_OK(status)) {
2039 if (c->opt_verbose)
2040 d_printf(_("Deleted %s '%s'\n"),
2041 sid_type_lookup(name_types.ids[0]), argv[0]);
2042 } else {
2043 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
2044 get_friendly_nt_error_msg(status));
2047 done:
2048 return status;
2052 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
2054 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2055 rpc_group_delete_internals, argc,argv);
2058 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
2060 NET_API_STATUS status;
2061 struct GROUP_INFO_1 info1;
2062 uint32_t parm_error = 0;
2064 if (argc != 1 || c->display_usage) {
2065 rpc_group_usage(c, argc, argv);
2066 return 0;
2069 ZERO_STRUCT(info1);
2071 info1.grpi1_name = argv[0];
2072 if (c->opt_comment && strlen(c->opt_comment) > 0) {
2073 info1.grpi1_comment = c->opt_comment;
2076 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
2078 if (status != 0) {
2079 d_fprintf(stderr,
2080 _("Failed to add group '%s' with error: %s.\n"),
2081 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2082 status));
2083 return -1;
2084 } else {
2085 d_printf(_("Added group '%s'.\n"), argv[0]);
2088 return 0;
2091 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
2093 NET_API_STATUS status;
2094 struct LOCALGROUP_INFO_1 info1;
2095 uint32_t parm_error = 0;
2097 if (argc != 1 || c->display_usage) {
2098 rpc_group_usage(c, argc, argv);
2099 return 0;
2102 ZERO_STRUCT(info1);
2104 info1.lgrpi1_name = argv[0];
2105 if (c->opt_comment && strlen(c->opt_comment) > 0) {
2106 info1.lgrpi1_comment = c->opt_comment;
2109 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
2111 if (status != 0) {
2112 d_fprintf(stderr,
2113 _("Failed to add alias '%s' with error: %s.\n"),
2114 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2115 status));
2116 return -1;
2117 } else {
2118 d_printf(_("Added alias '%s'.\n"), argv[0]);
2121 return 0;
2124 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
2126 if (c->opt_localgroup)
2127 return rpc_alias_add_internals(c, argc, argv);
2129 return rpc_group_add_internals(c, argc, argv);
2132 static NTSTATUS get_sid_from_name(struct cli_state *cli,
2133 TALLOC_CTX *mem_ctx,
2134 const char *name,
2135 struct dom_sid *sid,
2136 enum lsa_SidType *type)
2138 struct dom_sid *sids = NULL;
2139 enum lsa_SidType *types = NULL;
2140 struct rpc_pipe_client *pipe_hnd = NULL;
2141 struct policy_handle lsa_pol;
2142 NTSTATUS status, result;
2143 struct dcerpc_binding_handle *b;
2145 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
2146 &pipe_hnd);
2147 if (!NT_STATUS_IS_OK(status)) {
2148 goto done;
2151 b = pipe_hnd->binding_handle;
2153 status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
2154 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2156 if (!NT_STATUS_IS_OK(status)) {
2157 goto done;
2160 status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
2161 &name, NULL, 1, &sids, &types);
2163 if (NT_STATUS_IS_OK(status)) {
2164 sid_copy(sid, &sids[0]);
2165 *type = types[0];
2168 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
2170 done:
2171 if (pipe_hnd) {
2172 TALLOC_FREE(pipe_hnd);
2175 if (!NT_STATUS_IS_OK(status) && (strncasecmp_m(name, "S-", 2) == 0)) {
2177 /* Try as S-1-5-whatever */
2179 struct dom_sid tmp_sid;
2181 if (string_to_sid(&tmp_sid, name)) {
2182 sid_copy(sid, &tmp_sid);
2183 *type = SID_NAME_UNKNOWN;
2184 status = NT_STATUS_OK;
2188 return status;
2191 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
2192 TALLOC_CTX *mem_ctx,
2193 const struct dom_sid *group_sid,
2194 const char *member)
2196 struct policy_handle connect_pol, domain_pol;
2197 NTSTATUS status, result;
2198 uint32 group_rid;
2199 struct policy_handle group_pol;
2200 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2202 struct samr_Ids rids, rid_types;
2203 struct lsa_String lsa_acct_name;
2205 struct dom_sid sid;
2207 sid_copy(&sid, group_sid);
2209 if (!sid_split_rid(&sid, &group_rid)) {
2210 return NT_STATUS_UNSUCCESSFUL;
2213 /* Get sam policy handle */
2214 status = dcerpc_samr_Connect2(b, mem_ctx,
2215 pipe_hnd->desthost,
2216 MAXIMUM_ALLOWED_ACCESS,
2217 &connect_pol,
2218 &result);
2219 if (!NT_STATUS_IS_OK(status)) {
2220 return status;
2222 if (!NT_STATUS_IS_OK(result)) {
2223 return result;
2226 /* Get domain policy handle */
2227 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2228 &connect_pol,
2229 MAXIMUM_ALLOWED_ACCESS,
2230 &sid,
2231 &domain_pol,
2232 &result);
2233 if (!NT_STATUS_IS_OK(status)) {
2234 return status;
2236 if (!NT_STATUS_IS_OK(result)) {
2237 return result;
2240 init_lsa_String(&lsa_acct_name, member);
2242 status = dcerpc_samr_LookupNames(b, mem_ctx,
2243 &domain_pol,
2245 &lsa_acct_name,
2246 &rids,
2247 &rid_types,
2248 &result);
2249 if (!NT_STATUS_IS_OK(status)) {
2250 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2251 member);
2252 goto done;
2255 if (!NT_STATUS_IS_OK(result)) {
2256 status = result;
2257 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2258 member);
2259 goto done;
2261 if (rids.count != 1) {
2262 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2263 goto done;
2265 if (rid_types.count != 1) {
2266 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2267 goto done;
2270 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2271 &domain_pol,
2272 MAXIMUM_ALLOWED_ACCESS,
2273 group_rid,
2274 &group_pol,
2275 &result);
2276 if (!NT_STATUS_IS_OK(status)) {
2277 goto done;
2280 if (!NT_STATUS_IS_OK(result)) {
2281 status = result;
2282 goto done;
2285 status = dcerpc_samr_AddGroupMember(b, mem_ctx,
2286 &group_pol,
2287 rids.ids[0],
2288 0x0005, /* unknown flags */
2289 &result);
2290 if (!NT_STATUS_IS_OK(status)) {
2291 goto done;
2294 status = result;
2296 done:
2297 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2298 return status;
2301 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2302 struct cli_state *cli,
2303 TALLOC_CTX *mem_ctx,
2304 const struct dom_sid *alias_sid,
2305 const char *member)
2307 struct policy_handle connect_pol, domain_pol;
2308 NTSTATUS status, result;
2309 uint32 alias_rid;
2310 struct policy_handle alias_pol;
2311 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2313 struct dom_sid member_sid;
2314 enum lsa_SidType member_type;
2316 struct dom_sid sid;
2318 sid_copy(&sid, alias_sid);
2320 if (!sid_split_rid(&sid, &alias_rid)) {
2321 return NT_STATUS_UNSUCCESSFUL;
2324 result = get_sid_from_name(cli, mem_ctx,
2325 member, &member_sid, &member_type);
2327 if (!NT_STATUS_IS_OK(result)) {
2328 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2329 member);
2330 return result;
2333 /* Get sam policy handle */
2334 status = dcerpc_samr_Connect2(b, mem_ctx,
2335 pipe_hnd->desthost,
2336 MAXIMUM_ALLOWED_ACCESS,
2337 &connect_pol,
2338 &result);
2339 if (!NT_STATUS_IS_OK(status)) {
2340 goto done;
2342 if (!NT_STATUS_IS_OK(result)) {
2343 status = result;
2344 goto done;
2347 /* Get domain policy handle */
2348 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2349 &connect_pol,
2350 MAXIMUM_ALLOWED_ACCESS,
2351 &sid,
2352 &domain_pol,
2353 &result);
2354 if (!NT_STATUS_IS_OK(status)) {
2355 goto done;
2357 if (!NT_STATUS_IS_OK(result)) {
2358 status = result;
2359 goto done;
2362 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2363 &domain_pol,
2364 MAXIMUM_ALLOWED_ACCESS,
2365 alias_rid,
2366 &alias_pol,
2367 &result);
2368 if (!NT_STATUS_IS_OK(status)) {
2369 return status;
2371 if (!NT_STATUS_IS_OK(result)) {
2372 return result;
2375 status = dcerpc_samr_AddAliasMember(b, mem_ctx,
2376 &alias_pol,
2377 &member_sid,
2378 &result);
2379 if (!NT_STATUS_IS_OK(status)) {
2380 return status;
2383 status = result;
2385 done:
2386 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2387 return status;
2390 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2391 const struct dom_sid *domain_sid,
2392 const char *domain_name,
2393 struct cli_state *cli,
2394 struct rpc_pipe_client *pipe_hnd,
2395 TALLOC_CTX *mem_ctx,
2396 int argc,
2397 const char **argv)
2399 struct dom_sid group_sid;
2400 enum lsa_SidType group_type;
2402 if (argc != 2 || c->display_usage) {
2403 d_printf("%s\n%s",
2404 _("Usage:"),
2405 _("net rpc group addmem <group> <member>\n"
2406 " Add a member to a group\n"
2407 " group\tGroup to add member to\n"
2408 " member\tMember to add to group\n"));
2409 return NT_STATUS_UNSUCCESSFUL;
2412 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2413 &group_sid, &group_type))) {
2414 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2415 argv[0]);
2416 return NT_STATUS_UNSUCCESSFUL;
2419 if (group_type == SID_NAME_DOM_GRP) {
2420 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2421 &group_sid, argv[1]);
2423 if (!NT_STATUS_IS_OK(result)) {
2424 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2425 argv[1], argv[0], nt_errstr(result));
2427 return result;
2430 if (group_type == SID_NAME_ALIAS) {
2431 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, cli, mem_ctx,
2432 &group_sid, argv[1]);
2434 if (!NT_STATUS_IS_OK(result)) {
2435 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2436 argv[1], argv[0], nt_errstr(result));
2438 return result;
2441 d_fprintf(stderr, _("Can only add members to global or local groups "
2442 "which %s is not\n"), argv[0]);
2444 return NT_STATUS_UNSUCCESSFUL;
2447 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2449 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2450 rpc_group_addmem_internals,
2451 argc, argv);
2454 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2455 struct rpc_pipe_client *pipe_hnd,
2456 TALLOC_CTX *mem_ctx,
2457 const struct dom_sid *group_sid,
2458 const char *member)
2460 struct policy_handle connect_pol, domain_pol;
2461 NTSTATUS status, result;
2462 uint32 group_rid;
2463 struct policy_handle group_pol;
2464 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2466 struct samr_Ids rids, rid_types;
2467 struct lsa_String lsa_acct_name;
2469 struct dom_sid sid;
2471 sid_copy(&sid, group_sid);
2473 if (!sid_split_rid(&sid, &group_rid))
2474 return NT_STATUS_UNSUCCESSFUL;
2476 /* Get sam policy handle */
2477 status = dcerpc_samr_Connect2(b, mem_ctx,
2478 pipe_hnd->desthost,
2479 MAXIMUM_ALLOWED_ACCESS,
2480 &connect_pol,
2481 &result);
2482 if (!NT_STATUS_IS_OK(status)) {
2483 return status;
2485 if (!NT_STATUS_IS_OK(result)) {
2486 return result;
2490 /* Get domain policy handle */
2491 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2492 &connect_pol,
2493 MAXIMUM_ALLOWED_ACCESS,
2494 &sid,
2495 &domain_pol,
2496 &result);
2497 if (!NT_STATUS_IS_OK(status)) {
2498 return status;
2500 if (!NT_STATUS_IS_OK(result)) {
2501 return result;
2504 init_lsa_String(&lsa_acct_name, member);
2506 status = dcerpc_samr_LookupNames(b, mem_ctx,
2507 &domain_pol,
2509 &lsa_acct_name,
2510 &rids,
2511 &rid_types,
2512 &result);
2513 if (!NT_STATUS_IS_OK(status)) {
2514 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2515 member);
2516 goto done;
2519 if (!NT_STATUS_IS_OK(result)) {
2520 status = result;
2521 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2522 member);
2523 goto done;
2525 if (rids.count != 1) {
2526 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2527 goto done;
2529 if (rid_types.count != 1) {
2530 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2531 goto done;
2534 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2535 &domain_pol,
2536 MAXIMUM_ALLOWED_ACCESS,
2537 group_rid,
2538 &group_pol,
2539 &result);
2540 if (!NT_STATUS_IS_OK(status)) {
2541 goto done;
2543 if (!NT_STATUS_IS_OK(result)) {
2544 status = result;
2545 goto done;
2548 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2549 &group_pol,
2550 rids.ids[0],
2551 &result);
2552 if (!NT_STATUS_IS_OK(status)) {
2553 goto done;
2556 status = result;
2557 done:
2558 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2559 return status;
2562 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2563 struct cli_state *cli,
2564 TALLOC_CTX *mem_ctx,
2565 const struct dom_sid *alias_sid,
2566 const char *member)
2568 struct policy_handle connect_pol, domain_pol;
2569 NTSTATUS status, result;
2570 uint32 alias_rid;
2571 struct policy_handle alias_pol;
2572 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2574 struct dom_sid member_sid;
2575 enum lsa_SidType member_type;
2577 struct dom_sid sid;
2579 sid_copy(&sid, alias_sid);
2581 if (!sid_split_rid(&sid, &alias_rid))
2582 return NT_STATUS_UNSUCCESSFUL;
2584 result = get_sid_from_name(cli, mem_ctx,
2585 member, &member_sid, &member_type);
2587 if (!NT_STATUS_IS_OK(result)) {
2588 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2589 member);
2590 return result;
2593 /* Get sam policy handle */
2594 status = dcerpc_samr_Connect2(b, mem_ctx,
2595 pipe_hnd->desthost,
2596 MAXIMUM_ALLOWED_ACCESS,
2597 &connect_pol,
2598 &result);
2599 if (!NT_STATUS_IS_OK(status)) {
2600 goto done;
2602 if (!NT_STATUS_IS_OK(result)) {
2603 status = result;
2604 goto done;
2607 /* Get domain policy handle */
2608 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2609 &connect_pol,
2610 MAXIMUM_ALLOWED_ACCESS,
2611 &sid,
2612 &domain_pol,
2613 &result);
2614 if (!NT_STATUS_IS_OK(status)) {
2615 goto done;
2617 if (!NT_STATUS_IS_OK(result)) {
2618 status = result;
2619 goto done;
2622 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2623 &domain_pol,
2624 MAXIMUM_ALLOWED_ACCESS,
2625 alias_rid,
2626 &alias_pol,
2627 &result);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 return status;
2632 if (!NT_STATUS_IS_OK(result)) {
2633 return result;
2636 status = dcerpc_samr_DeleteAliasMember(b, mem_ctx,
2637 &alias_pol,
2638 &member_sid,
2639 &result);
2641 if (!NT_STATUS_IS_OK(status)) {
2642 return status;
2645 status = result;
2647 done:
2648 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2649 return status;
2652 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2653 const struct dom_sid *domain_sid,
2654 const char *domain_name,
2655 struct cli_state *cli,
2656 struct rpc_pipe_client *pipe_hnd,
2657 TALLOC_CTX *mem_ctx,
2658 int argc,
2659 const char **argv)
2661 struct dom_sid group_sid;
2662 enum lsa_SidType group_type;
2664 if (argc != 2 || c->display_usage) {
2665 d_printf("%s\n%s",
2666 _("Usage:"),
2667 _("net rpc group delmem <group> <member>\n"
2668 " Delete a member from a group\n"
2669 " group\tGroup to delete member from\n"
2670 " member\tMember to delete from group\n"));
2671 return NT_STATUS_UNSUCCESSFUL;
2674 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2675 &group_sid, &group_type))) {
2676 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2677 argv[0]);
2678 return NT_STATUS_UNSUCCESSFUL;
2681 if (group_type == SID_NAME_DOM_GRP) {
2682 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2683 &group_sid, argv[1]);
2685 if (!NT_STATUS_IS_OK(result)) {
2686 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2687 argv[1], argv[0], nt_errstr(result));
2689 return result;
2692 if (group_type == SID_NAME_ALIAS) {
2693 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, cli, mem_ctx,
2694 &group_sid, argv[1]);
2696 if (!NT_STATUS_IS_OK(result)) {
2697 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2698 argv[1], argv[0], nt_errstr(result));
2700 return result;
2703 d_fprintf(stderr, _("Can only delete members from global or local "
2704 "groups which %s is not\n"), argv[0]);
2706 return NT_STATUS_UNSUCCESSFUL;
2709 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2711 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2712 rpc_group_delmem_internals,
2713 argc, argv);
2717 * List groups on a remote RPC server.
2719 * All parameters are provided by the run_rpc_command function, except for
2720 * argc, argv which are passes through.
2722 * @param domain_sid The domain sid acquired from the remote server.
2723 * @param cli A cli_state connected to the server.
2724 * @param mem_ctx Talloc context, destroyed on completion of the function.
2725 * @param argc Standard main() style argc.
2726 * @param argv Standard main() style argv. Initial components are already
2727 * stripped.
2729 * @return Normal NTSTATUS return.
2732 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2733 const struct dom_sid *domain_sid,
2734 const char *domain_name,
2735 struct cli_state *cli,
2736 struct rpc_pipe_client *pipe_hnd,
2737 TALLOC_CTX *mem_ctx,
2738 int argc,
2739 const char **argv)
2741 struct policy_handle connect_pol, domain_pol;
2742 NTSTATUS status, result;
2743 uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2744 struct samr_SamArray *groups = NULL;
2745 bool global = false;
2746 bool local = false;
2747 bool builtin = false;
2748 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2750 if (c->display_usage) {
2751 d_printf("%s\n%s",
2752 _("Usage:"),
2753 _("net rpc group list [global] [local] [builtin]\n"
2754 " List groups on RPC server\n"
2755 " global\tList global groups\n"
2756 " local\tList local groups\n"
2757 " builtin\tList builtin groups\n"
2758 " If none of global, local or builtin is "
2759 "specified, all three options are considered "
2760 "set\n"));
2761 return NT_STATUS_OK;
2764 if (argc == 0) {
2765 global = true;
2766 local = true;
2767 builtin = true;
2770 for (i=0; i<argc; i++) {
2771 if (strequal(argv[i], "global"))
2772 global = true;
2774 if (strequal(argv[i], "local"))
2775 local = true;
2777 if (strequal(argv[i], "builtin"))
2778 builtin = true;
2781 /* Get sam policy handle */
2783 status = dcerpc_samr_Connect2(b, mem_ctx,
2784 pipe_hnd->desthost,
2785 MAXIMUM_ALLOWED_ACCESS,
2786 &connect_pol,
2787 &result);
2788 if (!NT_STATUS_IS_OK(status)) {
2789 goto done;
2791 if (!NT_STATUS_IS_OK(result)) {
2792 status = result;
2793 goto done;
2796 /* Get domain policy handle */
2798 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2799 &connect_pol,
2800 MAXIMUM_ALLOWED_ACCESS,
2801 discard_const_p(struct dom_sid2, domain_sid),
2802 &domain_pol,
2803 &result);
2804 if (!NT_STATUS_IS_OK(status)) {
2805 goto done;
2807 if (!NT_STATUS_IS_OK(result)) {
2808 status = result;
2809 goto done;
2812 /* Query domain groups */
2813 if (c->opt_long_list_entries)
2814 d_printf(_("\nGroup name Comment"
2815 "\n-----------------------------\n"));
2816 do {
2817 uint32_t max_size, total_size, returned_size;
2818 union samr_DispInfo info;
2820 if (!global) break;
2822 dcerpc_get_query_dispinfo_params(
2823 loop_count, &max_entries, &max_size);
2825 status = dcerpc_samr_QueryDisplayInfo(b, mem_ctx,
2826 &domain_pol,
2828 start_idx,
2829 max_entries,
2830 max_size,
2831 &total_size,
2832 &returned_size,
2833 &info,
2834 &result);
2835 if (!NT_STATUS_IS_OK(status)) {
2836 goto done;
2838 num_entries = info.info3.count;
2839 start_idx += info.info3.count;
2841 if (!NT_STATUS_IS_OK(result) &&
2842 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2843 break;
2845 for (i = 0; i < num_entries; i++) {
2847 const char *group = NULL;
2848 const char *desc = NULL;
2850 group = info.info3.entries[i].account_name.string;
2851 desc = info.info3.entries[i].description.string;
2853 if (c->opt_long_list_entries)
2854 printf("%-21.21s %-50.50s\n",
2855 group, desc);
2856 else
2857 printf("%s\n", group);
2859 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2860 /* query domain aliases */
2861 start_idx = 0;
2862 do {
2863 if (!local) break;
2865 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2866 &domain_pol,
2867 &start_idx,
2868 &groups,
2869 0xffff,
2870 &num_entries,
2871 &result);
2872 if (!NT_STATUS_IS_OK(status)) {
2873 goto done;
2875 if (!NT_STATUS_IS_OK(result) &&
2876 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2877 break;
2879 for (i = 0; i < num_entries; i++) {
2881 const char *description = NULL;
2883 if (c->opt_long_list_entries) {
2885 struct policy_handle alias_pol;
2886 union samr_AliasInfo *info = NULL;
2887 NTSTATUS _result;
2889 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2890 &domain_pol,
2891 0x8,
2892 groups->entries[i].idx,
2893 &alias_pol,
2894 &_result);
2895 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2896 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2897 &alias_pol,
2899 &info,
2900 &_result);
2901 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2902 status = dcerpc_samr_Close(b, mem_ctx,
2903 &alias_pol,
2904 &_result);
2905 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2906 description = info->description.string;
2912 if (description != NULL) {
2913 printf("%-21.21s %-50.50s\n",
2914 groups->entries[i].name.string,
2915 description);
2916 } else {
2917 printf("%s\n", groups->entries[i].name.string);
2920 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2921 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
2922 /* Get builtin policy handle */
2924 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2925 &connect_pol,
2926 MAXIMUM_ALLOWED_ACCESS,
2927 discard_const_p(struct dom_sid2, &global_sid_Builtin),
2928 &domain_pol,
2929 &result);
2930 if (!NT_STATUS_IS_OK(status)) {
2931 goto done;
2933 if (!NT_STATUS_IS_OK(result)) {
2934 status = result;
2935 goto done;
2938 /* query builtin aliases */
2939 start_idx = 0;
2940 do {
2941 if (!builtin) break;
2943 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2944 &domain_pol,
2945 &start_idx,
2946 &groups,
2947 max_entries,
2948 &num_entries,
2949 &result);
2950 if (!NT_STATUS_IS_OK(status)) {
2951 break;
2953 if (!NT_STATUS_IS_OK(result) &&
2954 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
2955 status = result;
2956 break;
2959 for (i = 0; i < num_entries; i++) {
2961 const char *description = NULL;
2963 if (c->opt_long_list_entries) {
2965 struct policy_handle alias_pol;
2966 union samr_AliasInfo *info = NULL;
2967 NTSTATUS _result;
2969 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2970 &domain_pol,
2971 0x8,
2972 groups->entries[i].idx,
2973 &alias_pol,
2974 &_result);
2975 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2976 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2977 &alias_pol,
2979 &info,
2980 &_result);
2981 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2982 status = dcerpc_samr_Close(b, mem_ctx,
2983 &alias_pol,
2984 &_result);
2985 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2986 description = info->description.string;
2992 if (description != NULL) {
2993 printf("%-21.21s %-50.50s\n",
2994 groups->entries[i].name.string,
2995 description);
2996 } else {
2997 printf("%s\n", groups->entries[i].name.string);
3000 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3002 status = result;
3004 done:
3005 return status;
3008 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
3010 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3011 rpc_group_list_internals,
3012 argc, argv);
3015 static NTSTATUS rpc_list_group_members(struct net_context *c,
3016 struct rpc_pipe_client *pipe_hnd,
3017 TALLOC_CTX *mem_ctx,
3018 const char *domain_name,
3019 const struct dom_sid *domain_sid,
3020 struct policy_handle *domain_pol,
3021 uint32 rid)
3023 NTSTATUS result, status;
3024 struct policy_handle group_pol;
3025 uint32 num_members, *group_rids;
3026 int i;
3027 struct samr_RidAttrArray *rids = NULL;
3028 struct lsa_Strings names;
3029 struct samr_Ids types;
3030 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3032 fstring sid_str;
3033 sid_to_fstring(sid_str, domain_sid);
3035 status = dcerpc_samr_OpenGroup(b, mem_ctx,
3036 domain_pol,
3037 MAXIMUM_ALLOWED_ACCESS,
3038 rid,
3039 &group_pol,
3040 &result);
3041 if (!NT_STATUS_IS_OK(status)) {
3042 return status;
3044 if (!NT_STATUS_IS_OK(result)) {
3045 return result;
3048 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
3049 &group_pol,
3050 &rids,
3051 &result);
3052 if (!NT_STATUS_IS_OK(status)) {
3053 return status;
3055 if (!NT_STATUS_IS_OK(result)) {
3056 return result;
3059 num_members = rids->count;
3060 group_rids = rids->rids;
3062 while (num_members > 0) {
3063 int this_time = 512;
3065 if (num_members < this_time)
3066 this_time = num_members;
3068 status = dcerpc_samr_LookupRids(b, mem_ctx,
3069 domain_pol,
3070 this_time,
3071 group_rids,
3072 &names,
3073 &types,
3074 &result);
3075 if (!NT_STATUS_IS_OK(status)) {
3076 return status;
3078 if (!NT_STATUS_IS_OK(result)) {
3079 return result;
3081 if (names.count != this_time) {
3082 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3084 if (types.count != this_time) {
3085 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3087 /* We only have users as members, but make the output
3088 the same as the output of alias members */
3090 for (i = 0; i < this_time; i++) {
3092 if (c->opt_long_list_entries) {
3093 printf("%s-%d %s\\%s %d\n", sid_str,
3094 group_rids[i], domain_name,
3095 names.names[i].string,
3096 SID_NAME_USER);
3097 } else {
3098 printf("%s\\%s\n", domain_name,
3099 names.names[i].string);
3103 num_members -= this_time;
3104 group_rids += 512;
3107 return NT_STATUS_OK;
3110 static NTSTATUS rpc_list_alias_members(struct net_context *c,
3111 struct rpc_pipe_client *pipe_hnd,
3112 struct cli_state *cli,
3113 TALLOC_CTX *mem_ctx,
3114 struct policy_handle *domain_pol,
3115 uint32 rid)
3117 NTSTATUS result, status;
3118 struct rpc_pipe_client *lsa_pipe;
3119 struct policy_handle alias_pol, lsa_pol;
3120 uint32 num_members;
3121 struct dom_sid *alias_sids;
3122 char **domains;
3123 char **names;
3124 enum lsa_SidType *types;
3125 int i;
3126 struct lsa_SidArray sid_array;
3127 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3129 status = dcerpc_samr_OpenAlias(b, mem_ctx,
3130 domain_pol,
3131 MAXIMUM_ALLOWED_ACCESS,
3132 rid,
3133 &alias_pol,
3134 &result);
3135 if (!NT_STATUS_IS_OK(status)) {
3136 return status;
3138 if (!NT_STATUS_IS_OK(result)) {
3139 return result;
3142 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
3143 &alias_pol,
3144 &sid_array,
3145 &result);
3146 if (!NT_STATUS_IS_OK(status)) {
3147 d_fprintf(stderr, _("Couldn't list alias members\n"));
3148 return status;
3150 if (!NT_STATUS_IS_OK(result)) {
3151 d_fprintf(stderr, _("Couldn't list alias members\n"));
3152 return result;
3155 num_members = sid_array.num_sids;
3157 if (num_members == 0) {
3158 return NT_STATUS_OK;
3161 result = cli_rpc_pipe_open_noauth(cli,
3162 &ndr_table_lsarpc,
3163 &lsa_pipe);
3164 if (!NT_STATUS_IS_OK(result)) {
3165 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
3166 nt_errstr(result) );
3167 return result;
3170 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
3171 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
3173 if (!NT_STATUS_IS_OK(result)) {
3174 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
3175 TALLOC_FREE(lsa_pipe);
3176 return result;
3179 alias_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
3180 if (!alias_sids) {
3181 d_fprintf(stderr, _("Out of memory\n"));
3182 TALLOC_FREE(lsa_pipe);
3183 return NT_STATUS_NO_MEMORY;
3186 for (i=0; i<num_members; i++) {
3187 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
3190 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
3191 num_members, alias_sids,
3192 &domains, &names, &types);
3194 if (!NT_STATUS_IS_OK(result) &&
3195 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
3196 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
3197 TALLOC_FREE(lsa_pipe);
3198 return result;
3201 for (i = 0; i < num_members; i++) {
3202 fstring sid_str;
3203 sid_to_fstring(sid_str, &alias_sids[i]);
3205 if (c->opt_long_list_entries) {
3206 printf("%s %s\\%s %d\n", sid_str,
3207 domains[i] ? domains[i] : _("*unknown*"),
3208 names[i] ? names[i] : _("*unknown*"), types[i]);
3209 } else {
3210 if (domains[i])
3211 printf("%s\\%s\n", domains[i], names[i]);
3212 else
3213 printf("%s\n", sid_str);
3217 TALLOC_FREE(lsa_pipe);
3218 return NT_STATUS_OK;
3221 static NTSTATUS rpc_group_members_internals(struct net_context *c,
3222 const struct dom_sid *domain_sid,
3223 const char *domain_name,
3224 struct cli_state *cli,
3225 struct rpc_pipe_client *pipe_hnd,
3226 TALLOC_CTX *mem_ctx,
3227 int argc,
3228 const char **argv)
3230 NTSTATUS result, status;
3231 struct policy_handle connect_pol, domain_pol;
3232 struct samr_Ids rids, rid_types;
3233 struct lsa_String lsa_acct_name;
3234 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3236 /* Get sam policy handle */
3238 status = dcerpc_samr_Connect2(b, mem_ctx,
3239 pipe_hnd->desthost,
3240 MAXIMUM_ALLOWED_ACCESS,
3241 &connect_pol,
3242 &result);
3243 if (!NT_STATUS_IS_OK(status)) {
3244 return status;
3246 if (!NT_STATUS_IS_OK(result)) {
3247 return result;
3250 /* Get domain policy handle */
3252 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3253 &connect_pol,
3254 MAXIMUM_ALLOWED_ACCESS,
3255 discard_const_p(struct dom_sid2, domain_sid),
3256 &domain_pol,
3257 &result);
3258 if (!NT_STATUS_IS_OK(status)) {
3259 return status;
3261 if (!NT_STATUS_IS_OK(result)) {
3262 return result;
3265 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
3267 status = dcerpc_samr_LookupNames(b, mem_ctx,
3268 &domain_pol,
3270 &lsa_acct_name,
3271 &rids,
3272 &rid_types,
3273 &result);
3274 if (!NT_STATUS_IS_OK(status)) {
3275 return status;
3278 if (!NT_STATUS_IS_OK(result)) {
3280 /* Ok, did not find it in the global sam, try with builtin */
3282 struct dom_sid sid_Builtin;
3284 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
3286 sid_copy(&sid_Builtin, &global_sid_Builtin);
3288 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3289 &connect_pol,
3290 MAXIMUM_ALLOWED_ACCESS,
3291 &sid_Builtin,
3292 &domain_pol,
3293 &result);
3294 if (!NT_STATUS_IS_OK(status)) {
3295 return status;
3297 if (!NT_STATUS_IS_OK(result)) {
3298 d_fprintf(stderr, _("Couldn't find group %s\n"),
3299 argv[0]);
3300 return result;
3303 status = dcerpc_samr_LookupNames(b, mem_ctx,
3304 &domain_pol,
3306 &lsa_acct_name,
3307 &rids,
3308 &rid_types,
3309 &result);
3310 if (!NT_STATUS_IS_OK(status)) {
3311 return status;
3313 if (!NT_STATUS_IS_OK(result)) {
3314 d_fprintf(stderr, _("Couldn't find group %s\n"),
3315 argv[0]);
3316 return result;
3320 if (rids.count != 1) {
3321 d_fprintf(stderr, _("Couldn't find group %s\n"),
3322 argv[0]);
3323 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3325 if (rid_types.count != 1) {
3326 d_fprintf(stderr, _("Couldn't find group %s\n"),
3327 argv[0]);
3328 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3332 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
3333 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
3334 domain_sid, &domain_pol,
3335 rids.ids[0]);
3338 if (rid_types.ids[0] == SID_NAME_ALIAS) {
3339 return rpc_list_alias_members(c, pipe_hnd, cli, mem_ctx, &domain_pol,
3340 rids.ids[0]);
3343 return NT_STATUS_NO_SUCH_GROUP;
3346 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
3348 if (argc != 1 || c->display_usage) {
3349 return rpc_group_usage(c, argc, argv);
3352 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3353 rpc_group_members_internals,
3354 argc, argv);
3357 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
3359 NET_API_STATUS status;
3360 struct GROUP_INFO_0 g0;
3361 uint32_t parm_err;
3363 if (argc != 2) {
3364 d_printf(_("Usage:\n"));
3365 d_printf("net rpc group rename group newname\n");
3366 return -1;
3369 g0.grpi0_name = argv[1];
3371 status = NetGroupSetInfo(c->opt_host,
3372 argv[0],
3374 (uint8_t *)&g0,
3375 &parm_err);
3377 if (status != 0) {
3378 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
3379 argv[0], libnetapi_get_error_string(c->netapi_ctx,
3380 status));
3381 return -1;
3384 return 0;
3387 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
3389 if (argc != 2 || c->display_usage) {
3390 return rpc_group_usage(c, argc, argv);
3393 return rpc_group_rename_internals(c, argc, argv);
3397 * 'net rpc group' entrypoint.
3398 * @param argc Standard main() style argc.
3399 * @param argv Standard main() style argv. Initial components are already
3400 * stripped.
3403 int net_rpc_group(struct net_context *c, int argc, const char **argv)
3405 NET_API_STATUS status;
3407 struct functable func[] = {
3409 "add",
3410 rpc_group_add,
3411 NET_TRANSPORT_RPC,
3412 N_("Create specified group"),
3413 N_("net rpc group add\n"
3414 " Create specified group")
3417 "delete",
3418 rpc_group_delete,
3419 NET_TRANSPORT_RPC,
3420 N_("Delete specified group"),
3421 N_("net rpc group delete\n"
3422 " Delete specified group")
3425 "addmem",
3426 rpc_group_addmem,
3427 NET_TRANSPORT_RPC,
3428 N_("Add member to group"),
3429 N_("net rpc group addmem\n"
3430 " Add member to group")
3433 "delmem",
3434 rpc_group_delmem,
3435 NET_TRANSPORT_RPC,
3436 N_("Remove member from group"),
3437 N_("net rpc group delmem\n"
3438 " Remove member from group")
3441 "list",
3442 rpc_group_list,
3443 NET_TRANSPORT_RPC,
3444 N_("List groups"),
3445 N_("net rpc group list\n"
3446 " List groups")
3449 "members",
3450 rpc_group_members,
3451 NET_TRANSPORT_RPC,
3452 N_("List group members"),
3453 N_("net rpc group members\n"
3454 " List group members")
3457 "rename",
3458 rpc_group_rename,
3459 NET_TRANSPORT_RPC,
3460 N_("Rename group"),
3461 N_("net rpc group rename\n"
3462 " Rename group")
3464 {NULL, NULL, 0, NULL, NULL}
3467 status = libnetapi_net_init(&c->netapi_ctx);
3468 if (status != 0) {
3469 return -1;
3471 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
3472 libnetapi_set_password(c->netapi_ctx, c->opt_password);
3473 if (c->opt_kerberos) {
3474 libnetapi_set_use_kerberos(c->netapi_ctx);
3477 if (argc == 0) {
3478 if (c->display_usage) {
3479 d_printf(_("Usage:\n"));
3480 d_printf(_("net rpc group\n"
3481 " Alias for net rpc group list global "
3482 "local builtin\n"));
3483 net_display_usage_from_functable(func);
3484 return 0;
3487 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3488 rpc_group_list_internals,
3489 argc, argv);
3492 return net_run_function(c, argc, argv, "net rpc group", func);
3495 /****************************************************************************/
3497 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
3499 return net_share_usage(c, argc, argv);
3503 * Add a share on a remote RPC server.
3505 * @param argc Standard main() style argc.
3506 * @param argv Standard main() style argv. Initial components are already
3507 * stripped.
3509 * @return A shell status integer (0 for success).
3512 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3514 NET_API_STATUS status;
3515 char *sharename;
3516 char *path;
3517 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3518 uint32 num_users=0, perms=0;
3519 char *password=NULL; /* don't allow a share password */
3520 struct SHARE_INFO_2 i2;
3521 uint32_t parm_error = 0;
3523 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3524 return rpc_share_usage(c, argc, argv);
3527 if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
3528 return -1;
3531 path = strchr(sharename, '=');
3532 if (!path) {
3533 return -1;
3536 *path++ = '\0';
3538 i2.shi2_netname = sharename;
3539 i2.shi2_type = type;
3540 i2.shi2_remark = c->opt_comment;
3541 i2.shi2_permissions = perms;
3542 i2.shi2_max_uses = c->opt_maxusers;
3543 i2.shi2_current_uses = num_users;
3544 i2.shi2_path = path;
3545 i2.shi2_passwd = password;
3547 status = NetShareAdd(c->opt_host,
3549 (uint8_t *)&i2,
3550 &parm_error);
3551 if (status != 0) {
3552 printf(_("NetShareAdd failed with: %s\n"),
3553 libnetapi_get_error_string(c->netapi_ctx, status));
3556 return status;
3560 * Delete a share on a remote RPC server.
3562 * @param domain_sid The domain sid acquired from the remote server.
3563 * @param argc Standard main() style argc.
3564 * @param argv Standard main() style argv. Initial components are already
3565 * stripped.
3567 * @return A shell status integer (0 for success).
3569 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3571 if (argc < 1 || c->display_usage) {
3572 return rpc_share_usage(c, argc, argv);
3575 return NetShareDel(c->opt_host, argv[0], 0);
3579 * Formatted print of share info
3581 * @param r pointer to SHARE_INFO_1 to format
3584 static void display_share_info_1(struct net_context *c,
3585 struct SHARE_INFO_1 *r)
3587 if (c->opt_long_list_entries) {
3588 d_printf("%-12s %-8.8s %-50s\n",
3589 r->shi1_netname,
3590 net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3591 r->shi1_remark);
3592 } else {
3593 d_printf("%s\n", r->shi1_netname);
3597 static WERROR get_share_info(struct net_context *c,
3598 struct rpc_pipe_client *pipe_hnd,
3599 TALLOC_CTX *mem_ctx,
3600 uint32 level,
3601 int argc,
3602 const char **argv,
3603 struct srvsvc_NetShareInfoCtr *info_ctr)
3605 WERROR result;
3606 NTSTATUS status;
3607 union srvsvc_NetShareInfo info;
3608 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3610 /* no specific share requested, enumerate all */
3611 if (argc == 0) {
3613 uint32_t preferred_len = 0xffffffff;
3614 uint32_t total_entries = 0;
3615 uint32_t resume_handle = 0;
3617 info_ctr->level = level;
3619 status = dcerpc_srvsvc_NetShareEnumAll(b, mem_ctx,
3620 pipe_hnd->desthost,
3621 info_ctr,
3622 preferred_len,
3623 &total_entries,
3624 &resume_handle,
3625 &result);
3626 if (!NT_STATUS_IS_OK(status)) {
3627 return ntstatus_to_werror(status);
3629 return result;
3632 /* request just one share */
3633 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
3634 pipe_hnd->desthost,
3635 argv[0],
3636 level,
3637 &info,
3638 &result);
3640 if (!NT_STATUS_IS_OK(status)) {
3641 result = ntstatus_to_werror(status);
3642 goto done;
3645 if (!W_ERROR_IS_OK(result)) {
3646 goto done;
3649 /* construct ctr */
3650 ZERO_STRUCTP(info_ctr);
3652 info_ctr->level = level;
3654 switch (level) {
3655 case 1:
3657 struct srvsvc_NetShareCtr1 *ctr1;
3659 ctr1 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr1);
3660 W_ERROR_HAVE_NO_MEMORY(ctr1);
3662 ctr1->count = 1;
3663 ctr1->array = info.info1;
3665 info_ctr->ctr.ctr1 = ctr1;
3667 break;
3669 case 2:
3671 struct srvsvc_NetShareCtr2 *ctr2;
3673 ctr2 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr2);
3674 W_ERROR_HAVE_NO_MEMORY(ctr2);
3676 ctr2->count = 1;
3677 ctr2->array = info.info2;
3679 info_ctr->ctr.ctr2 = ctr2;
3681 break;
3683 case 502:
3685 struct srvsvc_NetShareCtr502 *ctr502;
3687 ctr502 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr502);
3688 W_ERROR_HAVE_NO_MEMORY(ctr502);
3690 ctr502->count = 1;
3691 ctr502->array = info.info502;
3693 info_ctr->ctr.ctr502 = ctr502;
3695 break;
3697 } /* switch */
3698 done:
3699 return result;
3702 /***
3703 * 'net rpc share list' entrypoint.
3704 * @param argc Standard main() style argc.
3705 * @param argv Standard main() style argv. Initial components are already
3706 * stripped.
3708 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3710 NET_API_STATUS status;
3711 struct SHARE_INFO_1 *i1 = NULL;
3712 uint32_t entries_read = 0;
3713 uint32_t total_entries = 0;
3714 uint32_t resume_handle = 0;
3715 uint32_t i, level = 1;
3717 if (c->display_usage) {
3718 d_printf( "%s\n"
3719 "net rpc share list\n"
3720 " %s\n",
3721 _("Usage:"),
3722 _("List shares on remote server"));
3723 return 0;
3726 status = NetShareEnum(c->opt_host,
3727 level,
3728 (uint8_t **)(void *)&i1,
3729 (uint32_t)-1,
3730 &entries_read,
3731 &total_entries,
3732 &resume_handle);
3733 if (status != 0) {
3734 goto done;
3737 /* Display results */
3739 if (c->opt_long_list_entries) {
3740 d_printf(_(
3741 "\nEnumerating shared resources (exports) on remote server:\n\n"
3742 "\nShare name Type Description\n"
3743 "---------- ---- -----------\n"));
3745 for (i = 0; i < entries_read; i++)
3746 display_share_info_1(c, &i1[i]);
3747 done:
3748 return status;
3751 static bool check_share_availability(struct cli_state *cli, const char *netname)
3753 NTSTATUS status;
3755 status = cli_tree_connect(cli, netname, "A:", "", 0);
3756 if (!NT_STATUS_IS_OK(status)) {
3757 d_printf(_("skipping [%s]: not a file share.\n"), netname);
3758 return false;
3761 status = cli_tdis(cli);
3762 if (!NT_STATUS_IS_OK(status)) {
3763 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3764 return false;
3767 return true;
3770 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3771 const char *netname, uint32 type)
3773 /* only support disk shares */
3774 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3775 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3776 type);
3777 return false;
3780 /* skip builtin shares */
3781 /* FIXME: should print$ be added too ? */
3782 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3783 strequal(netname,"global"))
3784 return false;
3786 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3787 printf(_("excluding [%s]\n"), netname);
3788 return false;
3791 return check_share_availability(cli, netname);
3795 * Migrate shares from a remote RPC server to the local RPC server.
3797 * All parameters are provided by the run_rpc_command function, except for
3798 * argc, argv which are passed through.
3800 * @param domain_sid The domain sid acquired from the remote server.
3801 * @param cli A cli_state connected to the server.
3802 * @param mem_ctx Talloc context, destroyed on completion of the function.
3803 * @param argc Standard main() style argc.
3804 * @param argv Standard main() style argv. Initial components are already
3805 * stripped.
3807 * @return Normal NTSTATUS return.
3810 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3811 const struct dom_sid *domain_sid,
3812 const char *domain_name,
3813 struct cli_state *cli,
3814 struct rpc_pipe_client *pipe_hnd,
3815 TALLOC_CTX *mem_ctx,
3816 int argc,
3817 const char **argv)
3819 WERROR result;
3820 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3821 struct srvsvc_NetShareInfoCtr ctr_src;
3822 uint32 i;
3823 struct rpc_pipe_client *srvsvc_pipe = NULL;
3824 struct cli_state *cli_dst = NULL;
3825 uint32 level = 502; /* includes secdesc */
3826 uint32_t parm_error = 0;
3827 struct dcerpc_binding_handle *b;
3829 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3830 &ctr_src);
3831 if (!W_ERROR_IS_OK(result))
3832 goto done;
3834 /* connect destination PI_SRVSVC */
3835 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3836 &ndr_table_srvsvc);
3837 if (!NT_STATUS_IS_OK(nt_status))
3838 return nt_status;
3840 b = srvsvc_pipe->binding_handle;
3842 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3844 union srvsvc_NetShareInfo info;
3845 struct srvsvc_NetShareInfo502 info502 =
3846 ctr_src.ctr.ctr502->array[i];
3848 /* reset error-code */
3849 nt_status = NT_STATUS_UNSUCCESSFUL;
3851 if (!check_share_sanity(c, cli, info502.name, info502.type))
3852 continue;
3854 /* finally add the share on the dst server */
3856 printf(_("migrating: [%s], path: %s, comment: %s, without "
3857 "share-ACLs\n"),
3858 info502.name, info502.path, info502.comment);
3860 info.info502 = &info502;
3862 nt_status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
3863 srvsvc_pipe->desthost,
3864 502,
3865 &info,
3866 &parm_error,
3867 &result);
3868 if (!NT_STATUS_IS_OK(nt_status)) {
3869 printf(_("cannot add share: %s\n"),
3870 nt_errstr(nt_status));
3871 goto done;
3873 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3874 printf(_(" [%s] does already exist\n"),
3875 info502.name);
3876 continue;
3879 if (!W_ERROR_IS_OK(result)) {
3880 nt_status = werror_to_ntstatus(result);
3881 printf(_("cannot add share: %s\n"),
3882 win_errstr(result));
3883 goto done;
3888 nt_status = NT_STATUS_OK;
3890 done:
3891 if (cli_dst) {
3892 cli_shutdown(cli_dst);
3895 return nt_status;
3900 * Migrate shares from a RPC server to another.
3902 * @param argc Standard main() style argc.
3903 * @param argv Standard main() style argv. Initial components are already
3904 * stripped.
3906 * @return A shell status integer (0 for success).
3908 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3909 const char **argv)
3911 if (c->display_usage) {
3912 d_printf( "%s\n"
3913 "net rpc share migrate shares\n"
3914 " %s\n",
3915 _("Usage:"),
3916 _("Migrate shares to local server"));
3917 return 0;
3920 if (!c->opt_host) {
3921 printf(_("no server to migrate\n"));
3922 return -1;
3925 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
3926 rpc_share_migrate_shares_internals,
3927 argc, argv);
3931 * Copy a file/dir
3933 * @param f file_info
3934 * @param mask current search mask
3935 * @param state arg-pointer
3938 static NTSTATUS copy_fn(const char *mnt, struct file_info *f,
3939 const char *mask, void *state)
3941 static NTSTATUS nt_status;
3942 static struct copy_clistate *local_state;
3943 static fstring filename, new_mask;
3944 fstring dir;
3945 char *old_dir;
3946 struct net_context *c;
3948 local_state = (struct copy_clistate *)state;
3949 nt_status = NT_STATUS_UNSUCCESSFUL;
3951 c = local_state->c;
3953 if (strequal(f->name, ".") || strequal(f->name, ".."))
3954 return NT_STATUS_OK;
3956 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3958 /* DIRECTORY */
3959 if (f->mode & FILE_ATTRIBUTE_DIRECTORY) {
3961 DEBUG(3,("got dir: %s\n", f->name));
3963 fstrcpy(dir, local_state->cwd);
3964 fstrcat(dir, "\\");
3965 fstrcat(dir, f->name);
3967 switch (net_mode_share)
3969 case NET_MODE_SHARE_MIGRATE:
3970 /* create that directory */
3971 nt_status = net_copy_file(c, local_state->mem_ctx,
3972 local_state->cli_share_src,
3973 local_state->cli_share_dst,
3974 dir, dir,
3975 c->opt_acls? true : false,
3976 c->opt_attrs? true : false,
3977 c->opt_timestamps? true:false,
3978 false);
3979 break;
3980 default:
3981 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3982 return NT_STATUS_INTERNAL_ERROR;
3985 if (!NT_STATUS_IS_OK(nt_status)) {
3986 printf(_("could not handle dir %s: %s\n"),
3987 dir, nt_errstr(nt_status));
3988 return nt_status;
3991 /* search below that directory */
3992 if (strlcpy(new_mask, dir, sizeof(new_mask)) >= sizeof(new_mask)) {
3993 return NT_STATUS_NO_MEMORY;
3995 if (strlcat(new_mask, "\\*", sizeof(new_mask)) >= sizeof(new_mask)) {
3996 return NT_STATUS_NO_MEMORY;
3999 old_dir = local_state->cwd;
4000 local_state->cwd = dir;
4001 nt_status = sync_files(local_state, new_mask);
4002 if (!NT_STATUS_IS_OK(nt_status)) {
4003 printf(_("could not handle files\n"));
4005 local_state->cwd = old_dir;
4007 return nt_status;
4011 /* FILE */
4012 fstrcpy(filename, local_state->cwd);
4013 fstrcat(filename, "\\");
4014 fstrcat(filename, f->name);
4016 DEBUG(3,("got file: %s\n", filename));
4018 switch (net_mode_share)
4020 case NET_MODE_SHARE_MIGRATE:
4021 nt_status = net_copy_file(c, local_state->mem_ctx,
4022 local_state->cli_share_src,
4023 local_state->cli_share_dst,
4024 filename, filename,
4025 c->opt_acls? true : false,
4026 c->opt_attrs? true : false,
4027 c->opt_timestamps? true: false,
4028 true);
4029 break;
4030 default:
4031 d_fprintf(stderr, _("Unsupported file mode %d\n"),
4032 net_mode_share);
4033 return NT_STATUS_INTERNAL_ERROR;
4036 if (!NT_STATUS_IS_OK(nt_status))
4037 printf(_("could not handle file %s: %s\n"),
4038 filename, nt_errstr(nt_status));
4039 return nt_status;
4043 * sync files, can be called recursivly to list files
4044 * and then call copy_fn for each file
4046 * @param cp_clistate pointer to the copy_clistate we work with
4047 * @param mask the current search mask
4049 * @return Boolean result
4051 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask)
4053 struct cli_state *targetcli;
4054 char *targetpath = NULL;
4055 NTSTATUS status;
4057 DEBUG(3,("calling cli_list with mask: %s\n", mask));
4059 status = cli_resolve_path(talloc_tos(), "", NULL,
4060 cp_clistate->cli_share_src,
4061 mask, &targetcli, &targetpath);
4062 if (!NT_STATUS_IS_OK(status)) {
4063 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
4064 "%s\n"),
4065 mask, nt_errstr(status));
4066 return status;
4069 status = cli_list(targetcli, targetpath, cp_clistate->attribute,
4070 copy_fn, cp_clistate);
4071 if (!NT_STATUS_IS_OK(status)) {
4072 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
4073 mask, nt_errstr(status));
4076 return status;
4081 * Set the top level directory permissions before we do any further copies.
4082 * Should set up ACL inheritance.
4085 bool copy_top_level_perms(struct net_context *c,
4086 struct copy_clistate *cp_clistate,
4087 const char *sharename)
4089 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4091 switch (net_mode_share) {
4092 case NET_MODE_SHARE_MIGRATE:
4093 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
4094 nt_status = net_copy_fileattr(c,
4095 cp_clistate->mem_ctx,
4096 cp_clistate->cli_share_src,
4097 cp_clistate->cli_share_dst,
4098 "\\", "\\",
4099 c->opt_acls? true : false,
4100 c->opt_attrs? true : false,
4101 c->opt_timestamps? true: false,
4102 false);
4103 break;
4104 default:
4105 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
4106 break;
4109 if (!NT_STATUS_IS_OK(nt_status)) {
4110 printf(_("Could handle directory attributes for top level "
4111 "directory of share %s. Error %s\n"),
4112 sharename, nt_errstr(nt_status));
4113 return false;
4116 return true;
4120 * Sync all files inside a remote share to another share (over smb).
4122 * All parameters are provided by the run_rpc_command function, except for
4123 * argc, argv which are passed through.
4125 * @param domain_sid The domain sid acquired from the remote server.
4126 * @param cli A cli_state connected to the server.
4127 * @param mem_ctx Talloc context, destroyed on completion of the function.
4128 * @param argc Standard main() style argc.
4129 * @param argv Standard main() style argv. Initial components are already
4130 * stripped.
4132 * @return Normal NTSTATUS return.
4135 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
4136 const struct dom_sid *domain_sid,
4137 const char *domain_name,
4138 struct cli_state *cli,
4139 struct rpc_pipe_client *pipe_hnd,
4140 TALLOC_CTX *mem_ctx,
4141 int argc,
4142 const char **argv)
4144 WERROR result;
4145 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4146 struct srvsvc_NetShareInfoCtr ctr_src;
4147 uint32 i;
4148 uint32 level = 502;
4149 struct copy_clistate cp_clistate;
4150 bool got_src_share = false;
4151 bool got_dst_share = false;
4152 const char *mask = "\\*";
4153 char *dst = NULL;
4155 dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
4156 if (dst == NULL) {
4157 nt_status = NT_STATUS_NO_MEMORY;
4158 goto done;
4161 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
4162 &ctr_src);
4164 if (!W_ERROR_IS_OK(result))
4165 goto done;
4167 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
4169 struct srvsvc_NetShareInfo502 info502 =
4170 ctr_src.ctr.ctr502->array[i];
4172 if (!check_share_sanity(c, cli, info502.name, info502.type))
4173 continue;
4175 /* one might not want to mirror whole discs :) */
4176 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
4177 d_printf(_("skipping [%s]: builtin/hidden share\n"),
4178 info502.name);
4179 continue;
4182 switch (net_mode_share)
4184 case NET_MODE_SHARE_MIGRATE:
4185 printf("syncing");
4186 break;
4187 default:
4188 d_fprintf(stderr, _("Unsupported mode %d\n"),
4189 net_mode_share);
4190 break;
4192 printf(_(" [%s] files and directories %s ACLs, %s DOS "
4193 "Attributes %s\n"),
4194 info502.name,
4195 c->opt_acls ? _("including") : _("without"),
4196 c->opt_attrs ? _("including") : _("without"),
4197 c->opt_timestamps ? _("(preserving timestamps)") : "");
4199 cp_clistate.mem_ctx = mem_ctx;
4200 cp_clistate.cli_share_src = NULL;
4201 cp_clistate.cli_share_dst = NULL;
4202 cp_clistate.cwd = NULL;
4203 cp_clistate.attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
4204 cp_clistate.c = c;
4206 /* open share source */
4207 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
4208 smbXcli_conn_remote_sockaddr(cli->conn),
4209 smbXcli_conn_remote_name(cli->conn),
4210 info502.name, "A:");
4211 if (!NT_STATUS_IS_OK(nt_status))
4212 goto done;
4214 got_src_share = true;
4216 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
4217 /* open share destination */
4218 nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
4219 NULL, dst, info502.name, "A:");
4220 if (!NT_STATUS_IS_OK(nt_status))
4221 goto done;
4223 got_dst_share = true;
4226 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
4227 d_fprintf(stderr, _("Could not handle the top level "
4228 "directory permissions for the "
4229 "share: %s\n"), info502.name);
4230 nt_status = NT_STATUS_UNSUCCESSFUL;
4231 goto done;
4234 nt_status = sync_files(&cp_clistate, mask);
4235 if (!NT_STATUS_IS_OK(nt_status)) {
4236 d_fprintf(stderr, _("could not handle files for share: "
4237 "%s\n"), info502.name);
4238 goto done;
4242 nt_status = NT_STATUS_OK;
4244 done:
4246 if (got_src_share)
4247 cli_shutdown(cp_clistate.cli_share_src);
4249 if (got_dst_share)
4250 cli_shutdown(cp_clistate.cli_share_dst);
4252 SAFE_FREE(dst);
4253 return nt_status;
4257 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
4259 if (c->display_usage) {
4260 d_printf( "%s\n"
4261 "net share migrate files\n"
4262 " %s\n",
4263 _("Usage:"),
4264 _("Migrate files to local server"));
4265 return 0;
4268 if (!c->opt_host) {
4269 d_printf(_("no server to migrate\n"));
4270 return -1;
4273 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4274 rpc_share_migrate_files_internals,
4275 argc, argv);
4279 * Migrate share-ACLs from a remote RPC server to the local RPC server.
4281 * All parameters are provided by the run_rpc_command function, except for
4282 * argc, argv which are passed through.
4284 * @param domain_sid The domain sid acquired from the remote server.
4285 * @param cli A cli_state connected to the server.
4286 * @param mem_ctx Talloc context, destroyed on completion of the function.
4287 * @param argc Standard main() style argc.
4288 * @param argv Standard main() style argv. Initial components are already
4289 * stripped.
4291 * @return Normal NTSTATUS return.
4294 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
4295 const struct dom_sid *domain_sid,
4296 const char *domain_name,
4297 struct cli_state *cli,
4298 struct rpc_pipe_client *pipe_hnd,
4299 TALLOC_CTX *mem_ctx,
4300 int argc,
4301 const char **argv)
4303 WERROR result;
4304 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4305 struct srvsvc_NetShareInfoCtr ctr_src;
4306 union srvsvc_NetShareInfo info;
4307 uint32 i;
4308 struct rpc_pipe_client *srvsvc_pipe = NULL;
4309 struct cli_state *cli_dst = NULL;
4310 uint32 level = 502; /* includes secdesc */
4311 uint32_t parm_error = 0;
4312 struct dcerpc_binding_handle *b;
4314 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
4315 &ctr_src);
4317 if (!W_ERROR_IS_OK(result))
4318 goto done;
4320 /* connect destination PI_SRVSVC */
4321 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
4322 &ndr_table_srvsvc);
4323 if (!NT_STATUS_IS_OK(nt_status))
4324 return nt_status;
4326 b = srvsvc_pipe->binding_handle;
4328 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
4330 struct srvsvc_NetShareInfo502 info502 =
4331 ctr_src.ctr.ctr502->array[i];
4333 /* reset error-code */
4334 nt_status = NT_STATUS_UNSUCCESSFUL;
4336 if (!check_share_sanity(c, cli, info502.name, info502.type))
4337 continue;
4339 printf(_("migrating: [%s], path: %s, comment: %s, including "
4340 "share-ACLs\n"),
4341 info502.name, info502.path, info502.comment);
4343 if (c->opt_verbose)
4344 display_sec_desc(info502.sd_buf.sd);
4346 /* FIXME: shouldn't we be able to just set the security descriptor ? */
4347 info.info502 = &info502;
4349 /* finally modify the share on the dst server */
4350 nt_status = dcerpc_srvsvc_NetShareSetInfo(b, mem_ctx,
4351 srvsvc_pipe->desthost,
4352 info502.name,
4353 level,
4354 &info,
4355 &parm_error,
4356 &result);
4357 if (!NT_STATUS_IS_OK(nt_status)) {
4358 printf(_("cannot set share-acl: %s\n"),
4359 nt_errstr(nt_status));
4360 goto done;
4362 if (!W_ERROR_IS_OK(result)) {
4363 nt_status = werror_to_ntstatus(result);
4364 printf(_("cannot set share-acl: %s\n"),
4365 win_errstr(result));
4366 goto done;
4371 nt_status = NT_STATUS_OK;
4373 done:
4374 if (cli_dst) {
4375 cli_shutdown(cli_dst);
4378 return nt_status;
4383 * Migrate share-acls from a RPC server to another.
4385 * @param argc Standard main() style argc.
4386 * @param argv Standard main() style argv. Initial components are already
4387 * stripped.
4389 * @return A shell status integer (0 for success).
4391 static int rpc_share_migrate_security(struct net_context *c, int argc,
4392 const char **argv)
4394 if (c->display_usage) {
4395 d_printf( "%s\n"
4396 "net rpc share migrate security\n"
4397 " %s\n",
4398 _("Usage:"),
4399 _("Migrate share-acls to local server"));
4400 return 0;
4403 if (!c->opt_host) {
4404 d_printf(_("no server to migrate\n"));
4405 return -1;
4408 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4409 rpc_share_migrate_security_internals,
4410 argc, argv);
4414 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
4415 * from one server to another.
4417 * @param argc Standard main() style argc.
4418 * @param argv Standard main() style argv. Initial components are already
4419 * stripped.
4421 * @return A shell status integer (0 for success).
4424 static int rpc_share_migrate_all(struct net_context *c, int argc,
4425 const char **argv)
4427 int ret;
4429 if (c->display_usage) {
4430 d_printf( "%s\n"
4431 "net rpc share migrate all\n"
4432 " %s\n",
4433 _("Usage:"),
4434 _("Migrates shares including all share settings"));
4435 return 0;
4438 if (!c->opt_host) {
4439 d_printf(_("no server to migrate\n"));
4440 return -1;
4443 /* order is important. we don't want to be locked out by the share-acl
4444 * before copying files - gd */
4446 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4447 rpc_share_migrate_shares_internals, argc, argv);
4448 if (ret)
4449 return ret;
4451 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4452 rpc_share_migrate_files_internals, argc, argv);
4453 if (ret)
4454 return ret;
4456 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4457 rpc_share_migrate_security_internals, argc,
4458 argv);
4463 * 'net rpc share migrate' entrypoint.
4464 * @param argc Standard main() style argc.
4465 * @param argv Standard main() style argv. Initial components are already
4466 * stripped.
4468 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
4471 struct functable func[] = {
4473 "all",
4474 rpc_share_migrate_all,
4475 NET_TRANSPORT_RPC,
4476 N_("Migrate shares from remote to local server"),
4477 N_("net rpc share migrate all\n"
4478 " Migrate shares from remote to local server")
4481 "files",
4482 rpc_share_migrate_files,
4483 NET_TRANSPORT_RPC,
4484 N_("Migrate files from remote to local server"),
4485 N_("net rpc share migrate files\n"
4486 " Migrate files from remote to local server")
4489 "security",
4490 rpc_share_migrate_security,
4491 NET_TRANSPORT_RPC,
4492 N_("Migrate share-ACLs from remote to local server"),
4493 N_("net rpc share migrate security\n"
4494 " Migrate share-ACLs from remote to local server")
4497 "shares",
4498 rpc_share_migrate_shares,
4499 NET_TRANSPORT_RPC,
4500 N_("Migrate shares from remote to local server"),
4501 N_("net rpc share migrate shares\n"
4502 " Migrate shares from remote to local server")
4504 {NULL, NULL, 0, NULL, NULL}
4507 net_mode_share = NET_MODE_SHARE_MIGRATE;
4509 return net_run_function(c, argc, argv, "net rpc share migrate", func);
4512 struct full_alias {
4513 struct dom_sid sid;
4514 uint32 num_members;
4515 struct dom_sid *members;
4518 static int num_server_aliases;
4519 static struct full_alias *server_aliases;
4522 * Add an alias to the static list.
4524 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
4526 if (server_aliases == NULL)
4527 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
4529 server_aliases[num_server_aliases] = *alias;
4530 num_server_aliases += 1;
4534 * For a specific domain on the server, fetch all the aliases
4535 * and their members. Add all of them to the server_aliases.
4538 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4539 TALLOC_CTX *mem_ctx,
4540 struct policy_handle *connect_pol,
4541 const struct dom_sid *domain_sid)
4543 uint32 start_idx, max_entries, num_entries, i;
4544 struct samr_SamArray *groups = NULL;
4545 NTSTATUS result, status;
4546 struct policy_handle domain_pol;
4547 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4549 /* Get domain policy handle */
4551 status = dcerpc_samr_OpenDomain(b, mem_ctx,
4552 connect_pol,
4553 MAXIMUM_ALLOWED_ACCESS,
4554 discard_const_p(struct dom_sid2, domain_sid),
4555 &domain_pol,
4556 &result);
4557 if (!NT_STATUS_IS_OK(status)) {
4558 return status;
4560 if (!NT_STATUS_IS_OK(result)) {
4561 return result;
4564 start_idx = 0;
4565 max_entries = 250;
4567 do {
4568 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
4569 &domain_pol,
4570 &start_idx,
4571 &groups,
4572 max_entries,
4573 &num_entries,
4574 &result);
4575 if (!NT_STATUS_IS_OK(status)) {
4576 goto done;
4578 for (i = 0; i < num_entries; i++) {
4580 struct policy_handle alias_pol;
4581 struct full_alias alias;
4582 struct lsa_SidArray sid_array;
4583 int j;
4584 NTSTATUS _result;
4586 status = dcerpc_samr_OpenAlias(b, mem_ctx,
4587 &domain_pol,
4588 MAXIMUM_ALLOWED_ACCESS,
4589 groups->entries[i].idx,
4590 &alias_pol,
4591 &_result);
4592 if (!NT_STATUS_IS_OK(status)) {
4593 goto done;
4595 if (!NT_STATUS_IS_OK(_result)) {
4596 status = _result;
4597 goto done;
4600 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
4601 &alias_pol,
4602 &sid_array,
4603 &_result);
4604 if (!NT_STATUS_IS_OK(status)) {
4605 goto done;
4607 if (!NT_STATUS_IS_OK(_result)) {
4608 status = _result;
4609 goto done;
4612 alias.num_members = sid_array.num_sids;
4614 status = dcerpc_samr_Close(b, mem_ctx, &alias_pol, &_result);
4615 if (!NT_STATUS_IS_OK(status)) {
4616 goto done;
4618 if (!NT_STATUS_IS_OK(_result)) {
4619 status = _result;
4620 goto done;
4623 alias.members = NULL;
4625 if (alias.num_members > 0) {
4626 alias.members = SMB_MALLOC_ARRAY(struct dom_sid, alias.num_members);
4628 for (j = 0; j < alias.num_members; j++)
4629 sid_copy(&alias.members[j],
4630 sid_array.sids[j].sid);
4633 sid_compose(&alias.sid, domain_sid,
4634 groups->entries[i].idx);
4636 push_alias(mem_ctx, &alias);
4638 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4640 status = NT_STATUS_OK;
4642 done:
4643 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
4645 return status;
4649 * Dump server_aliases as names for debugging purposes.
4652 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4653 const struct dom_sid *domain_sid,
4654 const char *domain_name,
4655 struct cli_state *cli,
4656 struct rpc_pipe_client *pipe_hnd,
4657 TALLOC_CTX *mem_ctx,
4658 int argc,
4659 const char **argv)
4661 int i;
4662 NTSTATUS result;
4663 struct policy_handle lsa_pol;
4664 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4666 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4667 SEC_FLAG_MAXIMUM_ALLOWED,
4668 &lsa_pol);
4669 if (!NT_STATUS_IS_OK(result))
4670 return result;
4672 for (i=0; i<num_server_aliases; i++) {
4673 char **names;
4674 char **domains;
4675 enum lsa_SidType *types;
4676 int j;
4678 struct full_alias *alias = &server_aliases[i];
4680 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4681 &alias->sid,
4682 &domains, &names, &types);
4683 if (!NT_STATUS_IS_OK(result))
4684 continue;
4686 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4688 if (alias->num_members == 0) {
4689 DEBUG(1, ("\n"));
4690 continue;
4693 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4694 alias->num_members,
4695 alias->members,
4696 &domains, &names, &types);
4698 if (!NT_STATUS_IS_OK(result) &&
4699 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4700 continue;
4702 for (j=0; j<alias->num_members; j++)
4703 DEBUG(1, ("%s\\%s (%d); ",
4704 domains[j] ? domains[j] : "*unknown*",
4705 names[j] ? names[j] : "*unknown*",types[j]));
4706 DEBUG(1, ("\n"));
4709 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
4711 return NT_STATUS_OK;
4715 * Fetch a list of all server aliases and their members into
4716 * server_aliases.
4719 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4720 const struct dom_sid *domain_sid,
4721 const char *domain_name,
4722 struct cli_state *cli,
4723 struct rpc_pipe_client *pipe_hnd,
4724 TALLOC_CTX *mem_ctx,
4725 int argc,
4726 const char **argv)
4728 NTSTATUS result, status;
4729 struct policy_handle connect_pol;
4730 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4732 status = dcerpc_samr_Connect2(b, mem_ctx,
4733 pipe_hnd->desthost,
4734 MAXIMUM_ALLOWED_ACCESS,
4735 &connect_pol,
4736 &result);
4737 if (!NT_STATUS_IS_OK(status)) {
4738 goto done;
4740 if (!NT_STATUS_IS_OK(result)) {
4741 status = result;
4742 goto done;
4745 status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4746 &global_sid_Builtin);
4747 if (!NT_STATUS_IS_OK(status)) {
4748 goto done;
4751 status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4752 domain_sid);
4754 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
4755 done:
4756 return status;
4759 static void init_user_token(struct security_token *token, struct dom_sid *user_sid)
4761 token->num_sids = 4;
4763 if (!(token->sids = SMB_MALLOC_ARRAY(struct dom_sid, 4))) {
4764 d_fprintf(stderr, "malloc %s\n",_("failed"));
4765 token->num_sids = 0;
4766 return;
4769 token->sids[0] = *user_sid;
4770 sid_copy(&token->sids[1], &global_sid_World);
4771 sid_copy(&token->sids[2], &global_sid_Network);
4772 sid_copy(&token->sids[3], &global_sid_Authenticated_Users);
4775 static void free_user_token(struct security_token *token)
4777 SAFE_FREE(token->sids);
4780 static void add_sid_to_token(struct security_token *token, struct dom_sid *sid)
4782 if (security_token_has_sid(token, sid))
4783 return;
4785 token->sids = SMB_REALLOC_ARRAY(token->sids, struct dom_sid, token->num_sids+1);
4786 if (!token->sids) {
4787 return;
4790 sid_copy(&token->sids[token->num_sids], sid);
4792 token->num_sids += 1;
4795 struct user_token {
4796 fstring name;
4797 struct security_token token;
4800 static void dump_user_token(struct user_token *token)
4802 int i;
4804 d_printf("%s\n", token->name);
4806 for (i=0; i<token->token.num_sids; i++) {
4807 d_printf(" %s\n", sid_string_tos(&token->token.sids[i]));
4811 static bool is_alias_member(struct dom_sid *sid, struct full_alias *alias)
4813 int i;
4815 for (i=0; i<alias->num_members; i++) {
4816 if (dom_sid_compare(sid, &alias->members[i]) == 0)
4817 return true;
4820 return false;
4823 static void collect_sid_memberships(struct security_token *token, struct dom_sid sid)
4825 int i;
4827 for (i=0; i<num_server_aliases; i++) {
4828 if (is_alias_member(&sid, &server_aliases[i]))
4829 add_sid_to_token(token, &server_aliases[i].sid);
4834 * We got a user token with all the SIDs we can know about without asking the
4835 * server directly. These are the user and domain group sids. All of these can
4836 * be members of aliases. So scan the list of aliases for each of the SIDs and
4837 * add them to the token.
4840 static void collect_alias_memberships(struct security_token *token)
4842 int num_global_sids = token->num_sids;
4843 int i;
4845 for (i=0; i<num_global_sids; i++) {
4846 collect_sid_memberships(token, token->sids[i]);
4850 static bool get_user_sids(const char *domain, const char *user, struct security_token *token)
4852 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4853 enum wbcSidType type;
4854 fstring full_name;
4855 struct wbcDomainSid wsid;
4856 char sid_str[WBC_SID_STRING_BUFLEN];
4857 struct dom_sid user_sid;
4858 uint32_t num_groups;
4859 gid_t *groups = NULL;
4860 uint32_t i;
4862 fstr_sprintf(full_name, "%s%c%s",
4863 domain, *lp_winbind_separator(), user);
4865 /* First let's find out the user sid */
4867 wbc_status = wbcLookupName(domain, user, &wsid, &type);
4869 if (!WBC_ERROR_IS_OK(wbc_status)) {
4870 DEBUG(1, ("winbind could not find %s: %s\n",
4871 full_name, wbcErrorString(wbc_status)));
4872 return false;
4875 wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4877 if (type != WBC_SID_NAME_USER) {
4878 DEBUG(1, ("%s is not a user\n", full_name));
4879 return false;
4882 if (!string_to_sid(&user_sid, sid_str)) {
4883 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4884 return false;
4887 init_user_token(token, &user_sid);
4889 /* And now the groups winbind knows about */
4891 wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4892 if (!WBC_ERROR_IS_OK(wbc_status)) {
4893 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4894 full_name, wbcErrorString(wbc_status)));
4895 return false;
4898 for (i = 0; i < num_groups; i++) {
4899 gid_t gid = groups[i];
4900 struct dom_sid sid;
4901 bool ok;
4903 wbc_status = wbcGidToSid(gid, &wsid);
4904 if (!WBC_ERROR_IS_OK(wbc_status)) {
4905 DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4906 (unsigned int)gid, wbcErrorString(wbc_status)));
4907 wbcFreeMemory(groups);
4908 return false;
4911 wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4913 DEBUG(3, (" %s\n", sid_str));
4915 ok = string_to_sid(&sid, sid_str);
4916 if (!ok) {
4917 DEBUG(1, ("Failed to convert string to SID\n"));
4918 wbcFreeMemory(groups);
4919 return false;
4921 add_sid_to_token(token, &sid);
4923 wbcFreeMemory(groups);
4925 return true;
4929 * Get a list of all user tokens we want to look at
4932 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4933 struct user_token **user_tokens)
4935 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4936 uint32_t i, num_users;
4937 const char **users;
4938 struct user_token *result;
4939 TALLOC_CTX *frame = NULL;
4941 if (lp_winbind_use_default_domain() &&
4942 (c->opt_target_workgroup == NULL)) {
4943 d_fprintf(stderr, _("winbind use default domain = yes set, "
4944 "please specify a workgroup\n"));
4945 return false;
4948 /* Send request to winbind daemon */
4950 wbc_status = wbcListUsers(NULL, &num_users, &users);
4951 if (!WBC_ERROR_IS_OK(wbc_status)) {
4952 DEBUG(1, (_("winbind could not list users: %s\n"),
4953 wbcErrorString(wbc_status)));
4954 return false;
4957 result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4959 if (result == NULL) {
4960 DEBUG(1, ("Could not malloc sid array\n"));
4961 wbcFreeMemory(users);
4962 return false;
4965 frame = talloc_stackframe();
4966 for (i=0; i < num_users; i++) {
4967 fstring domain, user;
4968 char *p;
4970 fstrcpy(result[i].name, users[i]);
4972 p = strchr(users[i], *lp_winbind_separator());
4974 DEBUG(3, ("%s\n", users[i]));
4976 if (p == NULL) {
4977 fstrcpy(domain, c->opt_target_workgroup);
4978 fstrcpy(user, users[i]);
4979 } else {
4980 *p++ = '\0';
4981 fstrcpy(domain, users[i]);
4982 if (!strupper_m(domain)) {
4983 DEBUG(1, ("strupper_m %s failed\n", domain));
4984 wbcFreeMemory(users);
4985 return false;
4987 fstrcpy(user, p);
4990 get_user_sids(domain, user, &(result[i].token));
4992 TALLOC_FREE(frame);
4993 wbcFreeMemory(users);
4995 *num_tokens = num_users;
4996 *user_tokens = result;
4998 return true;
5001 static bool get_user_tokens_from_file(FILE *f,
5002 int *num_tokens,
5003 struct user_token **tokens)
5005 struct user_token *token = NULL;
5007 while (!feof(f)) {
5008 fstring line;
5010 if (fgets(line, sizeof(line)-1, f) == NULL) {
5011 return true;
5014 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
5015 line[strlen(line)-1] = '\0';
5018 if (line[0] == ' ') {
5019 /* We have a SID */
5021 struct dom_sid sid;
5022 if(!string_to_sid(&sid, &line[1])) {
5023 DEBUG(1,("get_user_tokens_from_file: Could "
5024 "not convert sid %s \n",&line[1]));
5025 return false;
5028 if (token == NULL) {
5029 DEBUG(0, ("File does not begin with username"));
5030 return false;
5033 add_sid_to_token(&token->token, &sid);
5034 continue;
5037 /* And a new user... */
5039 *num_tokens += 1;
5040 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
5041 if (*tokens == NULL) {
5042 DEBUG(0, ("Could not realloc tokens\n"));
5043 return false;
5046 token = &((*tokens)[*num_tokens-1]);
5048 if (strlcpy(token->name, line, sizeof(token->name)) >= sizeof(token->name)) {
5049 return false;
5051 token->token.num_sids = 0;
5052 token->token.sids = NULL;
5053 continue;
5056 return false;
5061 * Show the list of all users that have access to a share
5064 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
5065 struct cli_state *cli,
5066 TALLOC_CTX *mem_ctx,
5067 const char *netname,
5068 int num_tokens,
5069 struct user_token *tokens)
5071 uint16_t fnum;
5072 struct security_descriptor *share_sd = NULL;
5073 struct security_descriptor *root_sd = NULL;
5074 int i;
5075 union srvsvc_NetShareInfo info;
5076 WERROR result;
5077 NTSTATUS status;
5078 uint16 cnum;
5079 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5081 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5082 pipe_hnd->desthost,
5083 netname,
5084 502,
5085 &info,
5086 &result);
5088 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
5089 DEBUG(1, ("Coult not query secdesc for share %s\n",
5090 netname));
5091 return;
5094 share_sd = info.info502->sd_buf.sd;
5095 if (share_sd == NULL) {
5096 DEBUG(1, ("Got no secdesc for share %s\n",
5097 netname));
5100 cnum = cli_state_get_tid(cli);
5102 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, netname, "A:", "", 0))) {
5103 return;
5106 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
5107 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
5108 cli_query_secdesc(cli, fnum, mem_ctx, &root_sd);
5111 for (i=0; i<num_tokens; i++) {
5112 uint32 acc_granted;
5114 if (share_sd != NULL) {
5115 status = se_access_check(share_sd, &tokens[i].token,
5116 1, &acc_granted);
5118 if (!NT_STATUS_IS_OK(status)) {
5119 DEBUG(1, ("Could not check share_sd for "
5120 "user %s\n",
5121 tokens[i].name));
5122 continue;
5126 if (root_sd == NULL) {
5127 d_printf(" %s\n", tokens[i].name);
5128 continue;
5131 status = se_access_check(root_sd, &tokens[i].token,
5132 1, &acc_granted);
5133 if (!NT_STATUS_IS_OK(status)) {
5134 DEBUG(1, ("Could not check root_sd for user %s\n",
5135 tokens[i].name));
5136 continue;
5138 d_printf(" %s\n", tokens[i].name);
5141 if (fnum != (uint16_t)-1)
5142 cli_close(cli, fnum);
5143 cli_tdis(cli);
5144 cli_state_set_tid(cli, cnum);
5146 return;
5150 * List shares on a remote RPC server, including the security descriptors.
5152 * All parameters are provided by the run_rpc_command function, except for
5153 * argc, argv which are passed through.
5155 * @param domain_sid The domain sid acquired from the remote server.
5156 * @param cli A cli_state connected to the server.
5157 * @param mem_ctx Talloc context, destroyed on completion of the function.
5158 * @param argc Standard main() style argc.
5159 * @param argv Standard main() style argv. Initial components are already
5160 * stripped.
5162 * @return Normal NTSTATUS return.
5165 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
5166 const struct dom_sid *domain_sid,
5167 const char *domain_name,
5168 struct cli_state *cli,
5169 struct rpc_pipe_client *pipe_hnd,
5170 TALLOC_CTX *mem_ctx,
5171 int argc,
5172 const char **argv)
5174 bool r;
5175 FILE *f;
5176 NTSTATUS nt_status = NT_STATUS_OK;
5177 uint32_t total_entries = 0;
5178 uint32_t resume_handle = 0;
5179 uint32_t preferred_len = 0xffffffff;
5180 uint32_t i;
5181 struct dcerpc_binding_handle *b = NULL;
5182 struct srvsvc_NetShareInfoCtr info_ctr;
5183 struct srvsvc_NetShareCtr1 ctr1;
5184 WERROR result;
5186 struct user_token *tokens = NULL;
5187 int num_tokens = 0;
5189 if (argc == 0) {
5190 f = stdin;
5191 } else {
5192 f = fopen(argv[0], "r");
5195 if (f == NULL) {
5196 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
5197 return NT_STATUS_UNSUCCESSFUL;
5200 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
5202 if (f != stdin)
5203 fclose(f);
5205 if (!r) {
5206 DEBUG(0, ("Could not read users from file\n"));
5207 return NT_STATUS_UNSUCCESSFUL;
5210 for (i=0; i<num_tokens; i++)
5211 collect_alias_memberships(&tokens[i].token);
5213 ZERO_STRUCT(info_ctr);
5214 ZERO_STRUCT(ctr1);
5216 info_ctr.level = 1;
5217 info_ctr.ctr.ctr1 = &ctr1;
5219 b = pipe_hnd->binding_handle;
5221 /* Issue the NetShareEnum RPC call and retrieve the response */
5222 nt_status = dcerpc_srvsvc_NetShareEnumAll(b,
5223 talloc_tos(),
5224 pipe_hnd->desthost,
5225 &info_ctr,
5226 preferred_len,
5227 &total_entries,
5228 &resume_handle,
5229 &result);
5231 /* Was it successful? */
5232 if (!NT_STATUS_IS_OK(nt_status)) {
5233 /* Nope. Go clean up. */
5234 goto done;
5237 if (!W_ERROR_IS_OK(result)) {
5238 /* Nope. Go clean up. */
5239 nt_status = werror_to_ntstatus(result);
5240 goto done;
5243 if (total_entries == 0) {
5244 goto done;
5247 /* For each returned entry... */
5248 for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {
5249 const char *netname = info_ctr.ctr.ctr1->array[i].name;
5251 if (info_ctr.ctr.ctr1->array[i].type != STYPE_DISKTREE) {
5252 continue;
5255 d_printf("%s\n", netname);
5257 show_userlist(pipe_hnd, cli, mem_ctx, netname,
5258 num_tokens, tokens);
5260 done:
5261 for (i=0; i<num_tokens; i++) {
5262 free_user_token(&tokens[i].token);
5264 SAFE_FREE(tokens);
5266 return nt_status;
5269 static int rpc_share_allowedusers(struct net_context *c, int argc,
5270 const char **argv)
5272 int result;
5274 if (c->display_usage) {
5275 d_printf( "%s\n"
5276 "net rpc share allowedusers\n"
5277 " %s\n",
5278 _("Usage:"),
5279 _("List allowed users"));
5280 return 0;
5283 result = run_rpc_command(c, NULL, &ndr_table_samr, 0,
5284 rpc_aliaslist_internals,
5285 argc, argv);
5286 if (result != 0)
5287 return result;
5289 result = run_rpc_command(c, NULL, &ndr_table_lsarpc, 0,
5290 rpc_aliaslist_dump,
5291 argc, argv);
5292 if (result != 0)
5293 return result;
5295 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
5296 rpc_share_allowedusers_internals,
5297 argc, argv);
5300 int net_usersidlist(struct net_context *c, int argc, const char **argv)
5302 int num_tokens = 0;
5303 struct user_token *tokens = NULL;
5304 int i;
5306 if (argc != 0) {
5307 net_usersidlist_usage(c, argc, argv);
5308 return 0;
5311 if (!get_user_tokens(c, &num_tokens, &tokens)) {
5312 DEBUG(0, ("Could not get the user/sid list\n"));
5313 return -1;
5316 for (i=0; i<num_tokens; i++) {
5317 dump_user_token(&tokens[i]);
5318 free_user_token(&tokens[i].token);
5321 SAFE_FREE(tokens);
5322 return 0;
5325 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
5327 d_printf(_("net usersidlist\n"
5328 "\tprints out a list of all users the running winbind knows\n"
5329 "\tabout, together with all their SIDs. This is used as\n"
5330 "\tinput to the 'net rpc share allowedusers' command.\n\n"));
5332 net_common_flags_usage(c, argc, argv);
5333 return -1;
5337 * 'net rpc share' entrypoint.
5338 * @param argc Standard main() style argc.
5339 * @param argv Standard main() style argv. Initial components are already
5340 * stripped.
5343 int net_rpc_share(struct net_context *c, int argc, const char **argv)
5345 NET_API_STATUS status;
5347 struct functable func[] = {
5349 "add",
5350 rpc_share_add,
5351 NET_TRANSPORT_RPC,
5352 N_("Add share"),
5353 N_("net rpc share add\n"
5354 " Add share")
5357 "delete",
5358 rpc_share_delete,
5359 NET_TRANSPORT_RPC,
5360 N_("Remove share"),
5361 N_("net rpc share delete\n"
5362 " Remove share")
5365 "allowedusers",
5366 rpc_share_allowedusers,
5367 NET_TRANSPORT_RPC,
5368 N_("Modify allowed users"),
5369 N_("net rpc share allowedusers\n"
5370 " Modify allowed users")
5373 "migrate",
5374 rpc_share_migrate,
5375 NET_TRANSPORT_RPC,
5376 N_("Migrate share to local server"),
5377 N_("net rpc share migrate\n"
5378 " Migrate share to local server")
5381 "list",
5382 rpc_share_list,
5383 NET_TRANSPORT_RPC,
5384 N_("List shares"),
5385 N_("net rpc share list\n"
5386 " List shares")
5388 {NULL, NULL, 0, NULL, NULL}
5391 status = libnetapi_net_init(&c->netapi_ctx);
5392 if (status != 0) {
5393 return -1;
5395 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5396 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5397 if (c->opt_kerberos) {
5398 libnetapi_set_use_kerberos(c->netapi_ctx);
5401 if (argc == 0) {
5402 if (c->display_usage) {
5403 d_printf("%s\n%s",
5404 _("Usage:"),
5405 _("net rpc share\n"
5406 " List shares\n"
5407 " Alias for net rpc share list\n"));
5408 net_display_usage_from_functable(func);
5409 return 0;
5412 return rpc_share_list(c, argc, argv);
5415 return net_run_function(c, argc, argv, "net rpc share", func);
5418 static NTSTATUS rpc_sh_share_list(struct net_context *c,
5419 TALLOC_CTX *mem_ctx,
5420 struct rpc_sh_ctx *ctx,
5421 struct rpc_pipe_client *pipe_hnd,
5422 int argc, const char **argv)
5425 return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
5428 static NTSTATUS rpc_sh_share_add(struct net_context *c,
5429 TALLOC_CTX *mem_ctx,
5430 struct rpc_sh_ctx *ctx,
5431 struct rpc_pipe_client *pipe_hnd,
5432 int argc, const char **argv)
5434 NET_API_STATUS status;
5435 uint32_t parm_err = 0;
5436 struct SHARE_INFO_2 i2;
5438 if ((argc < 2) || (argc > 3)) {
5439 d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
5440 ctx->whoami);
5441 return NT_STATUS_INVALID_PARAMETER;
5444 i2.shi2_netname = argv[0];
5445 i2.shi2_type = STYPE_DISKTREE;
5446 i2.shi2_remark = (argc == 3) ? argv[2] : "";
5447 i2.shi2_permissions = 0;
5448 i2.shi2_max_uses = 0;
5449 i2.shi2_current_uses = 0;
5450 i2.shi2_path = argv[1];
5451 i2.shi2_passwd = NULL;
5453 status = NetShareAdd(pipe_hnd->desthost,
5455 (uint8_t *)&i2,
5456 &parm_err);
5458 return werror_to_ntstatus(W_ERROR(status));
5461 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
5462 TALLOC_CTX *mem_ctx,
5463 struct rpc_sh_ctx *ctx,
5464 struct rpc_pipe_client *pipe_hnd,
5465 int argc, const char **argv)
5467 if (argc != 1) {
5468 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5469 return NT_STATUS_INVALID_PARAMETER;
5472 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
5475 static NTSTATUS rpc_sh_share_info(struct net_context *c,
5476 TALLOC_CTX *mem_ctx,
5477 struct rpc_sh_ctx *ctx,
5478 struct rpc_pipe_client *pipe_hnd,
5479 int argc, const char **argv)
5481 union srvsvc_NetShareInfo info;
5482 WERROR result;
5483 NTSTATUS status;
5484 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5486 if (argc != 1) {
5487 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5488 return NT_STATUS_INVALID_PARAMETER;
5491 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5492 pipe_hnd->desthost,
5493 argv[0],
5495 &info,
5496 &result);
5497 if (!NT_STATUS_IS_OK(status)) {
5498 result = ntstatus_to_werror(status);
5499 goto done;
5501 if (!W_ERROR_IS_OK(result)) {
5502 goto done;
5505 d_printf(_("Name: %s\n"), info.info2->name);
5506 d_printf(_("Comment: %s\n"), info.info2->comment);
5507 d_printf(_("Path: %s\n"), info.info2->path);
5508 d_printf(_("Password: %s\n"), info.info2->password);
5510 done:
5511 return werror_to_ntstatus(result);
5514 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
5515 struct rpc_sh_ctx *ctx)
5517 static struct rpc_sh_cmd cmds[] = {
5519 { "list", NULL, &ndr_table_srvsvc, rpc_sh_share_list,
5520 N_("List available shares") },
5522 { "add", NULL, &ndr_table_srvsvc, rpc_sh_share_add,
5523 N_("Add a share") },
5525 { "delete", NULL, &ndr_table_srvsvc, rpc_sh_share_delete,
5526 N_("Delete a share") },
5528 { "info", NULL, &ndr_table_srvsvc, rpc_sh_share_info,
5529 N_("Get information about a share") },
5531 { NULL, NULL, 0, NULL, NULL }
5534 return cmds;
5537 /****************************************************************************/
5539 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
5541 return net_file_usage(c, argc, argv);
5545 * Close a file on a remote RPC server.
5547 * @param argc Standard main() style argc.
5548 * @param argv Standard main() style argv. Initial components are already
5549 * stripped.
5551 * @return A shell status integer (0 for success).
5553 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5555 if (argc < 1 || c->display_usage) {
5556 return rpc_file_usage(c, argc, argv);
5559 return NetFileClose(c->opt_host, atoi(argv[0]));
5563 * Formatted print of open file info
5565 * @param r struct FILE_INFO_3 contents
5568 static void display_file_info_3(struct FILE_INFO_3 *r)
5570 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5571 r->fi3_id, r->fi3_username, r->fi3_permissions,
5572 r->fi3_num_locks, r->fi3_pathname);
5576 * List files for a user on a remote RPC server.
5578 * @param argc Standard main() style argc.
5579 * @param argv Standard main() style argv. Initial components are already
5580 * stripped.
5582 * @return A shell status integer (0 for success)..
5585 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5587 NET_API_STATUS status;
5588 uint32 preferred_len = 0xffffffff, i;
5589 char *username=NULL;
5590 uint32_t total_entries = 0;
5591 uint32_t entries_read = 0;
5592 uint32_t resume_handle = 0;
5593 struct FILE_INFO_3 *i3 = NULL;
5595 if (c->display_usage) {
5596 return rpc_file_usage(c, argc, argv);
5599 /* if argc > 0, must be user command */
5600 if (argc > 0) {
5601 username = smb_xstrdup(argv[0]);
5604 status = NetFileEnum(c->opt_host,
5605 NULL,
5606 username,
5608 (uint8_t **)(void *)&i3,
5609 preferred_len,
5610 &entries_read,
5611 &total_entries,
5612 &resume_handle);
5614 if (status != 0) {
5615 goto done;
5618 /* Display results */
5620 d_printf(_(
5621 "\nEnumerating open files on remote server:\n\n"
5622 "\nFileId Opened by Perms Locks Path"
5623 "\n------ --------- ----- ----- ---- \n"));
5624 for (i = 0; i < entries_read; i++) {
5625 display_file_info_3(&i3[i]);
5627 done:
5628 SAFE_FREE(username);
5629 return status;
5633 * 'net rpc file' entrypoint.
5634 * @param argc Standard main() style argc.
5635 * @param argv Standard main() style argv. Initial components are already
5636 * stripped.
5639 int net_rpc_file(struct net_context *c, int argc, const char **argv)
5641 NET_API_STATUS status;
5643 struct functable func[] = {
5645 "close",
5646 rpc_file_close,
5647 NET_TRANSPORT_RPC,
5648 N_("Close opened file"),
5649 N_("net rpc file close\n"
5650 " Close opened file")
5653 "user",
5654 rpc_file_user,
5655 NET_TRANSPORT_RPC,
5656 N_("List files opened by user"),
5657 N_("net rpc file user\n"
5658 " List files opened by user")
5660 #if 0
5662 "info",
5663 rpc_file_info,
5664 NET_TRANSPORT_RPC,
5665 N_("Display information about opened file"),
5666 N_("net rpc file info\n"
5667 " Display information about opened file")
5669 #endif
5670 {NULL, NULL, 0, NULL, NULL}
5673 status = libnetapi_net_init(&c->netapi_ctx);
5674 if (status != 0) {
5675 return -1;
5677 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5678 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5679 if (c->opt_kerberos) {
5680 libnetapi_set_use_kerberos(c->netapi_ctx);
5683 if (argc == 0) {
5684 if (c->display_usage) {
5685 d_printf(_("Usage:\n"));
5686 d_printf(_("net rpc file\n"
5687 " List opened files\n"));
5688 net_display_usage_from_functable(func);
5689 return 0;
5692 return rpc_file_user(c, argc, argv);
5695 return net_run_function(c, argc, argv, "net rpc file", func);
5699 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5701 * All parameters are provided by the run_rpc_command function, except for
5702 * argc, argv which are passed through.
5704 * @param c A net_context structure.
5705 * @param domain_sid The domain sid acquired from the remote server.
5706 * @param cli A cli_state connected to the server.
5707 * @param mem_ctx Talloc context, destroyed on completion of the function.
5708 * @param argc Standard main() style argc.
5709 * @param argv Standard main() style argv. Initial components are already
5710 * stripped.
5712 * @return Normal NTSTATUS return.
5715 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5716 const struct dom_sid *domain_sid,
5717 const char *domain_name,
5718 struct cli_state *cli,
5719 struct rpc_pipe_client *pipe_hnd,
5720 TALLOC_CTX *mem_ctx,
5721 int argc,
5722 const char **argv)
5724 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5725 WERROR result;
5726 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5728 status = dcerpc_initshutdown_Abort(b, mem_ctx, NULL, &result);
5729 if (!NT_STATUS_IS_OK(status)) {
5730 return status;
5732 if (W_ERROR_IS_OK(result)) {
5733 d_printf(_("\nShutdown successfully aborted\n"));
5734 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5735 } else
5736 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5738 return werror_to_ntstatus(result);
5742 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5744 * All parameters are provided by the run_rpc_command function, except for
5745 * argc, argv which are passed through.
5747 * @param c A net_context structure.
5748 * @param domain_sid The domain sid acquired from the remote server.
5749 * @param cli A cli_state connected to the server.
5750 * @param mem_ctx Talloc context, destroyed on completion of the function.
5751 * @param argc Standard main() style argc.
5752 * @param argv Standard main() style argv. Initial components are already
5753 * stripped.
5755 * @return Normal NTSTATUS return.
5758 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5759 const struct dom_sid *domain_sid,
5760 const char *domain_name,
5761 struct cli_state *cli,
5762 struct rpc_pipe_client *pipe_hnd,
5763 TALLOC_CTX *mem_ctx,
5764 int argc,
5765 const char **argv)
5767 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5768 WERROR werr;
5769 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5771 result = dcerpc_winreg_AbortSystemShutdown(b, mem_ctx, NULL, &werr);
5773 if (!NT_STATUS_IS_OK(result)) {
5774 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5775 return result;
5777 if (W_ERROR_IS_OK(werr)) {
5778 d_printf(_("\nShutdown successfully aborted\n"));
5779 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5780 } else
5781 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5783 return werror_to_ntstatus(werr);
5787 * ABORT the shutdown of a remote RPC server.
5789 * @param argc Standard main() style argc.
5790 * @param argv Standard main() style argv. Initial components are already
5791 * stripped.
5793 * @return A shell status integer (0 for success).
5796 static int rpc_shutdown_abort(struct net_context *c, int argc,
5797 const char **argv)
5799 int rc = -1;
5801 if (c->display_usage) {
5802 d_printf( "%s\n"
5803 "net rpc abortshutdown\n"
5804 " %s\n",
5805 _("Usage:"),
5806 _("Abort a scheduled shutdown"));
5807 return 0;
5810 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5811 rpc_shutdown_abort_internals, argc, argv);
5813 if (rc == 0)
5814 return rc;
5816 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5818 return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5819 rpc_reg_shutdown_abort_internals,
5820 argc, argv);
5824 * Shut down a remote RPC Server via initshutdown pipe.
5826 * All parameters are provided by the run_rpc_command function, except for
5827 * argc, argv which are passed through.
5829 * @param c A net_context structure.
5830 * @param domain_sid The domain sid acquired from the remote server.
5831 * @param cli A cli_state connected to the server.
5832 * @param mem_ctx Talloc context, destroyed on completion of the function.
5833 * @param argc Standard main() style argc.
5834 * @param argv Standard main() style argv. Initial components are already
5835 * stripped.
5837 * @return Normal NTSTATUS return.
5840 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5841 const struct dom_sid *domain_sid,
5842 const char *domain_name,
5843 struct cli_state *cli,
5844 struct rpc_pipe_client *pipe_hnd,
5845 TALLOC_CTX *mem_ctx,
5846 int argc,
5847 const char **argv)
5849 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5850 WERROR result;
5851 const char *msg = N_("This machine will be shutdown shortly");
5852 uint32 timeout = 20;
5853 struct lsa_StringLarge msg_string;
5854 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5856 if (c->opt_comment) {
5857 msg = c->opt_comment;
5859 if (c->opt_timeout) {
5860 timeout = c->opt_timeout;
5863 msg_string.string = msg;
5865 /* create an entry */
5866 status = dcerpc_initshutdown_Init(b, mem_ctx, NULL,
5867 &msg_string, timeout, c->opt_force, c->opt_reboot,
5868 &result);
5869 if (!NT_STATUS_IS_OK(status)) {
5870 return status;
5872 if (W_ERROR_IS_OK(result)) {
5873 d_printf(_("\nShutdown of remote machine succeeded\n"));
5874 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5875 } else {
5876 DEBUG(1,("Shutdown of remote machine failed!\n"));
5878 return werror_to_ntstatus(result);
5882 * Shut down a remote RPC Server via winreg pipe.
5884 * All parameters are provided by the run_rpc_command function, except for
5885 * argc, argv which are passed through.
5887 * @param c A net_context structure.
5888 * @param domain_sid The domain sid acquired from the remote server.
5889 * @param cli A cli_state connected to the server.
5890 * @param mem_ctx Talloc context, destroyed on completion of the function.
5891 * @param argc Standard main() style argc.
5892 * @param argv Standard main() style argv. Initial components are already
5893 * stripped.
5895 * @return Normal NTSTATUS return.
5898 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5899 const struct dom_sid *domain_sid,
5900 const char *domain_name,
5901 struct cli_state *cli,
5902 struct rpc_pipe_client *pipe_hnd,
5903 TALLOC_CTX *mem_ctx,
5904 int argc,
5905 const char **argv)
5907 const char *msg = N_("This machine will be shutdown shortly");
5908 uint32 timeout = 20;
5909 struct lsa_StringLarge msg_string;
5910 NTSTATUS result;
5911 WERROR werr;
5912 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5914 if (c->opt_comment) {
5915 msg = c->opt_comment;
5917 msg_string.string = msg;
5919 if (c->opt_timeout) {
5920 timeout = c->opt_timeout;
5923 /* create an entry */
5924 result = dcerpc_winreg_InitiateSystemShutdown(b, mem_ctx, NULL,
5925 &msg_string, timeout, c->opt_force, c->opt_reboot,
5926 &werr);
5927 if (!NT_STATUS_IS_OK(result)) {
5928 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5929 return result;
5932 if (W_ERROR_IS_OK(werr)) {
5933 d_printf(_("\nShutdown of remote machine succeeded\n"));
5934 } else {
5935 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5936 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5937 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5938 else
5939 d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5942 return werror_to_ntstatus(werr);
5946 * Shut down a remote RPC server.
5948 * @param argc Standard main() style argc.
5949 * @param argv Standard main() style argv. Initial components are already
5950 * stripped.
5952 * @return A shell status integer (0 for success).
5955 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5957 int rc = -1;
5959 if (c->display_usage) {
5960 d_printf( "%s\n"
5961 "net rpc shutdown\n"
5962 " %s\n",
5963 _("Usage:"),
5964 _("Shut down a remote RPC server"));
5965 return 0;
5968 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5969 rpc_init_shutdown_internals, argc, argv);
5971 if (rc) {
5972 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5973 rc = run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5974 rpc_reg_shutdown_internals, argc, argv);
5977 return rc;
5980 /***************************************************************************
5981 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5982 ***************************************************************************/
5985 * Add interdomain trust account to the RPC server.
5986 * All parameters (except for argc and argv) are passed by run_rpc_command
5987 * function.
5989 * @param c A net_context structure.
5990 * @param domain_sid The domain sid acquired from the server.
5991 * @param cli A cli_state connected to the server.
5992 * @param mem_ctx Talloc context, destroyed on completion of the function.
5993 * @param argc Standard main() style argc.
5994 * @param argv Standard main() style argv. Initial components are already
5995 * stripped.
5997 * @return normal NTSTATUS return code.
6000 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
6001 const struct dom_sid *domain_sid,
6002 const char *domain_name,
6003 struct cli_state *cli,
6004 struct rpc_pipe_client *pipe_hnd,
6005 TALLOC_CTX *mem_ctx,
6006 int argc,
6007 const char **argv)
6009 struct policy_handle connect_pol, domain_pol, user_pol;
6010 NTSTATUS status, result;
6011 char *acct_name;
6012 struct lsa_String lsa_acct_name;
6013 uint32 acb_info;
6014 uint32 acct_flags=0;
6015 uint32 user_rid;
6016 uint32_t access_granted = 0;
6017 union samr_UserInfo info;
6018 unsigned int orig_timeout;
6019 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6020 DATA_BLOB session_key = data_blob_null;
6022 if (argc != 2) {
6023 d_printf("%s\n%s",
6024 _("Usage:"),
6025 _(" net rpc trustdom add <domain_name> "
6026 "<trust password>\n"));
6027 return NT_STATUS_INVALID_PARAMETER;
6031 * Make valid trusting domain account (ie. uppercased and with '$' appended)
6034 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
6035 return NT_STATUS_NO_MEMORY;
6038 if (!strupper_m(acct_name)) {
6039 SAFE_FREE(acct_name);
6040 return NT_STATUS_INVALID_PARAMETER;
6043 init_lsa_String(&lsa_acct_name, acct_name);
6045 status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
6046 if (!NT_STATUS_IS_OK(status)) {
6047 DEBUG(0,("Error getting session_key of SAM pipe. Error was %s\n",
6048 nt_errstr(status)));
6049 goto done;
6052 /* Get samr policy handle */
6053 status = dcerpc_samr_Connect2(b, mem_ctx,
6054 pipe_hnd->desthost,
6055 MAXIMUM_ALLOWED_ACCESS,
6056 &connect_pol,
6057 &result);
6058 if (!NT_STATUS_IS_OK(status)) {
6059 goto done;
6061 if (!NT_STATUS_IS_OK(result)) {
6062 status = result;
6063 goto done;
6066 /* Get domain policy handle */
6067 status = dcerpc_samr_OpenDomain(b, mem_ctx,
6068 &connect_pol,
6069 MAXIMUM_ALLOWED_ACCESS,
6070 discard_const_p(struct dom_sid2, domain_sid),
6071 &domain_pol,
6072 &result);
6073 if (!NT_STATUS_IS_OK(status)) {
6074 goto done;
6076 if (!NT_STATUS_IS_OK(result)) {
6077 status = result;
6078 goto done;
6081 /* This call can take a long time - allow the server to time out.
6082 * 35 seconds should do it. */
6084 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
6086 /* Create trusting domain's account */
6087 acb_info = ACB_NORMAL;
6088 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
6089 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
6090 SAMR_USER_ACCESS_SET_PASSWORD |
6091 SAMR_USER_ACCESS_GET_ATTRIBUTES |
6092 SAMR_USER_ACCESS_SET_ATTRIBUTES;
6094 status = dcerpc_samr_CreateUser2(b, mem_ctx,
6095 &domain_pol,
6096 &lsa_acct_name,
6097 acb_info,
6098 acct_flags,
6099 &user_pol,
6100 &access_granted,
6101 &user_rid,
6102 &result);
6103 if (!NT_STATUS_IS_OK(status)) {
6104 goto done;
6106 /* And restore our original timeout. */
6107 rpccli_set_timeout(pipe_hnd, orig_timeout);
6109 if (!NT_STATUS_IS_OK(result)) {
6110 status = result;
6111 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
6112 acct_name, nt_errstr(result));
6113 goto done;
6117 struct samr_CryptPassword crypt_pwd;
6119 ZERO_STRUCT(info.info23);
6121 init_samr_CryptPassword(argv[1],
6122 &session_key,
6123 &crypt_pwd);
6125 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
6126 SAMR_FIELD_NT_PASSWORD_PRESENT;
6127 info.info23.info.acct_flags = ACB_DOMTRUST;
6128 info.info23.password = crypt_pwd;
6130 status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
6131 &user_pol,
6133 &info,
6134 &result);
6135 if (!NT_STATUS_IS_OK(status)) {
6136 goto done;
6139 if (!NT_STATUS_IS_OK(result)) {
6140 status = result;
6141 DEBUG(0,("Could not set trust account password: %s\n",
6142 nt_errstr(result)));
6143 goto done;
6147 done:
6148 SAFE_FREE(acct_name);
6149 data_blob_clear_free(&session_key);
6150 return status;
6154 * Create interdomain trust account for a remote domain.
6156 * @param argc Standard argc.
6157 * @param argv Standard argv without initial components.
6159 * @return Integer status (0 means success).
6162 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
6164 if (argc > 0 && !c->display_usage) {
6165 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6166 rpc_trustdom_add_internals, argc, argv);
6167 } else {
6168 d_printf("%s\n%s",
6169 _("Usage:"),
6170 _("net rpc trustdom add <domain_name> <trust "
6171 "password>\n"));
6172 return -1;
6178 * Remove interdomain trust account from the RPC server.
6179 * All parameters (except for argc and argv) are passed by run_rpc_command
6180 * function.
6182 * @param c A net_context structure.
6183 * @param domain_sid The domain sid acquired from the server.
6184 * @param cli A cli_state connected to the server.
6185 * @param mem_ctx Talloc context, destroyed on completion of the function.
6186 * @param argc Standard main() style argc.
6187 * @param argv Standard main() style argv. Initial components are already
6188 * stripped.
6190 * @return normal NTSTATUS return code.
6193 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
6194 const struct dom_sid *domain_sid,
6195 const char *domain_name,
6196 struct cli_state *cli,
6197 struct rpc_pipe_client *pipe_hnd,
6198 TALLOC_CTX *mem_ctx,
6199 int argc,
6200 const char **argv)
6202 struct policy_handle connect_pol, domain_pol, user_pol;
6203 NTSTATUS status, result;
6204 char *acct_name;
6205 struct dom_sid trust_acct_sid;
6206 struct samr_Ids user_rids, name_types;
6207 struct lsa_String lsa_acct_name;
6208 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6210 if (argc != 1) {
6211 d_printf("%s\n%s",
6212 _("Usage:"),
6213 _(" net rpc trustdom del <domain_name>\n"));
6214 return NT_STATUS_INVALID_PARAMETER;
6218 * Make valid trusting domain account (ie. uppercased and with '$' appended)
6220 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
6222 if (acct_name == NULL)
6223 return NT_STATUS_NO_MEMORY;
6225 if (!strupper_m(acct_name)) {
6226 TALLOC_FREE(acct_name);
6227 return NT_STATUS_INVALID_PARAMETER;
6230 /* Get samr policy handle */
6231 status = dcerpc_samr_Connect2(b, mem_ctx,
6232 pipe_hnd->desthost,
6233 MAXIMUM_ALLOWED_ACCESS,
6234 &connect_pol,
6235 &result);
6236 if (!NT_STATUS_IS_OK(status)) {
6237 goto done;
6239 if (!NT_STATUS_IS_OK(result)) {
6240 status = result;
6241 goto done;
6244 /* Get domain policy handle */
6245 status = dcerpc_samr_OpenDomain(b, mem_ctx,
6246 &connect_pol,
6247 MAXIMUM_ALLOWED_ACCESS,
6248 discard_const_p(struct dom_sid2, domain_sid),
6249 &domain_pol,
6250 &result);
6251 if (!NT_STATUS_IS_OK(status)) {
6252 goto done;
6254 if (!NT_STATUS_IS_OK(result)) {
6255 status = result;
6256 goto done;
6259 init_lsa_String(&lsa_acct_name, acct_name);
6261 status = dcerpc_samr_LookupNames(b, mem_ctx,
6262 &domain_pol,
6264 &lsa_acct_name,
6265 &user_rids,
6266 &name_types,
6267 &result);
6268 if (!NT_STATUS_IS_OK(status)) {
6269 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6270 "failed %s\n"),
6271 acct_name, nt_errstr(status));
6272 goto done;
6274 if (!NT_STATUS_IS_OK(result)) {
6275 status = result;
6276 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6277 "failed %s\n"),
6278 acct_name, nt_errstr(result) );
6279 goto done;
6281 if (user_rids.count != 1) {
6282 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6283 goto done;
6285 if (name_types.count != 1) {
6286 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6287 goto done;
6290 status = dcerpc_samr_OpenUser(b, mem_ctx,
6291 &domain_pol,
6292 MAXIMUM_ALLOWED_ACCESS,
6293 user_rids.ids[0],
6294 &user_pol,
6295 &result);
6296 if (!NT_STATUS_IS_OK(status)) {
6297 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6298 "%s\n"),
6299 acct_name, nt_errstr(status) );
6300 goto done;
6303 if (!NT_STATUS_IS_OK(result)) {
6304 status = result;
6305 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6306 "%s\n"),
6307 acct_name, nt_errstr(result) );
6308 goto done;
6311 /* append the rid to the domain sid */
6312 if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
6313 goto done;
6316 /* remove the sid */
6318 status = dcerpc_samr_RemoveMemberFromForeignDomain(b, mem_ctx,
6319 &user_pol,
6320 &trust_acct_sid,
6321 &result);
6322 if (!NT_STATUS_IS_OK(status)) {
6323 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6324 " on user %s failed %s\n"),
6325 acct_name, nt_errstr(status));
6326 goto done;
6328 if (!NT_STATUS_IS_OK(result)) {
6329 status = result;
6330 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6331 " on user %s failed %s\n"),
6332 acct_name, nt_errstr(result) );
6333 goto done;
6337 /* Delete user */
6339 status = dcerpc_samr_DeleteUser(b, mem_ctx,
6340 &user_pol,
6341 &result);
6342 if (!NT_STATUS_IS_OK(status)) {
6343 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6344 "%s\n"),
6345 acct_name, nt_errstr(status));
6346 goto done;
6349 if (!NT_STATUS_IS_OK(result)) {
6350 result = status;
6351 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6352 "%s\n"),
6353 acct_name, nt_errstr(result) );
6354 goto done;
6357 if (!NT_STATUS_IS_OK(result)) {
6358 d_printf(_("Could not set trust account password: %s\n"),
6359 nt_errstr(result));
6360 goto done;
6363 done:
6364 return status;
6368 * Delete interdomain trust account for a remote domain.
6370 * @param argc Standard argc.
6371 * @param argv Standard argv without initial components.
6373 * @return Integer status (0 means success).
6376 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
6378 if (argc > 0 && !c->display_usage) {
6379 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6380 rpc_trustdom_del_internals, argc, argv);
6381 } else {
6382 d_printf("%s\n%s",
6383 _("Usage:"),
6384 _("net rpc trustdom del <domain>\n"));
6385 return -1;
6389 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
6390 struct cli_state *cli,
6391 TALLOC_CTX *mem_ctx,
6392 const char *domain_name)
6394 char *dc_name = NULL;
6395 const char *buffer = NULL;
6396 struct rpc_pipe_client *netr;
6397 NTSTATUS status;
6398 WERROR result;
6399 struct dcerpc_binding_handle *b;
6401 /* Use NetServerEnum2 */
6403 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
6404 SAFE_FREE(dc_name);
6405 return NT_STATUS_OK;
6408 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
6409 for domain %s\n", domain_name));
6411 /* Try netr_GetDcName */
6413 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon,
6414 &netr);
6415 if (!NT_STATUS_IS_OK(status)) {
6416 return status;
6419 b = netr->binding_handle;
6421 status = dcerpc_netr_GetDcName(b, mem_ctx,
6422 netr->desthost,
6423 domain_name,
6424 &buffer,
6425 &result);
6426 TALLOC_FREE(netr);
6428 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
6429 return status;
6432 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
6433 for domain %s\n", domain_name));
6435 if (!NT_STATUS_IS_OK(status)) {
6436 return status;
6439 return werror_to_ntstatus(result);
6443 * Establish trust relationship to a trusting domain.
6444 * Interdomain account must already be created on remote PDC.
6446 * @param c A net_context structure.
6447 * @param argc Standard argc.
6448 * @param argv Standard argv without initial components.
6450 * @return Integer status (0 means success).
6453 static int rpc_trustdom_establish(struct net_context *c, int argc,
6454 const char **argv)
6456 struct cli_state *cli = NULL;
6457 struct sockaddr_storage server_ss;
6458 struct rpc_pipe_client *pipe_hnd = NULL;
6459 struct policy_handle connect_hnd;
6460 TALLOC_CTX *mem_ctx;
6461 NTSTATUS nt_status, result;
6462 struct dom_sid *domain_sid;
6464 char* domain_name;
6465 char* acct_name;
6466 fstring pdc_name;
6467 union lsa_PolicyInformation *info = NULL;
6468 struct dcerpc_binding_handle *b;
6471 * Connect to \\server\ipc$ as 'our domain' account with password
6474 if (argc != 1 || c->display_usage) {
6475 d_printf("%s\n%s",
6476 _("Usage:"),
6477 _("net rpc trustdom establish <domain_name>\n"));
6478 return -1;
6481 domain_name = smb_xstrdup(argv[0]);
6482 if (!strupper_m(domain_name)) {
6483 SAFE_FREE(domain_name);
6484 return -1;
6487 /* account name used at first is our domain's name with '$' */
6488 if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
6489 return -1;
6491 if (!strupper_m(acct_name)) {
6492 SAFE_FREE(domain_name);
6493 SAFE_FREE(acct_name);
6494 return -1;
6498 * opt_workgroup will be used by connection functions further,
6499 * hence it should be set to remote domain name instead of ours
6501 if (c->opt_workgroup) {
6502 c->opt_workgroup = smb_xstrdup(domain_name);
6505 c->opt_user_name = acct_name;
6507 /* find the domain controller */
6508 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
6509 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
6510 return -1;
6513 /* connect to ipc$ as username/password */
6514 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
6515 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
6517 /* Is it trusting domain account for sure ? */
6518 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
6519 nt_errstr(nt_status)));
6520 return -1;
6523 /* store who we connected to */
6525 saf_store( domain_name, pdc_name );
6528 * Connect to \\server\ipc$ again (this time anonymously)
6531 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
6532 (char*)pdc_name);
6534 if (NT_STATUS_IS_ERR(nt_status)) {
6535 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
6536 domain_name, nt_errstr(nt_status)));
6537 return -1;
6540 if (!(mem_ctx = talloc_init("establishing trust relationship to "
6541 "domain %s", domain_name))) {
6542 DEBUG(0, ("talloc_init() failed\n"));
6543 cli_shutdown(cli);
6544 return -1;
6547 /* Make sure we're talking to a proper server */
6549 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
6550 if (!NT_STATUS_IS_OK(nt_status)) {
6551 cli_shutdown(cli);
6552 talloc_destroy(mem_ctx);
6553 return -1;
6557 * Call LsaOpenPolicy and LsaQueryInfo
6560 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
6561 &pipe_hnd);
6562 if (!NT_STATUS_IS_OK(nt_status)) {
6563 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
6564 cli_shutdown(cli);
6565 talloc_destroy(mem_ctx);
6566 return -1;
6569 b = pipe_hnd->binding_handle;
6571 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
6572 &connect_hnd);
6573 if (NT_STATUS_IS_ERR(nt_status)) {
6574 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6575 nt_errstr(nt_status)));
6576 cli_shutdown(cli);
6577 talloc_destroy(mem_ctx);
6578 return -1;
6581 /* Querying info level 5 */
6583 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6584 &connect_hnd,
6585 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6586 &info,
6587 &result);
6588 if (NT_STATUS_IS_ERR(nt_status)) {
6589 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6590 nt_errstr(nt_status)));
6591 cli_shutdown(cli);
6592 talloc_destroy(mem_ctx);
6593 return -1;
6595 if (NT_STATUS_IS_ERR(result)) {
6596 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6597 nt_errstr(result)));
6598 cli_shutdown(cli);
6599 talloc_destroy(mem_ctx);
6600 return -1;
6603 domain_sid = info->account_domain.sid;
6605 /* There should be actually query info level 3 (following nt serv behaviour),
6606 but I still don't know if it's _really_ necessary */
6609 * Store the password in secrets db
6612 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6613 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6614 cli_shutdown(cli);
6615 talloc_destroy(mem_ctx);
6616 return -1;
6620 * Close the pipes and clean up
6623 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6624 if (NT_STATUS_IS_ERR(nt_status)) {
6625 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6626 nt_errstr(nt_status)));
6627 cli_shutdown(cli);
6628 talloc_destroy(mem_ctx);
6629 return -1;
6632 cli_shutdown(cli);
6634 talloc_destroy(mem_ctx);
6636 d_printf(_("Trust to domain %s established\n"), domain_name);
6637 return 0;
6641 * Revoke trust relationship to the remote domain.
6643 * @param c A net_context structure.
6644 * @param argc Standard argc.
6645 * @param argv Standard argv without initial components.
6647 * @return Integer status (0 means success).
6650 static int rpc_trustdom_revoke(struct net_context *c, int argc,
6651 const char **argv)
6653 char* domain_name;
6654 int rc = -1;
6656 if (argc < 1 || c->display_usage) {
6657 d_printf("%s\n%s",
6658 _("Usage:"),
6659 _("net rpc trustdom revoke <domain_name>\n"
6660 " Revoke trust relationship\n"
6661 " domain_name\tName of domain to revoke trust\n"));
6662 return -1;
6665 /* generate upper cased domain name */
6666 domain_name = smb_xstrdup(argv[0]);
6667 if (!strupper_m(domain_name)) {
6668 SAFE_FREE(domain_name);
6669 return -1;
6672 /* delete password of the trust */
6673 if (!pdb_del_trusteddom_pw(domain_name)) {
6674 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6675 domain_name));
6676 goto done;
6679 rc = 0;
6680 done:
6681 SAFE_FREE(domain_name);
6682 return rc;
6685 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6686 const struct dom_sid *domain_sid,
6687 const char *domain_name,
6688 struct cli_state *cli,
6689 struct rpc_pipe_client *pipe_hnd,
6690 TALLOC_CTX *mem_ctx,
6691 int argc,
6692 const char **argv)
6694 fstring str_sid;
6695 if (!sid_to_fstring(str_sid, domain_sid)) {
6696 return NT_STATUS_UNSUCCESSFUL;
6698 d_printf("%s\n", str_sid);
6699 return NT_STATUS_OK;
6702 static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
6704 fstring ascii_sid;
6706 /* convert sid into ascii string */
6707 sid_to_fstring(ascii_sid, dom_sid);
6709 d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
6712 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6713 TALLOC_CTX *mem_ctx,
6714 struct policy_handle *pol,
6715 struct dom_sid dom_sid,
6716 const char *trusted_dom_name)
6718 NTSTATUS nt_status, result;
6719 union lsa_TrustedDomainInfo *info = NULL;
6720 char *cleartextpwd = NULL;
6721 DATA_BLOB session_key;
6722 DATA_BLOB data = data_blob_null;
6723 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6725 nt_status = dcerpc_lsa_QueryTrustedDomainInfoBySid(b, mem_ctx,
6726 pol,
6727 &dom_sid,
6728 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6729 &info,
6730 &result);
6731 if (NT_STATUS_IS_ERR(nt_status)) {
6732 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6733 nt_errstr(nt_status)));
6734 goto done;
6736 if (NT_STATUS_IS_ERR(result)) {
6737 nt_status = result;
6738 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6739 nt_errstr(result)));
6740 goto done;
6743 data = data_blob(info->password.password->data,
6744 info->password.password->length);
6746 nt_status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
6747 if (!NT_STATUS_IS_OK(nt_status)) {
6748 DEBUG(0, ("Could not retrieve session key: %s\n", nt_errstr(nt_status)));
6749 goto done;
6752 cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key);
6753 data_blob_free(&session_key);
6755 if (cleartextpwd == NULL) {
6756 DEBUG(0,("retrieved NULL password\n"));
6757 nt_status = NT_STATUS_UNSUCCESSFUL;
6758 goto done;
6761 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6762 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6763 nt_status = NT_STATUS_UNSUCCESSFUL;
6764 goto done;
6767 #ifdef DEBUG_PASSWORD
6768 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
6769 "password: [%s]\n", trusted_dom_name,
6770 sid_string_dbg(&dom_sid), cleartextpwd));
6771 #endif
6773 done:
6774 SAFE_FREE(cleartextpwd);
6775 data_blob_free(&data);
6777 return nt_status;
6780 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6781 const char **argv)
6783 /* common variables */
6784 TALLOC_CTX* mem_ctx;
6785 struct cli_state *cli = NULL;
6786 struct rpc_pipe_client *pipe_hnd = NULL;
6787 NTSTATUS nt_status, result;
6788 const char *domain_name = NULL;
6789 struct policy_handle connect_hnd;
6790 union lsa_PolicyInformation *info = NULL;
6792 /* trusted domains listing variables */
6793 unsigned int enum_ctx = 0;
6794 int i;
6795 struct lsa_DomainList dom_list;
6796 fstring pdc_name;
6797 struct dcerpc_binding_handle *b;
6799 if (c->display_usage) {
6800 d_printf( "%s\n"
6801 "net rpc trustdom vampire\n"
6802 " %s\n",
6803 _("Usage:"),
6804 _("Vampire trust relationship from remote server"));
6805 return 0;
6809 * Listing trusted domains (stored in secrets.tdb, if local)
6812 mem_ctx = talloc_init("trust relationships vampire");
6815 * set domain and pdc name to local samba server (default)
6816 * or to remote one given in command line
6819 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6820 domain_name = c->opt_workgroup;
6821 c->opt_target_workgroup = c->opt_workgroup;
6822 } else {
6823 fstrcpy(pdc_name, lp_netbios_name());
6824 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6825 c->opt_target_workgroup = domain_name;
6828 /* open \PIPE\lsarpc and open policy handle */
6829 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6830 if (!NT_STATUS_IS_OK(nt_status)) {
6831 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6832 nt_errstr(nt_status)));
6833 talloc_destroy(mem_ctx);
6834 return -1;
6837 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
6838 &pipe_hnd);
6839 if (!NT_STATUS_IS_OK(nt_status)) {
6840 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6841 nt_errstr(nt_status) ));
6842 cli_shutdown(cli);
6843 talloc_destroy(mem_ctx);
6844 return -1;
6847 b = pipe_hnd->binding_handle;
6849 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6850 &connect_hnd);
6851 if (NT_STATUS_IS_ERR(nt_status)) {
6852 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6853 nt_errstr(nt_status)));
6854 cli_shutdown(cli);
6855 talloc_destroy(mem_ctx);
6856 return -1;
6859 /* query info level 5 to obtain sid of a domain being queried */
6860 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6861 &connect_hnd,
6862 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6863 &info,
6864 &result);
6866 if (NT_STATUS_IS_ERR(nt_status)) {
6867 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6868 nt_errstr(nt_status)));
6869 cli_shutdown(cli);
6870 talloc_destroy(mem_ctx);
6871 return -1;
6873 if (NT_STATUS_IS_ERR(result)) {
6874 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6875 nt_errstr(result)));
6876 cli_shutdown(cli);
6877 talloc_destroy(mem_ctx);
6878 return -1;
6882 * Keep calling LsaEnumTrustdom over opened pipe until
6883 * the end of enumeration is reached
6886 d_printf(_("Vampire trusted domains:\n\n"));
6888 do {
6889 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
6890 &connect_hnd,
6891 &enum_ctx,
6892 &dom_list,
6893 (uint32_t)-1,
6894 &result);
6895 if (NT_STATUS_IS_ERR(nt_status)) {
6896 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6897 nt_errstr(nt_status)));
6898 cli_shutdown(cli);
6899 talloc_destroy(mem_ctx);
6900 return -1;
6902 if (NT_STATUS_IS_ERR(result)) {
6903 nt_status = result;
6904 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6905 nt_errstr(result)));
6906 cli_shutdown(cli);
6907 talloc_destroy(mem_ctx);
6908 return -1;
6912 for (i = 0; i < dom_list.count; i++) {
6914 print_trusted_domain(dom_list.domains[i].sid,
6915 dom_list.domains[i].name.string);
6917 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
6918 *dom_list.domains[i].sid,
6919 dom_list.domains[i].name.string);
6920 if (!NT_STATUS_IS_OK(nt_status)) {
6921 cli_shutdown(cli);
6922 talloc_destroy(mem_ctx);
6923 return -1;
6928 * in case of no trusted domains say something rather
6929 * than just display blank line
6931 if (!dom_list.count) d_printf(_("none\n"));
6933 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6935 /* close this connection before doing next one */
6936 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6937 if (NT_STATUS_IS_ERR(nt_status)) {
6938 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6939 nt_errstr(nt_status)));
6940 cli_shutdown(cli);
6941 talloc_destroy(mem_ctx);
6942 return -1;
6945 /* close lsarpc pipe and connection to IPC$ */
6946 cli_shutdown(cli);
6948 talloc_destroy(mem_ctx);
6949 return 0;
6952 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6954 /* common variables */
6955 TALLOC_CTX* mem_ctx;
6956 struct cli_state *cli = NULL, *remote_cli = NULL;
6957 struct rpc_pipe_client *pipe_hnd = NULL;
6958 NTSTATUS nt_status, result;
6959 const char *domain_name = NULL;
6960 struct dom_sid *queried_dom_sid;
6961 int ascii_dom_name_len;
6962 struct policy_handle connect_hnd;
6963 union lsa_PolicyInformation *info = NULL;
6964 struct dcerpc_binding_handle *b = NULL;
6966 /* trusted domains listing variables */
6967 unsigned int num_domains, enum_ctx = 0;
6968 int i;
6969 struct lsa_DomainList dom_list;
6970 fstring pdc_name;
6971 bool found_domain;
6973 /* trusting domains listing variables */
6974 struct policy_handle domain_hnd;
6975 struct samr_SamArray *trusts = NULL;
6977 if (c->display_usage) {
6978 d_printf( "%s\n"
6979 "net rpc trustdom list\n"
6980 " %s\n",
6981 _("Usage:"),
6982 _("List incoming and outgoing trust relationships"));
6983 return 0;
6987 * Listing trusted domains (stored in secrets.tdb, if local)
6990 mem_ctx = talloc_init("trust relationships listing");
6993 * set domain and pdc name to local samba server (default)
6994 * or to remote one given in command line
6997 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6998 domain_name = c->opt_workgroup;
6999 c->opt_target_workgroup = c->opt_workgroup;
7000 } else {
7001 fstrcpy(pdc_name, lp_netbios_name());
7002 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
7003 c->opt_target_workgroup = domain_name;
7006 /* open \PIPE\lsarpc and open policy handle */
7007 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
7008 if (!NT_STATUS_IS_OK(nt_status)) {
7009 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
7010 nt_errstr(nt_status)));
7011 talloc_destroy(mem_ctx);
7012 return -1;
7015 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
7016 &pipe_hnd);
7017 if (!NT_STATUS_IS_OK(nt_status)) {
7018 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
7019 nt_errstr(nt_status) ));
7020 cli_shutdown(cli);
7021 talloc_destroy(mem_ctx);
7022 return -1;
7025 b = pipe_hnd->binding_handle;
7027 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
7028 &connect_hnd);
7029 if (NT_STATUS_IS_ERR(nt_status)) {
7030 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
7031 nt_errstr(nt_status)));
7032 cli_shutdown(cli);
7033 talloc_destroy(mem_ctx);
7034 return -1;
7037 /* query info level 5 to obtain sid of a domain being queried */
7038 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
7039 &connect_hnd,
7040 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
7041 &info,
7042 &result);
7044 if (NT_STATUS_IS_ERR(nt_status)) {
7045 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
7046 nt_errstr(nt_status)));
7047 cli_shutdown(cli);
7048 talloc_destroy(mem_ctx);
7049 return -1;
7051 if (NT_STATUS_IS_ERR(result)) {
7052 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
7053 nt_errstr(result)));
7054 cli_shutdown(cli);
7055 talloc_destroy(mem_ctx);
7056 return -1;
7059 queried_dom_sid = info->account_domain.sid;
7062 * Keep calling LsaEnumTrustdom over opened pipe until
7063 * the end of enumeration is reached
7066 d_printf(_("Trusted domains list:\n\n"));
7068 found_domain = false;
7070 do {
7071 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
7072 &connect_hnd,
7073 &enum_ctx,
7074 &dom_list,
7075 (uint32_t)-1,
7076 &result);
7077 if (NT_STATUS_IS_ERR(nt_status)) {
7078 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7079 nt_errstr(nt_status)));
7080 cli_shutdown(cli);
7081 talloc_destroy(mem_ctx);
7082 return -1;
7084 if (NT_STATUS_IS_ERR(result)) {
7085 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7086 nt_errstr(result)));
7087 cli_shutdown(cli);
7088 talloc_destroy(mem_ctx);
7089 return -1;
7093 for (i = 0; i < dom_list.count; i++) {
7094 print_trusted_domain(dom_list.domains[i].sid,
7095 dom_list.domains[i].name.string);
7096 found_domain = true;
7100 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
7103 * in case of no trusted domains say something rather
7104 * than just display blank line
7106 if (!found_domain) {
7107 d_printf(_("none\n"));
7110 /* close this connection before doing next one */
7111 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
7112 if (NT_STATUS_IS_ERR(nt_status)) {
7113 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
7114 nt_errstr(nt_status)));
7115 cli_shutdown(cli);
7116 talloc_destroy(mem_ctx);
7117 return -1;
7120 TALLOC_FREE(pipe_hnd);
7123 * Listing trusting domains (stored in passdb backend, if local)
7126 d_printf(_("\nTrusting domains list:\n\n"));
7129 * Open \PIPE\samr and get needed policy handles
7131 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr,
7132 &pipe_hnd);
7133 if (!NT_STATUS_IS_OK(nt_status)) {
7134 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
7135 cli_shutdown(cli);
7136 talloc_destroy(mem_ctx);
7137 return -1;
7140 b = pipe_hnd->binding_handle;
7142 /* SamrConnect2 */
7143 nt_status = dcerpc_samr_Connect2(b, mem_ctx,
7144 pipe_hnd->desthost,
7145 SAMR_ACCESS_LOOKUP_DOMAIN,
7146 &connect_hnd,
7147 &result);
7148 if (!NT_STATUS_IS_OK(nt_status)) {
7149 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
7150 nt_errstr(nt_status)));
7151 cli_shutdown(cli);
7152 talloc_destroy(mem_ctx);
7153 return -1;
7155 if (!NT_STATUS_IS_OK(result)) {
7156 nt_status = result;
7157 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
7158 nt_errstr(result)));
7159 cli_shutdown(cli);
7160 talloc_destroy(mem_ctx);
7161 return -1;
7164 /* SamrOpenDomain - we have to open domain policy handle in order to be
7165 able to enumerate accounts*/
7166 nt_status = dcerpc_samr_OpenDomain(b, mem_ctx,
7167 &connect_hnd,
7168 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
7169 queried_dom_sid,
7170 &domain_hnd,
7171 &result);
7172 if (!NT_STATUS_IS_OK(nt_status)) {
7173 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7174 nt_errstr(nt_status)));
7175 cli_shutdown(cli);
7176 talloc_destroy(mem_ctx);
7177 return -1;
7179 if (!NT_STATUS_IS_OK(result)) {
7180 nt_status = result;
7181 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7182 nt_errstr(result)));
7183 cli_shutdown(cli);
7184 talloc_destroy(mem_ctx);
7185 return -1;
7189 * perform actual enumeration
7192 found_domain = false;
7194 enum_ctx = 0; /* reset enumeration context from last enumeration */
7195 do {
7197 nt_status = dcerpc_samr_EnumDomainUsers(b, mem_ctx,
7198 &domain_hnd,
7199 &enum_ctx,
7200 ACB_DOMTRUST,
7201 &trusts,
7202 0xffff,
7203 &num_domains,
7204 &result);
7205 if (NT_STATUS_IS_ERR(nt_status)) {
7206 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7207 nt_errstr(nt_status)));
7208 cli_shutdown(cli);
7209 talloc_destroy(mem_ctx);
7210 return -1;
7212 if (NT_STATUS_IS_ERR(result)) {
7213 nt_status = result;
7214 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7215 nt_errstr(result)));
7216 cli_shutdown(cli);
7217 talloc_destroy(mem_ctx);
7218 return -1;
7221 for (i = 0; i < num_domains; i++) {
7223 char *str = discard_const_p(char, trusts->entries[i].name.string);
7225 found_domain = true;
7228 * get each single domain's sid (do we _really_ need this ?):
7229 * 1) connect to domain's pdc
7230 * 2) query the pdc for domain's sid
7233 /* get rid of '$' tail */
7234 ascii_dom_name_len = strlen(str);
7235 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
7236 str[ascii_dom_name_len - 1] = '\0';
7238 /* set opt_* variables to remote domain */
7239 if (!strupper_m(str)) {
7240 cli_shutdown(cli);
7241 talloc_destroy(mem_ctx);
7242 return -1;
7244 c->opt_workgroup = talloc_strdup(mem_ctx, str);
7245 c->opt_target_workgroup = c->opt_workgroup;
7247 d_printf("%-20s", str);
7249 /* connect to remote domain controller */
7250 nt_status = net_make_ipc_connection(c,
7251 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
7252 &remote_cli);
7253 if (NT_STATUS_IS_OK(nt_status)) {
7254 /* query for domain's sid */
7255 if (run_rpc_command(
7256 c, remote_cli,
7257 &ndr_table_lsarpc, 0,
7258 rpc_query_domain_sid, argc,
7259 argv))
7260 d_printf(_("strange - couldn't get domain's sid\n"));
7262 cli_shutdown(remote_cli);
7264 } else {
7265 d_fprintf(stderr, _("domain controller is not "
7266 "responding: %s\n"),
7267 nt_errstr(nt_status));
7268 d_printf(_("couldn't get domain's sid\n"));
7272 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
7274 if (!found_domain) {
7275 d_printf("none\n");
7278 /* close opened samr and domain policy handles */
7279 nt_status = dcerpc_samr_Close(b, mem_ctx, &domain_hnd, &result);
7280 if (!NT_STATUS_IS_OK(nt_status)) {
7281 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
7284 nt_status = dcerpc_samr_Close(b, mem_ctx, &connect_hnd, &result);
7285 if (!NT_STATUS_IS_OK(nt_status)) {
7286 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
7289 /* close samr pipe and connection to IPC$ */
7290 cli_shutdown(cli);
7292 talloc_destroy(mem_ctx);
7293 return 0;
7297 * Entrypoint for 'net rpc trustdom' code.
7299 * @param argc Standard argc.
7300 * @param argv Standard argv without initial components.
7302 * @return Integer status (0 means success).
7305 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
7307 struct functable func[] = {
7309 "add",
7310 rpc_trustdom_add,
7311 NET_TRANSPORT_RPC,
7312 N_("Add trusting domain's account"),
7313 N_("net rpc trustdom add\n"
7314 " Add trusting domain's account")
7317 "del",
7318 rpc_trustdom_del,
7319 NET_TRANSPORT_RPC,
7320 N_("Remove trusting domain's account"),
7321 N_("net rpc trustdom del\n"
7322 " Remove trusting domain's account")
7325 "establish",
7326 rpc_trustdom_establish,
7327 NET_TRANSPORT_RPC,
7328 N_("Establish outgoing trust relationship"),
7329 N_("net rpc trustdom establish\n"
7330 " Establish outgoing trust relationship")
7333 "revoke",
7334 rpc_trustdom_revoke,
7335 NET_TRANSPORT_RPC,
7336 N_("Revoke outgoing trust relationship"),
7337 N_("net rpc trustdom revoke\n"
7338 " Revoke outgoing trust relationship")
7341 "list",
7342 rpc_trustdom_list,
7343 NET_TRANSPORT_RPC,
7344 N_("List in- and outgoing domain trusts"),
7345 N_("net rpc trustdom list\n"
7346 " List in- and outgoing domain trusts")
7349 "vampire",
7350 rpc_trustdom_vampire,
7351 NET_TRANSPORT_RPC,
7352 N_("Vampire trusts from remote server"),
7353 N_("net rpc trustdom vampire\n"
7354 " Vampire trusts from remote server")
7356 {NULL, NULL, 0, NULL, NULL}
7359 return net_run_function(c, argc, argv, "net rpc trustdom", func);
7363 * Check if a server will take rpc commands
7364 * @param flags Type of server to connect to (PDC, DMB, localhost)
7365 * if the host is not explicitly specified
7366 * @return bool (true means rpc supported)
7368 bool net_rpc_check(struct net_context *c, unsigned flags)
7370 struct cli_state *cli;
7371 bool ret = false;
7372 struct sockaddr_storage server_ss;
7373 char *server_name = NULL;
7374 NTSTATUS status;
7376 /* flags (i.e. server type) may depend on command */
7377 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
7378 return false;
7380 status = cli_connect_nb(server_name, &server_ss, 0, 0x20,
7381 lp_netbios_name(), SMB_SIGNING_DEFAULT,
7382 0, &cli);
7383 if (!NT_STATUS_IS_OK(status)) {
7384 return false;
7386 status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
7387 PROTOCOL_NT1);
7388 if (!NT_STATUS_IS_OK(status))
7389 goto done;
7390 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1)
7391 goto done;
7393 ret = true;
7394 done:
7395 cli_shutdown(cli);
7396 return ret;
7399 /* dump sam database via samsync rpc calls */
7400 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
7401 if (c->display_usage) {
7402 d_printf( "%s\n"
7403 "net rpc samdump\n"
7404 " %s\n",
7405 _("Usage:"),
7406 _("Dump remote SAM database"));
7407 return 0;
7410 return run_rpc_command(c, NULL, &ndr_table_netlogon,
7411 NET_FLAGS_ANONYMOUS,
7412 rpc_samdump_internals, argc, argv);
7415 /* syncronise sam database via samsync rpc calls */
7416 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
7418 struct functable func[] = {
7420 "ldif",
7421 rpc_vampire_ldif,
7422 NET_TRANSPORT_RPC,
7423 N_("Dump remote SAM database to ldif"),
7424 N_("net rpc vampire ldif\n"
7425 " Dump remote SAM database to LDIF file or "
7426 "stdout")
7429 "keytab",
7430 rpc_vampire_keytab,
7431 NET_TRANSPORT_RPC,
7432 N_("Dump remote SAM database to Kerberos Keytab"),
7433 N_("net rpc vampire keytab\n"
7434 " Dump remote SAM database to Kerberos keytab "
7435 "file")
7438 "passdb",
7439 rpc_vampire_passdb,
7440 NET_TRANSPORT_RPC,
7441 N_("Dump remote SAM database to passdb"),
7442 N_("net rpc vampire passdb\n"
7443 " Dump remote SAM database to passdb")
7446 {NULL, NULL, 0, NULL, NULL}
7449 if (argc == 0) {
7450 if (c->display_usage) {
7451 d_printf( "%s\n"
7452 "net rpc vampire\n"
7453 " %s\n",
7454 _("Usage:"),
7455 _("Vampire remote SAM database"));
7456 return 0;
7459 return rpc_vampire_passdb(c, argc, argv);
7462 return net_run_function(c, argc, argv, "net rpc vampire", func);
7466 * Migrate everything from a print server.
7468 * @param c A net_context structure.
7469 * @param argc Standard main() style argc.
7470 * @param argv Standard main() style argv. Initial components are already
7471 * stripped.
7473 * @return A shell status integer (0 for success).
7475 * The order is important !
7476 * To successfully add drivers the print queues have to exist !
7477 * Applying ACLs should be the last step, because you're easily locked out.
7480 static int rpc_printer_migrate_all(struct net_context *c, int argc,
7481 const char **argv)
7483 int ret;
7485 if (c->display_usage) {
7486 d_printf( "%s\n"
7487 "net rpc printer migrate all\n"
7488 " %s\n",
7489 _("Usage:"),
7490 _("Migrate everything from a print server"));
7491 return 0;
7494 if (!c->opt_host) {
7495 d_printf(_("no server to migrate\n"));
7496 return -1;
7499 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7500 rpc_printer_migrate_printers_internals, argc,
7501 argv);
7502 if (ret)
7503 return ret;
7505 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7506 rpc_printer_migrate_drivers_internals, argc,
7507 argv);
7508 if (ret)
7509 return ret;
7511 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7512 rpc_printer_migrate_forms_internals, argc, argv);
7513 if (ret)
7514 return ret;
7516 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7517 rpc_printer_migrate_settings_internals, argc,
7518 argv);
7519 if (ret)
7520 return ret;
7522 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7523 rpc_printer_migrate_security_internals, argc,
7524 argv);
7529 * Migrate print drivers from a print server.
7531 * @param c A net_context structure.
7532 * @param argc Standard main() style argc.
7533 * @param argv Standard main() style argv. Initial components are already
7534 * stripped.
7536 * @return A shell status integer (0 for success).
7538 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
7539 const char **argv)
7541 if (c->display_usage) {
7542 d_printf( "%s\n"
7543 "net rpc printer migrate drivers\n"
7544 " %s\n",
7545 _("Usage:"),
7546 _("Migrate print-drivers from a print-server"));
7547 return 0;
7550 if (!c->opt_host) {
7551 d_printf(_("no server to migrate\n"));
7552 return -1;
7555 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7556 rpc_printer_migrate_drivers_internals,
7557 argc, argv);
7561 * Migrate print-forms from a print-server.
7563 * @param c A net_context structure.
7564 * @param argc Standard main() style argc.
7565 * @param argv Standard main() style argv. Initial components are already
7566 * stripped.
7568 * @return A shell status integer (0 for success).
7570 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
7571 const char **argv)
7573 if (c->display_usage) {
7574 d_printf( "%s\n"
7575 "net rpc printer migrate forms\n"
7576 " %s\n",
7577 _("Usage:"),
7578 _("Migrate print-forms from a print-server"));
7579 return 0;
7582 if (!c->opt_host) {
7583 d_printf(_("no server to migrate\n"));
7584 return -1;
7587 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7588 rpc_printer_migrate_forms_internals,
7589 argc, argv);
7593 * Migrate printers from a print-server.
7595 * @param c A net_context structure.
7596 * @param argc Standard main() style argc.
7597 * @param argv Standard main() style argv. Initial components are already
7598 * stripped.
7600 * @return A shell status integer (0 for success).
7602 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
7603 const char **argv)
7605 if (c->display_usage) {
7606 d_printf( "%s\n"
7607 "net rpc printer migrate printers\n"
7608 " %s\n",
7609 _("Usage:"),
7610 _("Migrate printers from a print-server"));
7611 return 0;
7614 if (!c->opt_host) {
7615 d_printf(_("no server to migrate\n"));
7616 return -1;
7619 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7620 rpc_printer_migrate_printers_internals,
7621 argc, argv);
7625 * Migrate printer-ACLs from a print-server
7627 * @param c A net_context structure.
7628 * @param argc Standard main() style argc.
7629 * @param argv Standard main() style argv. Initial components are already
7630 * stripped.
7632 * @return A shell status integer (0 for success).
7634 static int rpc_printer_migrate_security(struct net_context *c, int argc,
7635 const char **argv)
7637 if (c->display_usage) {
7638 d_printf( "%s\n"
7639 "net rpc printer migrate security\n"
7640 " %s\n",
7641 _("Usage:"),
7642 _("Migrate printer-ACLs from a print-server"));
7643 return 0;
7646 if (!c->opt_host) {
7647 d_printf(_("no server to migrate\n"));
7648 return -1;
7651 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7652 rpc_printer_migrate_security_internals,
7653 argc, argv);
7657 * Migrate printer-settings from a print-server.
7659 * @param c A net_context structure.
7660 * @param argc Standard main() style argc.
7661 * @param argv Standard main() style argv. Initial components are already
7662 * stripped.
7664 * @return A shell status integer (0 for success).
7666 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
7667 const char **argv)
7669 if (c->display_usage) {
7670 d_printf( "%s\n"
7671 "net rpc printer migrate settings\n"
7672 " %s\n",
7673 _("Usage:"),
7674 _("Migrate printer-settings from a "
7675 "print-server"));
7676 return 0;
7679 if (!c->opt_host) {
7680 d_printf(_("no server to migrate\n"));
7681 return -1;
7684 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7685 rpc_printer_migrate_settings_internals,
7686 argc, argv);
7690 * 'net rpc printer' entrypoint.
7692 * @param c A net_context structure.
7693 * @param argc Standard main() style argc.
7694 * @param argv Standard main() style argv. Initial components are already
7695 * stripped.
7698 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
7701 /* ouch: when addriver and setdriver are called from within
7702 rpc_printer_migrate_drivers_internals, the printer-queue already
7703 *has* to exist */
7705 struct functable func[] = {
7707 "all",
7708 rpc_printer_migrate_all,
7709 NET_TRANSPORT_RPC,
7710 N_("Migrate all from remote to local print server"),
7711 N_("net rpc printer migrate all\n"
7712 " Migrate all from remote to local print server")
7715 "drivers",
7716 rpc_printer_migrate_drivers,
7717 NET_TRANSPORT_RPC,
7718 N_("Migrate drivers to local server"),
7719 N_("net rpc printer migrate drivers\n"
7720 " Migrate drivers to local server")
7723 "forms",
7724 rpc_printer_migrate_forms,
7725 NET_TRANSPORT_RPC,
7726 N_("Migrate froms to local server"),
7727 N_("net rpc printer migrate forms\n"
7728 " Migrate froms to local server")
7731 "printers",
7732 rpc_printer_migrate_printers,
7733 NET_TRANSPORT_RPC,
7734 N_("Migrate printers to local server"),
7735 N_("net rpc printer migrate printers\n"
7736 " Migrate printers to local server")
7739 "security",
7740 rpc_printer_migrate_security,
7741 NET_TRANSPORT_RPC,
7742 N_("Mirgate printer ACLs to local server"),
7743 N_("net rpc printer migrate security\n"
7744 " Mirgate printer ACLs to local server")
7747 "settings",
7748 rpc_printer_migrate_settings,
7749 NET_TRANSPORT_RPC,
7750 N_("Migrate printer settings to local server"),
7751 N_("net rpc printer migrate settings\n"
7752 " Migrate printer settings to local server")
7754 {NULL, NULL, 0, NULL, NULL}
7757 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7762 * List printers on a remote RPC server.
7764 * @param c A net_context structure.
7765 * @param argc Standard main() style argc.
7766 * @param argv Standard main() style argv. Initial components are already
7767 * stripped.
7769 * @return A shell status integer (0 for success).
7771 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7773 if (c->display_usage) {
7774 d_printf( "%s\n"
7775 "net rpc printer list\n"
7776 " %s\n",
7777 _("Usage:"),
7778 _("List printers on a remote RPC server"));
7779 return 0;
7782 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7783 rpc_printer_list_internals,
7784 argc, argv);
7788 * List printer-drivers on a remote RPC server.
7790 * @param c A net_context structure.
7791 * @param argc Standard main() style argc.
7792 * @param argv Standard main() style argv. Initial components are already
7793 * stripped.
7795 * @return A shell status integer (0 for success).
7797 static int rpc_printer_driver_list(struct net_context *c, int argc,
7798 const char **argv)
7800 if (c->display_usage) {
7801 d_printf( "%s\n"
7802 "net rpc printer driver\n"
7803 " %s\n",
7804 _("Usage:"),
7805 _("List printer-drivers on a remote RPC server"));
7806 return 0;
7809 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7810 rpc_printer_driver_list_internals,
7811 argc, argv);
7815 * Publish printer in ADS via MSRPC.
7817 * @param c A net_context structure.
7818 * @param argc Standard main() style argc.
7819 * @param argv Standard main() style argv. Initial components are already
7820 * stripped.
7822 * @return A shell status integer (0 for success).
7824 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7825 const char **argv)
7827 if (c->display_usage) {
7828 d_printf( "%s\n"
7829 "net rpc printer publish publish\n"
7830 " %s\n",
7831 _("Usage:"),
7832 _("Publish printer in ADS via MSRPC"));
7833 return 0;
7836 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7837 rpc_printer_publish_publish_internals,
7838 argc, argv);
7842 * Update printer in ADS via MSRPC.
7844 * @param c A net_context structure.
7845 * @param argc Standard main() style argc.
7846 * @param argv Standard main() style argv. Initial components are already
7847 * stripped.
7849 * @return A shell status integer (0 for success).
7851 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7853 if (c->display_usage) {
7854 d_printf( "%s\n"
7855 "net rpc printer publish update\n"
7856 " %s\n",
7857 _("Usage:"),
7858 _("Update printer in ADS via MSRPC"));
7859 return 0;
7862 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7863 rpc_printer_publish_update_internals,
7864 argc, argv);
7868 * UnPublish printer in ADS via MSRPC.
7870 * @param c A net_context structure.
7871 * @param argc Standard main() style argc.
7872 * @param argv Standard main() style argv. Initial components are already
7873 * stripped.
7875 * @return A shell status integer (0 for success).
7877 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7878 const char **argv)
7880 if (c->display_usage) {
7881 d_printf( "%s\n"
7882 "net rpc printer publish unpublish\n"
7883 " %s\n",
7884 _("Usage:\n"),
7885 _("UnPublish printer in ADS via MSRPC"));
7886 return 0;
7889 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7890 rpc_printer_publish_unpublish_internals,
7891 argc, argv);
7895 * List published printers via MSRPC.
7897 * @param c A net_context structure.
7898 * @param argc Standard main() style argc.
7899 * @param argv Standard main() style argv. Initial components are already
7900 * stripped.
7902 * @return A shell status integer (0 for success).
7904 static int rpc_printer_publish_list(struct net_context *c, int argc,
7905 const char **argv)
7907 if (c->display_usage) {
7908 d_printf( "%s\n"
7909 "net rpc printer publish list\n"
7910 " %s\n",
7911 _("Usage:"),
7912 _("List published printers via MSRPC"));
7913 return 0;
7916 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7917 rpc_printer_publish_list_internals,
7918 argc, argv);
7923 * Publish printer in ADS.
7925 * @param c A net_context structure.
7926 * @param argc Standard main() style argc.
7927 * @param argv Standard main() style argv. Initial components are already
7928 * stripped.
7930 * @return A shell status integer (0 for success).
7932 static int rpc_printer_publish(struct net_context *c, int argc,
7933 const char **argv)
7936 struct functable func[] = {
7938 "publish",
7939 rpc_printer_publish_publish,
7940 NET_TRANSPORT_RPC,
7941 N_("Publish printer in AD"),
7942 N_("net rpc printer publish publish\n"
7943 " Publish printer in AD")
7946 "update",
7947 rpc_printer_publish_update,
7948 NET_TRANSPORT_RPC,
7949 N_("Update printer in AD"),
7950 N_("net rpc printer publish update\n"
7951 " Update printer in AD")
7954 "unpublish",
7955 rpc_printer_publish_unpublish,
7956 NET_TRANSPORT_RPC,
7957 N_("Unpublish printer"),
7958 N_("net rpc printer publish unpublish\n"
7959 " Unpublish printer")
7962 "list",
7963 rpc_printer_publish_list,
7964 NET_TRANSPORT_RPC,
7965 N_("List published printers"),
7966 N_("net rpc printer publish list\n"
7967 " List published printers")
7969 {NULL, NULL, 0, NULL, NULL}
7972 if (argc == 0) {
7973 if (c->display_usage) {
7974 d_printf(_("Usage:\n"));
7975 d_printf(_("net rpc printer publish\n"
7976 " List published printers\n"
7977 " Alias of net rpc printer publish "
7978 "list\n"));
7979 net_display_usage_from_functable(func);
7980 return 0;
7982 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7983 rpc_printer_publish_list_internals,
7984 argc, argv);
7987 return net_run_function(c, argc, argv, "net rpc printer publish",func);
7993 * Display rpc printer help page.
7995 * @param c A net_context structure.
7996 * @param argc Standard main() style argc.
7997 * @param argv Standard main() style argv. Initial components are already
7998 * stripped.
8000 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
8002 d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
8003 "\tlists all printers on print-server\n\n"));
8004 d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
8005 "\tlists all printer-drivers on print-server\n\n"));
8006 d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
8007 "\tpublishes printer settings in Active Directory\n"
8008 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
8009 d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
8010 "\n\tmigrates printers from remote to local server\n\n"));
8011 d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
8012 "\n\tmigrates printer-settings from remote to local server\n\n"));
8013 d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
8014 "\n\tmigrates printer-drivers from remote to local server\n\n"));
8015 d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
8016 "\n\tmigrates printer-forms from remote to local server\n\n"));
8017 d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
8018 "\n\tmigrates printer-ACLs from remote to local server\n\n"));
8019 d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
8020 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
8021 "\tremote to local print-server\n\n"));
8022 net_common_methods_usage(c, argc, argv);
8023 net_common_flags_usage(c, argc, argv);
8024 d_printf(_(
8025 "\t-v or --verbose\t\t\tgive verbose output\n"
8026 "\t --destination\t\tmigration target server (default: localhost)\n"));
8028 return -1;
8032 * 'net rpc printer' entrypoint.
8034 * @param c A net_context structure.
8035 * @param argc Standard main() style argc.
8036 * @param argv Standard main() style argv. Initial components are already
8037 * stripped.
8039 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
8041 struct functable func[] = {
8043 "list",
8044 rpc_printer_list,
8045 NET_TRANSPORT_RPC,
8046 N_("List all printers on print server"),
8047 N_("net rpc printer list\n"
8048 " List all printers on print server")
8051 "migrate",
8052 rpc_printer_migrate,
8053 NET_TRANSPORT_RPC,
8054 N_("Migrate printer to local server"),
8055 N_("net rpc printer migrate\n"
8056 " Migrate printer to local server")
8059 "driver",
8060 rpc_printer_driver_list,
8061 NET_TRANSPORT_RPC,
8062 N_("List printer drivers"),
8063 N_("net rpc printer driver\n"
8064 " List printer drivers")
8067 "publish",
8068 rpc_printer_publish,
8069 NET_TRANSPORT_RPC,
8070 N_("Publish printer in AD"),
8071 N_("net rpc printer publish\n"
8072 " Publish printer in AD")
8074 {NULL, NULL, 0, NULL, NULL}
8077 if (argc == 0) {
8078 if (c->display_usage) {
8079 d_printf(_("Usage:\n"));
8080 d_printf(_("net rpc printer\n"
8081 " List printers\n"));
8082 net_display_usage_from_functable(func);
8083 return 0;
8085 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
8086 rpc_printer_list_internals,
8087 argc, argv);
8090 return net_run_function(c, argc, argv, "net rpc printer", func);
8094 * 'net rpc' entrypoint.
8096 * @param c A net_context structure.
8097 * @param argc Standard main() style argc.
8098 * @param argv Standard main() style argv. Initial components are already
8099 * stripped.
8102 int net_rpc(struct net_context *c, int argc, const char **argv)
8104 NET_API_STATUS status;
8106 struct functable func[] = {
8108 "audit",
8109 net_rpc_audit,
8110 NET_TRANSPORT_RPC,
8111 N_("Modify global audit settings"),
8112 N_("net rpc audit\n"
8113 " Modify global audit settings")
8116 "info",
8117 net_rpc_info,
8118 NET_TRANSPORT_RPC,
8119 N_("Show basic info about a domain"),
8120 N_("net rpc info\n"
8121 " Show basic info about a domain")
8124 "join",
8125 net_rpc_join,
8126 NET_TRANSPORT_RPC,
8127 N_("Join a domain"),
8128 N_("net rpc join\n"
8129 " Join a domain")
8132 "oldjoin",
8133 net_rpc_oldjoin,
8134 NET_TRANSPORT_RPC,
8135 N_("Join a domain created in server manager"),
8136 N_("net rpc oldjoin\n"
8137 " Join a domain created in server manager")
8140 "testjoin",
8141 net_rpc_testjoin,
8142 NET_TRANSPORT_RPC,
8143 N_("Test that a join is valid"),
8144 N_("net rpc testjoin\n"
8145 " Test that a join is valid")
8148 "user",
8149 net_rpc_user,
8150 NET_TRANSPORT_RPC,
8151 N_("List/modify users"),
8152 N_("net rpc user\n"
8153 " List/modify users")
8156 "password",
8157 rpc_user_password,
8158 NET_TRANSPORT_RPC,
8159 N_("Change a user password"),
8160 N_("net rpc password\n"
8161 " Change a user password\n"
8162 " Alias for net rpc user password")
8165 "group",
8166 net_rpc_group,
8167 NET_TRANSPORT_RPC,
8168 N_("List/modify groups"),
8169 N_("net rpc group\n"
8170 " List/modify groups")
8173 "share",
8174 net_rpc_share,
8175 NET_TRANSPORT_RPC,
8176 N_("List/modify shares"),
8177 N_("net rpc share\n"
8178 " List/modify shares")
8181 "file",
8182 net_rpc_file,
8183 NET_TRANSPORT_RPC,
8184 N_("List open files"),
8185 N_("net rpc file\n"
8186 " List open files")
8189 "printer",
8190 net_rpc_printer,
8191 NET_TRANSPORT_RPC,
8192 N_("List/modify printers"),
8193 N_("net rpc printer\n"
8194 " List/modify printers")
8197 "changetrustpw",
8198 net_rpc_changetrustpw,
8199 NET_TRANSPORT_RPC,
8200 N_("Change trust account password"),
8201 N_("net rpc changetrustpw\n"
8202 " Change trust account password")
8205 "trustdom",
8206 rpc_trustdom,
8207 NET_TRANSPORT_RPC,
8208 N_("Modify domain trusts"),
8209 N_("net rpc trustdom\n"
8210 " Modify domain trusts")
8213 "abortshutdown",
8214 rpc_shutdown_abort,
8215 NET_TRANSPORT_RPC,
8216 N_("Abort a remote shutdown"),
8217 N_("net rpc abortshutdown\n"
8218 " Abort a remote shutdown")
8221 "shutdown",
8222 rpc_shutdown,
8223 NET_TRANSPORT_RPC,
8224 N_("Shutdown a remote server"),
8225 N_("net rpc shutdown\n"
8226 " Shutdown a remote server")
8229 "samdump",
8230 rpc_samdump,
8231 NET_TRANSPORT_RPC,
8232 N_("Dump SAM data of remote NT PDC"),
8233 N_("net rpc samdump\n"
8234 " Dump SAM data of remote NT PDC")
8237 "vampire",
8238 rpc_vampire,
8239 NET_TRANSPORT_RPC,
8240 N_("Sync a remote NT PDC's data into local passdb"),
8241 N_("net rpc vampire\n"
8242 " Sync a remote NT PDC's data into local passdb")
8245 "getsid",
8246 net_rpc_getsid,
8247 NET_TRANSPORT_RPC,
8248 N_("Fetch the domain sid into local secrets.tdb"),
8249 N_("net rpc getsid\n"
8250 " Fetch the domain sid into local secrets.tdb")
8253 "rights",
8254 net_rpc_rights,
8255 NET_TRANSPORT_RPC,
8256 N_("Manage privileges assigned to SID"),
8257 N_("net rpc rights\n"
8258 " Manage privileges assigned to SID")
8261 "service",
8262 net_rpc_service,
8263 NET_TRANSPORT_RPC,
8264 N_("Start/stop/query remote services"),
8265 N_("net rpc service\n"
8266 " Start/stop/query remote services")
8269 "registry",
8270 net_rpc_registry,
8271 NET_TRANSPORT_RPC,
8272 N_("Manage registry hives"),
8273 N_("net rpc registry\n"
8274 " Manage registry hives")
8277 "shell",
8278 net_rpc_shell,
8279 NET_TRANSPORT_RPC,
8280 N_("Open interactive shell on remote server"),
8281 N_("net rpc shell\n"
8282 " Open interactive shell on remote server")
8285 "trust",
8286 net_rpc_trust,
8287 NET_TRANSPORT_RPC,
8288 N_("Manage trusts"),
8289 N_("net rpc trust\n"
8290 " Manage trusts")
8293 "conf",
8294 net_rpc_conf,
8295 NET_TRANSPORT_RPC,
8296 N_("Configure a remote samba server"),
8297 N_("net rpc conf\n"
8298 " Configure a remote samba server")
8300 {NULL, NULL, 0, NULL, NULL}
8303 status = libnetapi_net_init(&c->netapi_ctx);
8304 if (status != 0) {
8305 return -1;
8307 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
8308 libnetapi_set_password(c->netapi_ctx, c->opt_password);
8309 if (c->opt_kerberos) {
8310 libnetapi_set_use_kerberos(c->netapi_ctx);
8312 if (c->opt_ccache) {
8313 libnetapi_set_use_ccache(c->netapi_ctx);
8316 return net_run_function(c, argc, argv, "net rpc", func);