torture3: Add some brlock entries in cleanup2
[Samba.git] / source3 / utils / net_rpc.c
blobb5c4d0b2e93bcb0dc19d8d83d47c996e751d13bb
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,
5108 FILE_OPEN, 0x0, 0x0, &fnum, NULL))) {
5109 cli_query_secdesc(cli, fnum, mem_ctx, &root_sd);
5112 for (i=0; i<num_tokens; i++) {
5113 uint32 acc_granted;
5115 if (share_sd != NULL) {
5116 status = se_access_check(share_sd, &tokens[i].token,
5117 1, &acc_granted);
5119 if (!NT_STATUS_IS_OK(status)) {
5120 DEBUG(1, ("Could not check share_sd for "
5121 "user %s\n",
5122 tokens[i].name));
5123 continue;
5127 if (root_sd == NULL) {
5128 d_printf(" %s\n", tokens[i].name);
5129 continue;
5132 status = se_access_check(root_sd, &tokens[i].token,
5133 1, &acc_granted);
5134 if (!NT_STATUS_IS_OK(status)) {
5135 DEBUG(1, ("Could not check root_sd for user %s\n",
5136 tokens[i].name));
5137 continue;
5139 d_printf(" %s\n", tokens[i].name);
5142 if (fnum != (uint16_t)-1)
5143 cli_close(cli, fnum);
5144 cli_tdis(cli);
5145 cli_state_set_tid(cli, cnum);
5147 return;
5151 * List shares on a remote RPC server, including the security descriptors.
5153 * All parameters are provided by the run_rpc_command function, except for
5154 * argc, argv which are passed through.
5156 * @param domain_sid The domain sid acquired from the remote server.
5157 * @param cli A cli_state connected to the server.
5158 * @param mem_ctx Talloc context, destroyed on completion of the function.
5159 * @param argc Standard main() style argc.
5160 * @param argv Standard main() style argv. Initial components are already
5161 * stripped.
5163 * @return Normal NTSTATUS return.
5166 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
5167 const struct dom_sid *domain_sid,
5168 const char *domain_name,
5169 struct cli_state *cli,
5170 struct rpc_pipe_client *pipe_hnd,
5171 TALLOC_CTX *mem_ctx,
5172 int argc,
5173 const char **argv)
5175 bool r;
5176 FILE *f;
5177 NTSTATUS nt_status = NT_STATUS_OK;
5178 uint32_t total_entries = 0;
5179 uint32_t resume_handle = 0;
5180 uint32_t preferred_len = 0xffffffff;
5181 uint32_t i;
5182 struct dcerpc_binding_handle *b = NULL;
5183 struct srvsvc_NetShareInfoCtr info_ctr;
5184 struct srvsvc_NetShareCtr1 ctr1;
5185 WERROR result;
5187 struct user_token *tokens = NULL;
5188 int num_tokens = 0;
5190 if (argc == 0) {
5191 f = stdin;
5192 } else {
5193 f = fopen(argv[0], "r");
5196 if (f == NULL) {
5197 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
5198 return NT_STATUS_UNSUCCESSFUL;
5201 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
5203 if (f != stdin)
5204 fclose(f);
5206 if (!r) {
5207 DEBUG(0, ("Could not read users from file\n"));
5208 return NT_STATUS_UNSUCCESSFUL;
5211 for (i=0; i<num_tokens; i++)
5212 collect_alias_memberships(&tokens[i].token);
5214 ZERO_STRUCT(info_ctr);
5215 ZERO_STRUCT(ctr1);
5217 info_ctr.level = 1;
5218 info_ctr.ctr.ctr1 = &ctr1;
5220 b = pipe_hnd->binding_handle;
5222 /* Issue the NetShareEnum RPC call and retrieve the response */
5223 nt_status = dcerpc_srvsvc_NetShareEnumAll(b,
5224 talloc_tos(),
5225 pipe_hnd->desthost,
5226 &info_ctr,
5227 preferred_len,
5228 &total_entries,
5229 &resume_handle,
5230 &result);
5232 /* Was it successful? */
5233 if (!NT_STATUS_IS_OK(nt_status)) {
5234 /* Nope. Go clean up. */
5235 goto done;
5238 if (!W_ERROR_IS_OK(result)) {
5239 /* Nope. Go clean up. */
5240 nt_status = werror_to_ntstatus(result);
5241 goto done;
5244 if (total_entries == 0) {
5245 goto done;
5248 /* For each returned entry... */
5249 for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {
5250 const char *netname = info_ctr.ctr.ctr1->array[i].name;
5252 if (info_ctr.ctr.ctr1->array[i].type != STYPE_DISKTREE) {
5253 continue;
5256 d_printf("%s\n", netname);
5258 show_userlist(pipe_hnd, cli, mem_ctx, netname,
5259 num_tokens, tokens);
5261 done:
5262 for (i=0; i<num_tokens; i++) {
5263 free_user_token(&tokens[i].token);
5265 SAFE_FREE(tokens);
5267 return nt_status;
5270 static int rpc_share_allowedusers(struct net_context *c, int argc,
5271 const char **argv)
5273 int result;
5275 if (c->display_usage) {
5276 d_printf( "%s\n"
5277 "net rpc share allowedusers\n"
5278 " %s\n",
5279 _("Usage:"),
5280 _("List allowed users"));
5281 return 0;
5284 result = run_rpc_command(c, NULL, &ndr_table_samr, 0,
5285 rpc_aliaslist_internals,
5286 argc, argv);
5287 if (result != 0)
5288 return result;
5290 result = run_rpc_command(c, NULL, &ndr_table_lsarpc, 0,
5291 rpc_aliaslist_dump,
5292 argc, argv);
5293 if (result != 0)
5294 return result;
5296 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
5297 rpc_share_allowedusers_internals,
5298 argc, argv);
5301 int net_usersidlist(struct net_context *c, int argc, const char **argv)
5303 int num_tokens = 0;
5304 struct user_token *tokens = NULL;
5305 int i;
5307 if (argc != 0) {
5308 net_usersidlist_usage(c, argc, argv);
5309 return 0;
5312 if (!get_user_tokens(c, &num_tokens, &tokens)) {
5313 DEBUG(0, ("Could not get the user/sid list\n"));
5314 return -1;
5317 for (i=0; i<num_tokens; i++) {
5318 dump_user_token(&tokens[i]);
5319 free_user_token(&tokens[i].token);
5322 SAFE_FREE(tokens);
5323 return 0;
5326 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
5328 d_printf(_("net usersidlist\n"
5329 "\tprints out a list of all users the running winbind knows\n"
5330 "\tabout, together with all their SIDs. This is used as\n"
5331 "\tinput to the 'net rpc share allowedusers' command.\n\n"));
5333 net_common_flags_usage(c, argc, argv);
5334 return -1;
5338 * 'net rpc share' entrypoint.
5339 * @param argc Standard main() style argc.
5340 * @param argv Standard main() style argv. Initial components are already
5341 * stripped.
5344 int net_rpc_share(struct net_context *c, int argc, const char **argv)
5346 NET_API_STATUS status;
5348 struct functable func[] = {
5350 "add",
5351 rpc_share_add,
5352 NET_TRANSPORT_RPC,
5353 N_("Add share"),
5354 N_("net rpc share add\n"
5355 " Add share")
5358 "delete",
5359 rpc_share_delete,
5360 NET_TRANSPORT_RPC,
5361 N_("Remove share"),
5362 N_("net rpc share delete\n"
5363 " Remove share")
5366 "allowedusers",
5367 rpc_share_allowedusers,
5368 NET_TRANSPORT_RPC,
5369 N_("Modify allowed users"),
5370 N_("net rpc share allowedusers\n"
5371 " Modify allowed users")
5374 "migrate",
5375 rpc_share_migrate,
5376 NET_TRANSPORT_RPC,
5377 N_("Migrate share to local server"),
5378 N_("net rpc share migrate\n"
5379 " Migrate share to local server")
5382 "list",
5383 rpc_share_list,
5384 NET_TRANSPORT_RPC,
5385 N_("List shares"),
5386 N_("net rpc share list\n"
5387 " List shares")
5389 {NULL, NULL, 0, NULL, NULL}
5392 status = libnetapi_net_init(&c->netapi_ctx);
5393 if (status != 0) {
5394 return -1;
5396 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5397 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5398 if (c->opt_kerberos) {
5399 libnetapi_set_use_kerberos(c->netapi_ctx);
5402 if (argc == 0) {
5403 if (c->display_usage) {
5404 d_printf("%s\n%s",
5405 _("Usage:"),
5406 _("net rpc share\n"
5407 " List shares\n"
5408 " Alias for net rpc share list\n"));
5409 net_display_usage_from_functable(func);
5410 return 0;
5413 return rpc_share_list(c, argc, argv);
5416 return net_run_function(c, argc, argv, "net rpc share", func);
5419 static NTSTATUS rpc_sh_share_list(struct net_context *c,
5420 TALLOC_CTX *mem_ctx,
5421 struct rpc_sh_ctx *ctx,
5422 struct rpc_pipe_client *pipe_hnd,
5423 int argc, const char **argv)
5426 return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
5429 static NTSTATUS rpc_sh_share_add(struct net_context *c,
5430 TALLOC_CTX *mem_ctx,
5431 struct rpc_sh_ctx *ctx,
5432 struct rpc_pipe_client *pipe_hnd,
5433 int argc, const char **argv)
5435 NET_API_STATUS status;
5436 uint32_t parm_err = 0;
5437 struct SHARE_INFO_2 i2;
5439 if ((argc < 2) || (argc > 3)) {
5440 d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
5441 ctx->whoami);
5442 return NT_STATUS_INVALID_PARAMETER;
5445 i2.shi2_netname = argv[0];
5446 i2.shi2_type = STYPE_DISKTREE;
5447 i2.shi2_remark = (argc == 3) ? argv[2] : "";
5448 i2.shi2_permissions = 0;
5449 i2.shi2_max_uses = 0;
5450 i2.shi2_current_uses = 0;
5451 i2.shi2_path = argv[1];
5452 i2.shi2_passwd = NULL;
5454 status = NetShareAdd(pipe_hnd->desthost,
5456 (uint8_t *)&i2,
5457 &parm_err);
5459 return werror_to_ntstatus(W_ERROR(status));
5462 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
5463 TALLOC_CTX *mem_ctx,
5464 struct rpc_sh_ctx *ctx,
5465 struct rpc_pipe_client *pipe_hnd,
5466 int argc, const char **argv)
5468 if (argc != 1) {
5469 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5470 return NT_STATUS_INVALID_PARAMETER;
5473 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
5476 static NTSTATUS rpc_sh_share_info(struct net_context *c,
5477 TALLOC_CTX *mem_ctx,
5478 struct rpc_sh_ctx *ctx,
5479 struct rpc_pipe_client *pipe_hnd,
5480 int argc, const char **argv)
5482 union srvsvc_NetShareInfo info;
5483 WERROR result;
5484 NTSTATUS status;
5485 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5487 if (argc != 1) {
5488 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5489 return NT_STATUS_INVALID_PARAMETER;
5492 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5493 pipe_hnd->desthost,
5494 argv[0],
5496 &info,
5497 &result);
5498 if (!NT_STATUS_IS_OK(status)) {
5499 result = ntstatus_to_werror(status);
5500 goto done;
5502 if (!W_ERROR_IS_OK(result)) {
5503 goto done;
5506 d_printf(_("Name: %s\n"), info.info2->name);
5507 d_printf(_("Comment: %s\n"), info.info2->comment);
5508 d_printf(_("Path: %s\n"), info.info2->path);
5509 d_printf(_("Password: %s\n"), info.info2->password);
5511 done:
5512 return werror_to_ntstatus(result);
5515 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
5516 struct rpc_sh_ctx *ctx)
5518 static struct rpc_sh_cmd cmds[] = {
5520 { "list", NULL, &ndr_table_srvsvc, rpc_sh_share_list,
5521 N_("List available shares") },
5523 { "add", NULL, &ndr_table_srvsvc, rpc_sh_share_add,
5524 N_("Add a share") },
5526 { "delete", NULL, &ndr_table_srvsvc, rpc_sh_share_delete,
5527 N_("Delete a share") },
5529 { "info", NULL, &ndr_table_srvsvc, rpc_sh_share_info,
5530 N_("Get information about a share") },
5532 { NULL, NULL, 0, NULL, NULL }
5535 return cmds;
5538 /****************************************************************************/
5540 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
5542 return net_file_usage(c, argc, argv);
5546 * Close a file on a remote RPC server.
5548 * @param argc Standard main() style argc.
5549 * @param argv Standard main() style argv. Initial components are already
5550 * stripped.
5552 * @return A shell status integer (0 for success).
5554 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5556 if (argc < 1 || c->display_usage) {
5557 return rpc_file_usage(c, argc, argv);
5560 return NetFileClose(c->opt_host, atoi(argv[0]));
5564 * Formatted print of open file info
5566 * @param r struct FILE_INFO_3 contents
5569 static void display_file_info_3(struct FILE_INFO_3 *r)
5571 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5572 r->fi3_id, r->fi3_username, r->fi3_permissions,
5573 r->fi3_num_locks, r->fi3_pathname);
5577 * List files for a user on a remote RPC server.
5579 * @param argc Standard main() style argc.
5580 * @param argv Standard main() style argv. Initial components are already
5581 * stripped.
5583 * @return A shell status integer (0 for success)..
5586 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5588 NET_API_STATUS status;
5589 uint32 preferred_len = 0xffffffff, i;
5590 char *username=NULL;
5591 uint32_t total_entries = 0;
5592 uint32_t entries_read = 0;
5593 uint32_t resume_handle = 0;
5594 struct FILE_INFO_3 *i3 = NULL;
5596 if (c->display_usage) {
5597 return rpc_file_usage(c, argc, argv);
5600 /* if argc > 0, must be user command */
5601 if (argc > 0) {
5602 username = smb_xstrdup(argv[0]);
5605 status = NetFileEnum(c->opt_host,
5606 NULL,
5607 username,
5609 (uint8_t **)(void *)&i3,
5610 preferred_len,
5611 &entries_read,
5612 &total_entries,
5613 &resume_handle);
5615 if (status != 0) {
5616 goto done;
5619 /* Display results */
5621 d_printf(_(
5622 "\nEnumerating open files on remote server:\n\n"
5623 "\nFileId Opened by Perms Locks Path"
5624 "\n------ --------- ----- ----- ---- \n"));
5625 for (i = 0; i < entries_read; i++) {
5626 display_file_info_3(&i3[i]);
5628 done:
5629 SAFE_FREE(username);
5630 return status;
5634 * 'net rpc file' entrypoint.
5635 * @param argc Standard main() style argc.
5636 * @param argv Standard main() style argv. Initial components are already
5637 * stripped.
5640 int net_rpc_file(struct net_context *c, int argc, const char **argv)
5642 NET_API_STATUS status;
5644 struct functable func[] = {
5646 "close",
5647 rpc_file_close,
5648 NET_TRANSPORT_RPC,
5649 N_("Close opened file"),
5650 N_("net rpc file close\n"
5651 " Close opened file")
5654 "user",
5655 rpc_file_user,
5656 NET_TRANSPORT_RPC,
5657 N_("List files opened by user"),
5658 N_("net rpc file user\n"
5659 " List files opened by user")
5661 #if 0
5663 "info",
5664 rpc_file_info,
5665 NET_TRANSPORT_RPC,
5666 N_("Display information about opened file"),
5667 N_("net rpc file info\n"
5668 " Display information about opened file")
5670 #endif
5671 {NULL, NULL, 0, NULL, NULL}
5674 status = libnetapi_net_init(&c->netapi_ctx);
5675 if (status != 0) {
5676 return -1;
5678 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5679 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5680 if (c->opt_kerberos) {
5681 libnetapi_set_use_kerberos(c->netapi_ctx);
5684 if (argc == 0) {
5685 if (c->display_usage) {
5686 d_printf(_("Usage:\n"));
5687 d_printf(_("net rpc file\n"
5688 " List opened files\n"));
5689 net_display_usage_from_functable(func);
5690 return 0;
5693 return rpc_file_user(c, argc, argv);
5696 return net_run_function(c, argc, argv, "net rpc file", func);
5700 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5702 * All parameters are provided by the run_rpc_command function, except for
5703 * argc, argv which are passed through.
5705 * @param c A net_context structure.
5706 * @param domain_sid The domain sid acquired from the remote server.
5707 * @param cli A cli_state connected to the server.
5708 * @param mem_ctx Talloc context, destroyed on completion of the function.
5709 * @param argc Standard main() style argc.
5710 * @param argv Standard main() style argv. Initial components are already
5711 * stripped.
5713 * @return Normal NTSTATUS return.
5716 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5717 const struct dom_sid *domain_sid,
5718 const char *domain_name,
5719 struct cli_state *cli,
5720 struct rpc_pipe_client *pipe_hnd,
5721 TALLOC_CTX *mem_ctx,
5722 int argc,
5723 const char **argv)
5725 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5726 WERROR result;
5727 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5729 status = dcerpc_initshutdown_Abort(b, mem_ctx, NULL, &result);
5730 if (!NT_STATUS_IS_OK(status)) {
5731 return status;
5733 if (W_ERROR_IS_OK(result)) {
5734 d_printf(_("\nShutdown successfully aborted\n"));
5735 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5736 } else
5737 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5739 return werror_to_ntstatus(result);
5743 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5745 * All parameters are provided by the run_rpc_command function, except for
5746 * argc, argv which are passed through.
5748 * @param c A net_context structure.
5749 * @param domain_sid The domain sid acquired from the remote server.
5750 * @param cli A cli_state connected to the server.
5751 * @param mem_ctx Talloc context, destroyed on completion of the function.
5752 * @param argc Standard main() style argc.
5753 * @param argv Standard main() style argv. Initial components are already
5754 * stripped.
5756 * @return Normal NTSTATUS return.
5759 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5760 const struct dom_sid *domain_sid,
5761 const char *domain_name,
5762 struct cli_state *cli,
5763 struct rpc_pipe_client *pipe_hnd,
5764 TALLOC_CTX *mem_ctx,
5765 int argc,
5766 const char **argv)
5768 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5769 WERROR werr;
5770 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5772 result = dcerpc_winreg_AbortSystemShutdown(b, mem_ctx, NULL, &werr);
5774 if (!NT_STATUS_IS_OK(result)) {
5775 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5776 return result;
5778 if (W_ERROR_IS_OK(werr)) {
5779 d_printf(_("\nShutdown successfully aborted\n"));
5780 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5781 } else
5782 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5784 return werror_to_ntstatus(werr);
5788 * ABORT the shutdown of a remote RPC server.
5790 * @param argc Standard main() style argc.
5791 * @param argv Standard main() style argv. Initial components are already
5792 * stripped.
5794 * @return A shell status integer (0 for success).
5797 static int rpc_shutdown_abort(struct net_context *c, int argc,
5798 const char **argv)
5800 int rc = -1;
5802 if (c->display_usage) {
5803 d_printf( "%s\n"
5804 "net rpc abortshutdown\n"
5805 " %s\n",
5806 _("Usage:"),
5807 _("Abort a scheduled shutdown"));
5808 return 0;
5811 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5812 rpc_shutdown_abort_internals, argc, argv);
5814 if (rc == 0)
5815 return rc;
5817 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5819 return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5820 rpc_reg_shutdown_abort_internals,
5821 argc, argv);
5825 * Shut down a remote RPC Server via initshutdown pipe.
5827 * All parameters are provided by the run_rpc_command function, except for
5828 * argc, argv which are passed through.
5830 * @param c A net_context structure.
5831 * @param domain_sid The domain sid acquired from the remote server.
5832 * @param cli A cli_state connected to the server.
5833 * @param mem_ctx Talloc context, destroyed on completion of the function.
5834 * @param argc Standard main() style argc.
5835 * @param argv Standard main() style argv. Initial components are already
5836 * stripped.
5838 * @return Normal NTSTATUS return.
5841 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5842 const struct dom_sid *domain_sid,
5843 const char *domain_name,
5844 struct cli_state *cli,
5845 struct rpc_pipe_client *pipe_hnd,
5846 TALLOC_CTX *mem_ctx,
5847 int argc,
5848 const char **argv)
5850 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5851 WERROR result;
5852 const char *msg = N_("This machine will be shutdown shortly");
5853 uint32 timeout = 20;
5854 struct lsa_StringLarge msg_string;
5855 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5857 if (c->opt_comment) {
5858 msg = c->opt_comment;
5860 if (c->opt_timeout) {
5861 timeout = c->opt_timeout;
5864 msg_string.string = msg;
5866 /* create an entry */
5867 status = dcerpc_initshutdown_Init(b, mem_ctx, NULL,
5868 &msg_string, timeout, c->opt_force, c->opt_reboot,
5869 &result);
5870 if (!NT_STATUS_IS_OK(status)) {
5871 return status;
5873 if (W_ERROR_IS_OK(result)) {
5874 d_printf(_("\nShutdown of remote machine succeeded\n"));
5875 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5876 } else {
5877 DEBUG(1,("Shutdown of remote machine failed!\n"));
5879 return werror_to_ntstatus(result);
5883 * Shut down a remote RPC Server via winreg pipe.
5885 * All parameters are provided by the run_rpc_command function, except for
5886 * argc, argv which are passed through.
5888 * @param c A net_context structure.
5889 * @param domain_sid The domain sid acquired from the remote server.
5890 * @param cli A cli_state connected to the server.
5891 * @param mem_ctx Talloc context, destroyed on completion of the function.
5892 * @param argc Standard main() style argc.
5893 * @param argv Standard main() style argv. Initial components are already
5894 * stripped.
5896 * @return Normal NTSTATUS return.
5899 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5900 const struct dom_sid *domain_sid,
5901 const char *domain_name,
5902 struct cli_state *cli,
5903 struct rpc_pipe_client *pipe_hnd,
5904 TALLOC_CTX *mem_ctx,
5905 int argc,
5906 const char **argv)
5908 const char *msg = N_("This machine will be shutdown shortly");
5909 uint32 timeout = 20;
5910 struct lsa_StringLarge msg_string;
5911 NTSTATUS result;
5912 WERROR werr;
5913 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5915 if (c->opt_comment) {
5916 msg = c->opt_comment;
5918 msg_string.string = msg;
5920 if (c->opt_timeout) {
5921 timeout = c->opt_timeout;
5924 /* create an entry */
5925 result = dcerpc_winreg_InitiateSystemShutdown(b, mem_ctx, NULL,
5926 &msg_string, timeout, c->opt_force, c->opt_reboot,
5927 &werr);
5928 if (!NT_STATUS_IS_OK(result)) {
5929 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5930 return result;
5933 if (W_ERROR_IS_OK(werr)) {
5934 d_printf(_("\nShutdown of remote machine succeeded\n"));
5935 } else {
5936 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5937 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5938 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5939 else
5940 d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5943 return werror_to_ntstatus(werr);
5947 * Shut down a remote RPC server.
5949 * @param argc Standard main() style argc.
5950 * @param argv Standard main() style argv. Initial components are already
5951 * stripped.
5953 * @return A shell status integer (0 for success).
5956 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5958 int rc = -1;
5960 if (c->display_usage) {
5961 d_printf( "%s\n"
5962 "net rpc shutdown\n"
5963 " %s\n",
5964 _("Usage:"),
5965 _("Shut down a remote RPC server"));
5966 return 0;
5969 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5970 rpc_init_shutdown_internals, argc, argv);
5972 if (rc) {
5973 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5974 rc = run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5975 rpc_reg_shutdown_internals, argc, argv);
5978 return rc;
5981 /***************************************************************************
5982 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5983 ***************************************************************************/
5986 * Add interdomain trust account to the RPC server.
5987 * All parameters (except for argc and argv) are passed by run_rpc_command
5988 * function.
5990 * @param c A net_context structure.
5991 * @param domain_sid The domain sid acquired from the server.
5992 * @param cli A cli_state connected to the server.
5993 * @param mem_ctx Talloc context, destroyed on completion of the function.
5994 * @param argc Standard main() style argc.
5995 * @param argv Standard main() style argv. Initial components are already
5996 * stripped.
5998 * @return normal NTSTATUS return code.
6001 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
6002 const struct dom_sid *domain_sid,
6003 const char *domain_name,
6004 struct cli_state *cli,
6005 struct rpc_pipe_client *pipe_hnd,
6006 TALLOC_CTX *mem_ctx,
6007 int argc,
6008 const char **argv)
6010 struct policy_handle connect_pol, domain_pol, user_pol;
6011 NTSTATUS status, result;
6012 char *acct_name;
6013 struct lsa_String lsa_acct_name;
6014 uint32 acb_info;
6015 uint32 acct_flags=0;
6016 uint32 user_rid;
6017 uint32_t access_granted = 0;
6018 union samr_UserInfo info;
6019 unsigned int orig_timeout;
6020 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6021 DATA_BLOB session_key = data_blob_null;
6023 if (argc != 2) {
6024 d_printf("%s\n%s",
6025 _("Usage:"),
6026 _(" net rpc trustdom add <domain_name> "
6027 "<trust password>\n"));
6028 return NT_STATUS_INVALID_PARAMETER;
6032 * Make valid trusting domain account (ie. uppercased and with '$' appended)
6035 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
6036 return NT_STATUS_NO_MEMORY;
6039 if (!strupper_m(acct_name)) {
6040 SAFE_FREE(acct_name);
6041 return NT_STATUS_INVALID_PARAMETER;
6044 init_lsa_String(&lsa_acct_name, acct_name);
6046 status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
6047 if (!NT_STATUS_IS_OK(status)) {
6048 DEBUG(0,("Error getting session_key of SAM pipe. Error was %s\n",
6049 nt_errstr(status)));
6050 goto done;
6053 /* Get samr policy handle */
6054 status = dcerpc_samr_Connect2(b, mem_ctx,
6055 pipe_hnd->desthost,
6056 MAXIMUM_ALLOWED_ACCESS,
6057 &connect_pol,
6058 &result);
6059 if (!NT_STATUS_IS_OK(status)) {
6060 goto done;
6062 if (!NT_STATUS_IS_OK(result)) {
6063 status = result;
6064 goto done;
6067 /* Get domain policy handle */
6068 status = dcerpc_samr_OpenDomain(b, mem_ctx,
6069 &connect_pol,
6070 MAXIMUM_ALLOWED_ACCESS,
6071 discard_const_p(struct dom_sid2, domain_sid),
6072 &domain_pol,
6073 &result);
6074 if (!NT_STATUS_IS_OK(status)) {
6075 goto done;
6077 if (!NT_STATUS_IS_OK(result)) {
6078 status = result;
6079 goto done;
6082 /* This call can take a long time - allow the server to time out.
6083 * 35 seconds should do it. */
6085 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
6087 /* Create trusting domain's account */
6088 acb_info = ACB_NORMAL;
6089 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
6090 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
6091 SAMR_USER_ACCESS_SET_PASSWORD |
6092 SAMR_USER_ACCESS_GET_ATTRIBUTES |
6093 SAMR_USER_ACCESS_SET_ATTRIBUTES;
6095 status = dcerpc_samr_CreateUser2(b, mem_ctx,
6096 &domain_pol,
6097 &lsa_acct_name,
6098 acb_info,
6099 acct_flags,
6100 &user_pol,
6101 &access_granted,
6102 &user_rid,
6103 &result);
6104 if (!NT_STATUS_IS_OK(status)) {
6105 goto done;
6107 /* And restore our original timeout. */
6108 rpccli_set_timeout(pipe_hnd, orig_timeout);
6110 if (!NT_STATUS_IS_OK(result)) {
6111 status = result;
6112 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
6113 acct_name, nt_errstr(result));
6114 goto done;
6118 struct samr_CryptPassword crypt_pwd;
6120 ZERO_STRUCT(info.info23);
6122 init_samr_CryptPassword(argv[1],
6123 &session_key,
6124 &crypt_pwd);
6126 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
6127 SAMR_FIELD_NT_PASSWORD_PRESENT;
6128 info.info23.info.acct_flags = ACB_DOMTRUST;
6129 info.info23.password = crypt_pwd;
6131 status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
6132 &user_pol,
6134 &info,
6135 &result);
6136 if (!NT_STATUS_IS_OK(status)) {
6137 goto done;
6140 if (!NT_STATUS_IS_OK(result)) {
6141 status = result;
6142 DEBUG(0,("Could not set trust account password: %s\n",
6143 nt_errstr(result)));
6144 goto done;
6148 done:
6149 SAFE_FREE(acct_name);
6150 data_blob_clear_free(&session_key);
6151 return status;
6155 * Create interdomain trust account for a remote domain.
6157 * @param argc Standard argc.
6158 * @param argv Standard argv without initial components.
6160 * @return Integer status (0 means success).
6163 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
6165 if (argc > 0 && !c->display_usage) {
6166 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6167 rpc_trustdom_add_internals, argc, argv);
6168 } else {
6169 d_printf("%s\n%s",
6170 _("Usage:"),
6171 _("net rpc trustdom add <domain_name> <trust "
6172 "password>\n"));
6173 return -1;
6179 * Remove interdomain trust account from the RPC server.
6180 * All parameters (except for argc and argv) are passed by run_rpc_command
6181 * function.
6183 * @param c A net_context structure.
6184 * @param domain_sid The domain sid acquired from the server.
6185 * @param cli A cli_state connected to the server.
6186 * @param mem_ctx Talloc context, destroyed on completion of the function.
6187 * @param argc Standard main() style argc.
6188 * @param argv Standard main() style argv. Initial components are already
6189 * stripped.
6191 * @return normal NTSTATUS return code.
6194 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
6195 const struct dom_sid *domain_sid,
6196 const char *domain_name,
6197 struct cli_state *cli,
6198 struct rpc_pipe_client *pipe_hnd,
6199 TALLOC_CTX *mem_ctx,
6200 int argc,
6201 const char **argv)
6203 struct policy_handle connect_pol, domain_pol, user_pol;
6204 NTSTATUS status, result;
6205 char *acct_name;
6206 struct dom_sid trust_acct_sid;
6207 struct samr_Ids user_rids, name_types;
6208 struct lsa_String lsa_acct_name;
6209 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6211 if (argc != 1) {
6212 d_printf("%s\n%s",
6213 _("Usage:"),
6214 _(" net rpc trustdom del <domain_name>\n"));
6215 return NT_STATUS_INVALID_PARAMETER;
6219 * Make valid trusting domain account (ie. uppercased and with '$' appended)
6221 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
6223 if (acct_name == NULL)
6224 return NT_STATUS_NO_MEMORY;
6226 if (!strupper_m(acct_name)) {
6227 TALLOC_FREE(acct_name);
6228 return NT_STATUS_INVALID_PARAMETER;
6231 /* Get samr policy handle */
6232 status = dcerpc_samr_Connect2(b, mem_ctx,
6233 pipe_hnd->desthost,
6234 MAXIMUM_ALLOWED_ACCESS,
6235 &connect_pol,
6236 &result);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 goto done;
6240 if (!NT_STATUS_IS_OK(result)) {
6241 status = result;
6242 goto done;
6245 /* Get domain policy handle */
6246 status = dcerpc_samr_OpenDomain(b, mem_ctx,
6247 &connect_pol,
6248 MAXIMUM_ALLOWED_ACCESS,
6249 discard_const_p(struct dom_sid2, domain_sid),
6250 &domain_pol,
6251 &result);
6252 if (!NT_STATUS_IS_OK(status)) {
6253 goto done;
6255 if (!NT_STATUS_IS_OK(result)) {
6256 status = result;
6257 goto done;
6260 init_lsa_String(&lsa_acct_name, acct_name);
6262 status = dcerpc_samr_LookupNames(b, mem_ctx,
6263 &domain_pol,
6265 &lsa_acct_name,
6266 &user_rids,
6267 &name_types,
6268 &result);
6269 if (!NT_STATUS_IS_OK(status)) {
6270 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6271 "failed %s\n"),
6272 acct_name, nt_errstr(status));
6273 goto done;
6275 if (!NT_STATUS_IS_OK(result)) {
6276 status = result;
6277 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6278 "failed %s\n"),
6279 acct_name, nt_errstr(result) );
6280 goto done;
6282 if (user_rids.count != 1) {
6283 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6284 goto done;
6286 if (name_types.count != 1) {
6287 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6288 goto done;
6291 status = dcerpc_samr_OpenUser(b, mem_ctx,
6292 &domain_pol,
6293 MAXIMUM_ALLOWED_ACCESS,
6294 user_rids.ids[0],
6295 &user_pol,
6296 &result);
6297 if (!NT_STATUS_IS_OK(status)) {
6298 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6299 "%s\n"),
6300 acct_name, nt_errstr(status) );
6301 goto done;
6304 if (!NT_STATUS_IS_OK(result)) {
6305 status = result;
6306 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6307 "%s\n"),
6308 acct_name, nt_errstr(result) );
6309 goto done;
6312 /* append the rid to the domain sid */
6313 if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
6314 goto done;
6317 /* remove the sid */
6319 status = dcerpc_samr_RemoveMemberFromForeignDomain(b, mem_ctx,
6320 &user_pol,
6321 &trust_acct_sid,
6322 &result);
6323 if (!NT_STATUS_IS_OK(status)) {
6324 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6325 " on user %s failed %s\n"),
6326 acct_name, nt_errstr(status));
6327 goto done;
6329 if (!NT_STATUS_IS_OK(result)) {
6330 status = result;
6331 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6332 " on user %s failed %s\n"),
6333 acct_name, nt_errstr(result) );
6334 goto done;
6338 /* Delete user */
6340 status = dcerpc_samr_DeleteUser(b, mem_ctx,
6341 &user_pol,
6342 &result);
6343 if (!NT_STATUS_IS_OK(status)) {
6344 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6345 "%s\n"),
6346 acct_name, nt_errstr(status));
6347 goto done;
6350 if (!NT_STATUS_IS_OK(result)) {
6351 result = status;
6352 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6353 "%s\n"),
6354 acct_name, nt_errstr(result) );
6355 goto done;
6358 if (!NT_STATUS_IS_OK(result)) {
6359 d_printf(_("Could not set trust account password: %s\n"),
6360 nt_errstr(result));
6361 goto done;
6364 done:
6365 return status;
6369 * Delete interdomain trust account for a remote domain.
6371 * @param argc Standard argc.
6372 * @param argv Standard argv without initial components.
6374 * @return Integer status (0 means success).
6377 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
6379 if (argc > 0 && !c->display_usage) {
6380 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6381 rpc_trustdom_del_internals, argc, argv);
6382 } else {
6383 d_printf("%s\n%s",
6384 _("Usage:"),
6385 _("net rpc trustdom del <domain>\n"));
6386 return -1;
6390 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
6391 struct cli_state *cli,
6392 TALLOC_CTX *mem_ctx,
6393 const char *domain_name)
6395 char *dc_name = NULL;
6396 const char *buffer = NULL;
6397 struct rpc_pipe_client *netr;
6398 NTSTATUS status;
6399 WERROR result;
6400 struct dcerpc_binding_handle *b;
6402 /* Use NetServerEnum2 */
6404 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
6405 SAFE_FREE(dc_name);
6406 return NT_STATUS_OK;
6409 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
6410 for domain %s\n", domain_name));
6412 /* Try netr_GetDcName */
6414 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon,
6415 &netr);
6416 if (!NT_STATUS_IS_OK(status)) {
6417 return status;
6420 b = netr->binding_handle;
6422 status = dcerpc_netr_GetDcName(b, mem_ctx,
6423 netr->desthost,
6424 domain_name,
6425 &buffer,
6426 &result);
6427 TALLOC_FREE(netr);
6429 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
6430 return status;
6433 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
6434 for domain %s\n", domain_name));
6436 if (!NT_STATUS_IS_OK(status)) {
6437 return status;
6440 return werror_to_ntstatus(result);
6444 * Establish trust relationship to a trusting domain.
6445 * Interdomain account must already be created on remote PDC.
6447 * @param c A net_context structure.
6448 * @param argc Standard argc.
6449 * @param argv Standard argv without initial components.
6451 * @return Integer status (0 means success).
6454 static int rpc_trustdom_establish(struct net_context *c, int argc,
6455 const char **argv)
6457 struct cli_state *cli = NULL;
6458 struct sockaddr_storage server_ss;
6459 struct rpc_pipe_client *pipe_hnd = NULL;
6460 struct policy_handle connect_hnd;
6461 TALLOC_CTX *mem_ctx;
6462 NTSTATUS nt_status, result;
6463 struct dom_sid *domain_sid;
6465 char* domain_name;
6466 char* acct_name;
6467 fstring pdc_name;
6468 union lsa_PolicyInformation *info = NULL;
6469 struct dcerpc_binding_handle *b;
6472 * Connect to \\server\ipc$ as 'our domain' account with password
6475 if (argc != 1 || c->display_usage) {
6476 d_printf("%s\n%s",
6477 _("Usage:"),
6478 _("net rpc trustdom establish <domain_name>\n"));
6479 return -1;
6482 domain_name = smb_xstrdup(argv[0]);
6483 if (!strupper_m(domain_name)) {
6484 SAFE_FREE(domain_name);
6485 return -1;
6488 /* account name used at first is our domain's name with '$' */
6489 if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
6490 return -1;
6492 if (!strupper_m(acct_name)) {
6493 SAFE_FREE(domain_name);
6494 SAFE_FREE(acct_name);
6495 return -1;
6499 * opt_workgroup will be used by connection functions further,
6500 * hence it should be set to remote domain name instead of ours
6502 if (c->opt_workgroup) {
6503 c->opt_workgroup = smb_xstrdup(domain_name);
6506 c->opt_user_name = acct_name;
6508 /* find the domain controller */
6509 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
6510 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
6511 return -1;
6514 /* connect to ipc$ as username/password */
6515 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
6516 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
6518 /* Is it trusting domain account for sure ? */
6519 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
6520 nt_errstr(nt_status)));
6521 return -1;
6524 /* store who we connected to */
6526 saf_store( domain_name, pdc_name );
6529 * Connect to \\server\ipc$ again (this time anonymously)
6532 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
6533 (char*)pdc_name);
6535 if (NT_STATUS_IS_ERR(nt_status)) {
6536 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
6537 domain_name, nt_errstr(nt_status)));
6538 return -1;
6541 if (!(mem_ctx = talloc_init("establishing trust relationship to "
6542 "domain %s", domain_name))) {
6543 DEBUG(0, ("talloc_init() failed\n"));
6544 cli_shutdown(cli);
6545 return -1;
6548 /* Make sure we're talking to a proper server */
6550 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
6551 if (!NT_STATUS_IS_OK(nt_status)) {
6552 cli_shutdown(cli);
6553 talloc_destroy(mem_ctx);
6554 return -1;
6558 * Call LsaOpenPolicy and LsaQueryInfo
6561 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
6562 &pipe_hnd);
6563 if (!NT_STATUS_IS_OK(nt_status)) {
6564 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
6565 cli_shutdown(cli);
6566 talloc_destroy(mem_ctx);
6567 return -1;
6570 b = pipe_hnd->binding_handle;
6572 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
6573 &connect_hnd);
6574 if (NT_STATUS_IS_ERR(nt_status)) {
6575 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6576 nt_errstr(nt_status)));
6577 cli_shutdown(cli);
6578 talloc_destroy(mem_ctx);
6579 return -1;
6582 /* Querying info level 5 */
6584 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6585 &connect_hnd,
6586 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6587 &info,
6588 &result);
6589 if (NT_STATUS_IS_ERR(nt_status)) {
6590 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6591 nt_errstr(nt_status)));
6592 cli_shutdown(cli);
6593 talloc_destroy(mem_ctx);
6594 return -1;
6596 if (NT_STATUS_IS_ERR(result)) {
6597 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6598 nt_errstr(result)));
6599 cli_shutdown(cli);
6600 talloc_destroy(mem_ctx);
6601 return -1;
6604 domain_sid = info->account_domain.sid;
6606 /* There should be actually query info level 3 (following nt serv behaviour),
6607 but I still don't know if it's _really_ necessary */
6610 * Store the password in secrets db
6613 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6614 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6615 cli_shutdown(cli);
6616 talloc_destroy(mem_ctx);
6617 return -1;
6621 * Close the pipes and clean up
6624 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6625 if (NT_STATUS_IS_ERR(nt_status)) {
6626 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6627 nt_errstr(nt_status)));
6628 cli_shutdown(cli);
6629 talloc_destroy(mem_ctx);
6630 return -1;
6633 cli_shutdown(cli);
6635 talloc_destroy(mem_ctx);
6637 d_printf(_("Trust to domain %s established\n"), domain_name);
6638 return 0;
6642 * Revoke trust relationship to the remote domain.
6644 * @param c A net_context structure.
6645 * @param argc Standard argc.
6646 * @param argv Standard argv without initial components.
6648 * @return Integer status (0 means success).
6651 static int rpc_trustdom_revoke(struct net_context *c, int argc,
6652 const char **argv)
6654 char* domain_name;
6655 int rc = -1;
6657 if (argc < 1 || c->display_usage) {
6658 d_printf("%s\n%s",
6659 _("Usage:"),
6660 _("net rpc trustdom revoke <domain_name>\n"
6661 " Revoke trust relationship\n"
6662 " domain_name\tName of domain to revoke trust\n"));
6663 return -1;
6666 /* generate upper cased domain name */
6667 domain_name = smb_xstrdup(argv[0]);
6668 if (!strupper_m(domain_name)) {
6669 SAFE_FREE(domain_name);
6670 return -1;
6673 /* delete password of the trust */
6674 if (!pdb_del_trusteddom_pw(domain_name)) {
6675 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6676 domain_name));
6677 goto done;
6680 rc = 0;
6681 done:
6682 SAFE_FREE(domain_name);
6683 return rc;
6686 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6687 const struct dom_sid *domain_sid,
6688 const char *domain_name,
6689 struct cli_state *cli,
6690 struct rpc_pipe_client *pipe_hnd,
6691 TALLOC_CTX *mem_ctx,
6692 int argc,
6693 const char **argv)
6695 fstring str_sid;
6696 if (!sid_to_fstring(str_sid, domain_sid)) {
6697 return NT_STATUS_UNSUCCESSFUL;
6699 d_printf("%s\n", str_sid);
6700 return NT_STATUS_OK;
6703 static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
6705 fstring ascii_sid;
6707 /* convert sid into ascii string */
6708 sid_to_fstring(ascii_sid, dom_sid);
6710 d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
6713 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6714 TALLOC_CTX *mem_ctx,
6715 struct policy_handle *pol,
6716 struct dom_sid dom_sid,
6717 const char *trusted_dom_name)
6719 NTSTATUS nt_status, result;
6720 union lsa_TrustedDomainInfo *info = NULL;
6721 char *cleartextpwd = NULL;
6722 DATA_BLOB session_key;
6723 DATA_BLOB data = data_blob_null;
6724 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6726 nt_status = dcerpc_lsa_QueryTrustedDomainInfoBySid(b, mem_ctx,
6727 pol,
6728 &dom_sid,
6729 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6730 &info,
6731 &result);
6732 if (NT_STATUS_IS_ERR(nt_status)) {
6733 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6734 nt_errstr(nt_status)));
6735 goto done;
6737 if (NT_STATUS_IS_ERR(result)) {
6738 nt_status = result;
6739 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6740 nt_errstr(result)));
6741 goto done;
6744 data = data_blob(info->password.password->data,
6745 info->password.password->length);
6747 nt_status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
6748 if (!NT_STATUS_IS_OK(nt_status)) {
6749 DEBUG(0, ("Could not retrieve session key: %s\n", nt_errstr(nt_status)));
6750 goto done;
6753 cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key);
6754 data_blob_free(&session_key);
6756 if (cleartextpwd == NULL) {
6757 DEBUG(0,("retrieved NULL password\n"));
6758 nt_status = NT_STATUS_UNSUCCESSFUL;
6759 goto done;
6762 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6763 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6764 nt_status = NT_STATUS_UNSUCCESSFUL;
6765 goto done;
6768 #ifdef DEBUG_PASSWORD
6769 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
6770 "password: [%s]\n", trusted_dom_name,
6771 sid_string_dbg(&dom_sid), cleartextpwd));
6772 #endif
6774 done:
6775 SAFE_FREE(cleartextpwd);
6776 data_blob_free(&data);
6778 return nt_status;
6781 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6782 const char **argv)
6784 /* common variables */
6785 TALLOC_CTX* mem_ctx;
6786 struct cli_state *cli = NULL;
6787 struct rpc_pipe_client *pipe_hnd = NULL;
6788 NTSTATUS nt_status, result;
6789 const char *domain_name = NULL;
6790 struct policy_handle connect_hnd;
6791 union lsa_PolicyInformation *info = NULL;
6793 /* trusted domains listing variables */
6794 unsigned int enum_ctx = 0;
6795 int i;
6796 struct lsa_DomainList dom_list;
6797 fstring pdc_name;
6798 struct dcerpc_binding_handle *b;
6800 if (c->display_usage) {
6801 d_printf( "%s\n"
6802 "net rpc trustdom vampire\n"
6803 " %s\n",
6804 _("Usage:"),
6805 _("Vampire trust relationship from remote server"));
6806 return 0;
6810 * Listing trusted domains (stored in secrets.tdb, if local)
6813 mem_ctx = talloc_init("trust relationships vampire");
6816 * set domain and pdc name to local samba server (default)
6817 * or to remote one given in command line
6820 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6821 domain_name = c->opt_workgroup;
6822 c->opt_target_workgroup = c->opt_workgroup;
6823 } else {
6824 fstrcpy(pdc_name, lp_netbios_name());
6825 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6826 c->opt_target_workgroup = domain_name;
6829 /* open \PIPE\lsarpc and open policy handle */
6830 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6831 if (!NT_STATUS_IS_OK(nt_status)) {
6832 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6833 nt_errstr(nt_status)));
6834 talloc_destroy(mem_ctx);
6835 return -1;
6838 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
6839 &pipe_hnd);
6840 if (!NT_STATUS_IS_OK(nt_status)) {
6841 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6842 nt_errstr(nt_status) ));
6843 cli_shutdown(cli);
6844 talloc_destroy(mem_ctx);
6845 return -1;
6848 b = pipe_hnd->binding_handle;
6850 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6851 &connect_hnd);
6852 if (NT_STATUS_IS_ERR(nt_status)) {
6853 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6854 nt_errstr(nt_status)));
6855 cli_shutdown(cli);
6856 talloc_destroy(mem_ctx);
6857 return -1;
6860 /* query info level 5 to obtain sid of a domain being queried */
6861 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6862 &connect_hnd,
6863 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6864 &info,
6865 &result);
6867 if (NT_STATUS_IS_ERR(nt_status)) {
6868 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6869 nt_errstr(nt_status)));
6870 cli_shutdown(cli);
6871 talloc_destroy(mem_ctx);
6872 return -1;
6874 if (NT_STATUS_IS_ERR(result)) {
6875 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6876 nt_errstr(result)));
6877 cli_shutdown(cli);
6878 talloc_destroy(mem_ctx);
6879 return -1;
6883 * Keep calling LsaEnumTrustdom over opened pipe until
6884 * the end of enumeration is reached
6887 d_printf(_("Vampire trusted domains:\n\n"));
6889 do {
6890 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
6891 &connect_hnd,
6892 &enum_ctx,
6893 &dom_list,
6894 (uint32_t)-1,
6895 &result);
6896 if (NT_STATUS_IS_ERR(nt_status)) {
6897 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6898 nt_errstr(nt_status)));
6899 cli_shutdown(cli);
6900 talloc_destroy(mem_ctx);
6901 return -1;
6903 if (NT_STATUS_IS_ERR(result)) {
6904 nt_status = result;
6905 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6906 nt_errstr(result)));
6907 cli_shutdown(cli);
6908 talloc_destroy(mem_ctx);
6909 return -1;
6913 for (i = 0; i < dom_list.count; i++) {
6915 print_trusted_domain(dom_list.domains[i].sid,
6916 dom_list.domains[i].name.string);
6918 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
6919 *dom_list.domains[i].sid,
6920 dom_list.domains[i].name.string);
6921 if (!NT_STATUS_IS_OK(nt_status)) {
6922 cli_shutdown(cli);
6923 talloc_destroy(mem_ctx);
6924 return -1;
6929 * in case of no trusted domains say something rather
6930 * than just display blank line
6932 if (!dom_list.count) d_printf(_("none\n"));
6934 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6936 /* close this connection before doing next one */
6937 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6938 if (NT_STATUS_IS_ERR(nt_status)) {
6939 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6940 nt_errstr(nt_status)));
6941 cli_shutdown(cli);
6942 talloc_destroy(mem_ctx);
6943 return -1;
6946 /* close lsarpc pipe and connection to IPC$ */
6947 cli_shutdown(cli);
6949 talloc_destroy(mem_ctx);
6950 return 0;
6953 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6955 /* common variables */
6956 TALLOC_CTX* mem_ctx;
6957 struct cli_state *cli = NULL, *remote_cli = NULL;
6958 struct rpc_pipe_client *pipe_hnd = NULL;
6959 NTSTATUS nt_status, result;
6960 const char *domain_name = NULL;
6961 struct dom_sid *queried_dom_sid;
6962 int ascii_dom_name_len;
6963 struct policy_handle connect_hnd;
6964 union lsa_PolicyInformation *info = NULL;
6965 struct dcerpc_binding_handle *b = NULL;
6967 /* trusted domains listing variables */
6968 unsigned int num_domains, enum_ctx = 0;
6969 int i;
6970 struct lsa_DomainList dom_list;
6971 fstring pdc_name;
6972 bool found_domain;
6974 /* trusting domains listing variables */
6975 struct policy_handle domain_hnd;
6976 struct samr_SamArray *trusts = NULL;
6978 if (c->display_usage) {
6979 d_printf( "%s\n"
6980 "net rpc trustdom list\n"
6981 " %s\n",
6982 _("Usage:"),
6983 _("List incoming and outgoing trust relationships"));
6984 return 0;
6988 * Listing trusted domains (stored in secrets.tdb, if local)
6991 mem_ctx = talloc_init("trust relationships listing");
6994 * set domain and pdc name to local samba server (default)
6995 * or to remote one given in command line
6998 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6999 domain_name = c->opt_workgroup;
7000 c->opt_target_workgroup = c->opt_workgroup;
7001 } else {
7002 fstrcpy(pdc_name, lp_netbios_name());
7003 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
7004 c->opt_target_workgroup = domain_name;
7007 /* open \PIPE\lsarpc and open policy handle */
7008 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
7009 if (!NT_STATUS_IS_OK(nt_status)) {
7010 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
7011 nt_errstr(nt_status)));
7012 talloc_destroy(mem_ctx);
7013 return -1;
7016 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
7017 &pipe_hnd);
7018 if (!NT_STATUS_IS_OK(nt_status)) {
7019 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
7020 nt_errstr(nt_status) ));
7021 cli_shutdown(cli);
7022 talloc_destroy(mem_ctx);
7023 return -1;
7026 b = pipe_hnd->binding_handle;
7028 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
7029 &connect_hnd);
7030 if (NT_STATUS_IS_ERR(nt_status)) {
7031 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
7032 nt_errstr(nt_status)));
7033 cli_shutdown(cli);
7034 talloc_destroy(mem_ctx);
7035 return -1;
7038 /* query info level 5 to obtain sid of a domain being queried */
7039 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
7040 &connect_hnd,
7041 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
7042 &info,
7043 &result);
7045 if (NT_STATUS_IS_ERR(nt_status)) {
7046 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
7047 nt_errstr(nt_status)));
7048 cli_shutdown(cli);
7049 talloc_destroy(mem_ctx);
7050 return -1;
7052 if (NT_STATUS_IS_ERR(result)) {
7053 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
7054 nt_errstr(result)));
7055 cli_shutdown(cli);
7056 talloc_destroy(mem_ctx);
7057 return -1;
7060 queried_dom_sid = info->account_domain.sid;
7063 * Keep calling LsaEnumTrustdom over opened pipe until
7064 * the end of enumeration is reached
7067 d_printf(_("Trusted domains list:\n\n"));
7069 found_domain = false;
7071 do {
7072 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
7073 &connect_hnd,
7074 &enum_ctx,
7075 &dom_list,
7076 (uint32_t)-1,
7077 &result);
7078 if (NT_STATUS_IS_ERR(nt_status)) {
7079 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7080 nt_errstr(nt_status)));
7081 cli_shutdown(cli);
7082 talloc_destroy(mem_ctx);
7083 return -1;
7085 if (NT_STATUS_IS_ERR(result)) {
7086 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
7087 nt_errstr(result)));
7088 cli_shutdown(cli);
7089 talloc_destroy(mem_ctx);
7090 return -1;
7094 for (i = 0; i < dom_list.count; i++) {
7095 print_trusted_domain(dom_list.domains[i].sid,
7096 dom_list.domains[i].name.string);
7097 found_domain = true;
7101 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
7104 * in case of no trusted domains say something rather
7105 * than just display blank line
7107 if (!found_domain) {
7108 d_printf(_("none\n"));
7111 /* close this connection before doing next one */
7112 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
7113 if (NT_STATUS_IS_ERR(nt_status)) {
7114 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
7115 nt_errstr(nt_status)));
7116 cli_shutdown(cli);
7117 talloc_destroy(mem_ctx);
7118 return -1;
7121 TALLOC_FREE(pipe_hnd);
7124 * Listing trusting domains (stored in passdb backend, if local)
7127 d_printf(_("\nTrusting domains list:\n\n"));
7130 * Open \PIPE\samr and get needed policy handles
7132 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr,
7133 &pipe_hnd);
7134 if (!NT_STATUS_IS_OK(nt_status)) {
7135 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
7136 cli_shutdown(cli);
7137 talloc_destroy(mem_ctx);
7138 return -1;
7141 b = pipe_hnd->binding_handle;
7143 /* SamrConnect2 */
7144 nt_status = dcerpc_samr_Connect2(b, mem_ctx,
7145 pipe_hnd->desthost,
7146 SAMR_ACCESS_LOOKUP_DOMAIN,
7147 &connect_hnd,
7148 &result);
7149 if (!NT_STATUS_IS_OK(nt_status)) {
7150 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
7151 nt_errstr(nt_status)));
7152 cli_shutdown(cli);
7153 talloc_destroy(mem_ctx);
7154 return -1;
7156 if (!NT_STATUS_IS_OK(result)) {
7157 nt_status = result;
7158 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
7159 nt_errstr(result)));
7160 cli_shutdown(cli);
7161 talloc_destroy(mem_ctx);
7162 return -1;
7165 /* SamrOpenDomain - we have to open domain policy handle in order to be
7166 able to enumerate accounts*/
7167 nt_status = dcerpc_samr_OpenDomain(b, mem_ctx,
7168 &connect_hnd,
7169 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
7170 queried_dom_sid,
7171 &domain_hnd,
7172 &result);
7173 if (!NT_STATUS_IS_OK(nt_status)) {
7174 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7175 nt_errstr(nt_status)));
7176 cli_shutdown(cli);
7177 talloc_destroy(mem_ctx);
7178 return -1;
7180 if (!NT_STATUS_IS_OK(result)) {
7181 nt_status = result;
7182 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7183 nt_errstr(result)));
7184 cli_shutdown(cli);
7185 talloc_destroy(mem_ctx);
7186 return -1;
7190 * perform actual enumeration
7193 found_domain = false;
7195 enum_ctx = 0; /* reset enumeration context from last enumeration */
7196 do {
7198 nt_status = dcerpc_samr_EnumDomainUsers(b, mem_ctx,
7199 &domain_hnd,
7200 &enum_ctx,
7201 ACB_DOMTRUST,
7202 &trusts,
7203 0xffff,
7204 &num_domains,
7205 &result);
7206 if (NT_STATUS_IS_ERR(nt_status)) {
7207 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7208 nt_errstr(nt_status)));
7209 cli_shutdown(cli);
7210 talloc_destroy(mem_ctx);
7211 return -1;
7213 if (NT_STATUS_IS_ERR(result)) {
7214 nt_status = result;
7215 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7216 nt_errstr(result)));
7217 cli_shutdown(cli);
7218 talloc_destroy(mem_ctx);
7219 return -1;
7222 for (i = 0; i < num_domains; i++) {
7224 char *str = discard_const_p(char, trusts->entries[i].name.string);
7226 found_domain = true;
7229 * get each single domain's sid (do we _really_ need this ?):
7230 * 1) connect to domain's pdc
7231 * 2) query the pdc for domain's sid
7234 /* get rid of '$' tail */
7235 ascii_dom_name_len = strlen(str);
7236 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
7237 str[ascii_dom_name_len - 1] = '\0';
7239 /* set opt_* variables to remote domain */
7240 if (!strupper_m(str)) {
7241 cli_shutdown(cli);
7242 talloc_destroy(mem_ctx);
7243 return -1;
7245 c->opt_workgroup = talloc_strdup(mem_ctx, str);
7246 c->opt_target_workgroup = c->opt_workgroup;
7248 d_printf("%-20s", str);
7250 /* connect to remote domain controller */
7251 nt_status = net_make_ipc_connection(c,
7252 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
7253 &remote_cli);
7254 if (NT_STATUS_IS_OK(nt_status)) {
7255 /* query for domain's sid */
7256 if (run_rpc_command(
7257 c, remote_cli,
7258 &ndr_table_lsarpc, 0,
7259 rpc_query_domain_sid, argc,
7260 argv))
7261 d_printf(_("strange - couldn't get domain's sid\n"));
7263 cli_shutdown(remote_cli);
7265 } else {
7266 d_fprintf(stderr, _("domain controller is not "
7267 "responding: %s\n"),
7268 nt_errstr(nt_status));
7269 d_printf(_("couldn't get domain's sid\n"));
7273 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
7275 if (!found_domain) {
7276 d_printf("none\n");
7279 /* close opened samr and domain policy handles */
7280 nt_status = dcerpc_samr_Close(b, mem_ctx, &domain_hnd, &result);
7281 if (!NT_STATUS_IS_OK(nt_status)) {
7282 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
7285 nt_status = dcerpc_samr_Close(b, mem_ctx, &connect_hnd, &result);
7286 if (!NT_STATUS_IS_OK(nt_status)) {
7287 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
7290 /* close samr pipe and connection to IPC$ */
7291 cli_shutdown(cli);
7293 talloc_destroy(mem_ctx);
7294 return 0;
7298 * Entrypoint for 'net rpc trustdom' code.
7300 * @param argc Standard argc.
7301 * @param argv Standard argv without initial components.
7303 * @return Integer status (0 means success).
7306 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
7308 struct functable func[] = {
7310 "add",
7311 rpc_trustdom_add,
7312 NET_TRANSPORT_RPC,
7313 N_("Add trusting domain's account"),
7314 N_("net rpc trustdom add\n"
7315 " Add trusting domain's account")
7318 "del",
7319 rpc_trustdom_del,
7320 NET_TRANSPORT_RPC,
7321 N_("Remove trusting domain's account"),
7322 N_("net rpc trustdom del\n"
7323 " Remove trusting domain's account")
7326 "establish",
7327 rpc_trustdom_establish,
7328 NET_TRANSPORT_RPC,
7329 N_("Establish outgoing trust relationship"),
7330 N_("net rpc trustdom establish\n"
7331 " Establish outgoing trust relationship")
7334 "revoke",
7335 rpc_trustdom_revoke,
7336 NET_TRANSPORT_RPC,
7337 N_("Revoke outgoing trust relationship"),
7338 N_("net rpc trustdom revoke\n"
7339 " Revoke outgoing trust relationship")
7342 "list",
7343 rpc_trustdom_list,
7344 NET_TRANSPORT_RPC,
7345 N_("List in- and outgoing domain trusts"),
7346 N_("net rpc trustdom list\n"
7347 " List in- and outgoing domain trusts")
7350 "vampire",
7351 rpc_trustdom_vampire,
7352 NET_TRANSPORT_RPC,
7353 N_("Vampire trusts from remote server"),
7354 N_("net rpc trustdom vampire\n"
7355 " Vampire trusts from remote server")
7357 {NULL, NULL, 0, NULL, NULL}
7360 return net_run_function(c, argc, argv, "net rpc trustdom", func);
7364 * Check if a server will take rpc commands
7365 * @param flags Type of server to connect to (PDC, DMB, localhost)
7366 * if the host is not explicitly specified
7367 * @return bool (true means rpc supported)
7369 bool net_rpc_check(struct net_context *c, unsigned flags)
7371 struct cli_state *cli;
7372 bool ret = false;
7373 struct sockaddr_storage server_ss;
7374 char *server_name = NULL;
7375 NTSTATUS status;
7377 /* flags (i.e. server type) may depend on command */
7378 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
7379 return false;
7381 status = cli_connect_nb(server_name, &server_ss, 0, 0x20,
7382 lp_netbios_name(), SMB_SIGNING_DEFAULT,
7383 0, &cli);
7384 if (!NT_STATUS_IS_OK(status)) {
7385 return false;
7387 status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
7388 PROTOCOL_NT1);
7389 if (!NT_STATUS_IS_OK(status))
7390 goto done;
7391 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1)
7392 goto done;
7394 ret = true;
7395 done:
7396 cli_shutdown(cli);
7397 return ret;
7400 /* dump sam database via samsync rpc calls */
7401 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
7402 if (c->display_usage) {
7403 d_printf( "%s\n"
7404 "net rpc samdump\n"
7405 " %s\n",
7406 _("Usage:"),
7407 _("Dump remote SAM database"));
7408 return 0;
7411 return run_rpc_command(c, NULL, &ndr_table_netlogon,
7412 NET_FLAGS_ANONYMOUS,
7413 rpc_samdump_internals, argc, argv);
7416 /* syncronise sam database via samsync rpc calls */
7417 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
7419 struct functable func[] = {
7421 "ldif",
7422 rpc_vampire_ldif,
7423 NET_TRANSPORT_RPC,
7424 N_("Dump remote SAM database to ldif"),
7425 N_("net rpc vampire ldif\n"
7426 " Dump remote SAM database to LDIF file or "
7427 "stdout")
7430 "keytab",
7431 rpc_vampire_keytab,
7432 NET_TRANSPORT_RPC,
7433 N_("Dump remote SAM database to Kerberos Keytab"),
7434 N_("net rpc vampire keytab\n"
7435 " Dump remote SAM database to Kerberos keytab "
7436 "file")
7439 "passdb",
7440 rpc_vampire_passdb,
7441 NET_TRANSPORT_RPC,
7442 N_("Dump remote SAM database to passdb"),
7443 N_("net rpc vampire passdb\n"
7444 " Dump remote SAM database to passdb")
7447 {NULL, NULL, 0, NULL, NULL}
7450 if (argc == 0) {
7451 if (c->display_usage) {
7452 d_printf( "%s\n"
7453 "net rpc vampire\n"
7454 " %s\n",
7455 _("Usage:"),
7456 _("Vampire remote SAM database"));
7457 return 0;
7460 return rpc_vampire_passdb(c, argc, argv);
7463 return net_run_function(c, argc, argv, "net rpc vampire", func);
7467 * Migrate everything from a print server.
7469 * @param c A net_context structure.
7470 * @param argc Standard main() style argc.
7471 * @param argv Standard main() style argv. Initial components are already
7472 * stripped.
7474 * @return A shell status integer (0 for success).
7476 * The order is important !
7477 * To successfully add drivers the print queues have to exist !
7478 * Applying ACLs should be the last step, because you're easily locked out.
7481 static int rpc_printer_migrate_all(struct net_context *c, int argc,
7482 const char **argv)
7484 int ret;
7486 if (c->display_usage) {
7487 d_printf( "%s\n"
7488 "net rpc printer migrate all\n"
7489 " %s\n",
7490 _("Usage:"),
7491 _("Migrate everything from a print server"));
7492 return 0;
7495 if (!c->opt_host) {
7496 d_printf(_("no server to migrate\n"));
7497 return -1;
7500 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7501 rpc_printer_migrate_printers_internals, argc,
7502 argv);
7503 if (ret)
7504 return ret;
7506 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7507 rpc_printer_migrate_drivers_internals, argc,
7508 argv);
7509 if (ret)
7510 return ret;
7512 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7513 rpc_printer_migrate_forms_internals, argc, argv);
7514 if (ret)
7515 return ret;
7517 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7518 rpc_printer_migrate_settings_internals, argc,
7519 argv);
7520 if (ret)
7521 return ret;
7523 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7524 rpc_printer_migrate_security_internals, argc,
7525 argv);
7530 * Migrate print drivers from a print server.
7532 * @param c A net_context structure.
7533 * @param argc Standard main() style argc.
7534 * @param argv Standard main() style argv. Initial components are already
7535 * stripped.
7537 * @return A shell status integer (0 for success).
7539 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
7540 const char **argv)
7542 if (c->display_usage) {
7543 d_printf( "%s\n"
7544 "net rpc printer migrate drivers\n"
7545 " %s\n",
7546 _("Usage:"),
7547 _("Migrate print-drivers from a print-server"));
7548 return 0;
7551 if (!c->opt_host) {
7552 d_printf(_("no server to migrate\n"));
7553 return -1;
7556 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7557 rpc_printer_migrate_drivers_internals,
7558 argc, argv);
7562 * Migrate print-forms from a print-server.
7564 * @param c A net_context structure.
7565 * @param argc Standard main() style argc.
7566 * @param argv Standard main() style argv. Initial components are already
7567 * stripped.
7569 * @return A shell status integer (0 for success).
7571 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
7572 const char **argv)
7574 if (c->display_usage) {
7575 d_printf( "%s\n"
7576 "net rpc printer migrate forms\n"
7577 " %s\n",
7578 _("Usage:"),
7579 _("Migrate print-forms from a print-server"));
7580 return 0;
7583 if (!c->opt_host) {
7584 d_printf(_("no server to migrate\n"));
7585 return -1;
7588 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7589 rpc_printer_migrate_forms_internals,
7590 argc, argv);
7594 * Migrate printers from a print-server.
7596 * @param c A net_context structure.
7597 * @param argc Standard main() style argc.
7598 * @param argv Standard main() style argv. Initial components are already
7599 * stripped.
7601 * @return A shell status integer (0 for success).
7603 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
7604 const char **argv)
7606 if (c->display_usage) {
7607 d_printf( "%s\n"
7608 "net rpc printer migrate printers\n"
7609 " %s\n",
7610 _("Usage:"),
7611 _("Migrate printers from a print-server"));
7612 return 0;
7615 if (!c->opt_host) {
7616 d_printf(_("no server to migrate\n"));
7617 return -1;
7620 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7621 rpc_printer_migrate_printers_internals,
7622 argc, argv);
7626 * Migrate printer-ACLs from a print-server
7628 * @param c A net_context structure.
7629 * @param argc Standard main() style argc.
7630 * @param argv Standard main() style argv. Initial components are already
7631 * stripped.
7633 * @return A shell status integer (0 for success).
7635 static int rpc_printer_migrate_security(struct net_context *c, int argc,
7636 const char **argv)
7638 if (c->display_usage) {
7639 d_printf( "%s\n"
7640 "net rpc printer migrate security\n"
7641 " %s\n",
7642 _("Usage:"),
7643 _("Migrate printer-ACLs from a print-server"));
7644 return 0;
7647 if (!c->opt_host) {
7648 d_printf(_("no server to migrate\n"));
7649 return -1;
7652 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7653 rpc_printer_migrate_security_internals,
7654 argc, argv);
7658 * Migrate printer-settings from a print-server.
7660 * @param c A net_context structure.
7661 * @param argc Standard main() style argc.
7662 * @param argv Standard main() style argv. Initial components are already
7663 * stripped.
7665 * @return A shell status integer (0 for success).
7667 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
7668 const char **argv)
7670 if (c->display_usage) {
7671 d_printf( "%s\n"
7672 "net rpc printer migrate settings\n"
7673 " %s\n",
7674 _("Usage:"),
7675 _("Migrate printer-settings from a "
7676 "print-server"));
7677 return 0;
7680 if (!c->opt_host) {
7681 d_printf(_("no server to migrate\n"));
7682 return -1;
7685 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7686 rpc_printer_migrate_settings_internals,
7687 argc, argv);
7691 * 'net rpc printer' entrypoint.
7693 * @param c A net_context structure.
7694 * @param argc Standard main() style argc.
7695 * @param argv Standard main() style argv. Initial components are already
7696 * stripped.
7699 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
7702 /* ouch: when addriver and setdriver are called from within
7703 rpc_printer_migrate_drivers_internals, the printer-queue already
7704 *has* to exist */
7706 struct functable func[] = {
7708 "all",
7709 rpc_printer_migrate_all,
7710 NET_TRANSPORT_RPC,
7711 N_("Migrate all from remote to local print server"),
7712 N_("net rpc printer migrate all\n"
7713 " Migrate all from remote to local print server")
7716 "drivers",
7717 rpc_printer_migrate_drivers,
7718 NET_TRANSPORT_RPC,
7719 N_("Migrate drivers to local server"),
7720 N_("net rpc printer migrate drivers\n"
7721 " Migrate drivers to local server")
7724 "forms",
7725 rpc_printer_migrate_forms,
7726 NET_TRANSPORT_RPC,
7727 N_("Migrate froms to local server"),
7728 N_("net rpc printer migrate forms\n"
7729 " Migrate froms to local server")
7732 "printers",
7733 rpc_printer_migrate_printers,
7734 NET_TRANSPORT_RPC,
7735 N_("Migrate printers to local server"),
7736 N_("net rpc printer migrate printers\n"
7737 " Migrate printers to local server")
7740 "security",
7741 rpc_printer_migrate_security,
7742 NET_TRANSPORT_RPC,
7743 N_("Mirgate printer ACLs to local server"),
7744 N_("net rpc printer migrate security\n"
7745 " Mirgate printer ACLs to local server")
7748 "settings",
7749 rpc_printer_migrate_settings,
7750 NET_TRANSPORT_RPC,
7751 N_("Migrate printer settings to local server"),
7752 N_("net rpc printer migrate settings\n"
7753 " Migrate printer settings to local server")
7755 {NULL, NULL, 0, NULL, NULL}
7758 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7763 * List printers on a remote RPC server.
7765 * @param c A net_context structure.
7766 * @param argc Standard main() style argc.
7767 * @param argv Standard main() style argv. Initial components are already
7768 * stripped.
7770 * @return A shell status integer (0 for success).
7772 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7774 if (c->display_usage) {
7775 d_printf( "%s\n"
7776 "net rpc printer list\n"
7777 " %s\n",
7778 _("Usage:"),
7779 _("List printers on a remote RPC server"));
7780 return 0;
7783 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7784 rpc_printer_list_internals,
7785 argc, argv);
7789 * List printer-drivers on a remote RPC server.
7791 * @param c A net_context structure.
7792 * @param argc Standard main() style argc.
7793 * @param argv Standard main() style argv. Initial components are already
7794 * stripped.
7796 * @return A shell status integer (0 for success).
7798 static int rpc_printer_driver_list(struct net_context *c, int argc,
7799 const char **argv)
7801 if (c->display_usage) {
7802 d_printf( "%s\n"
7803 "net rpc printer driver\n"
7804 " %s\n",
7805 _("Usage:"),
7806 _("List printer-drivers on a remote RPC server"));
7807 return 0;
7810 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7811 rpc_printer_driver_list_internals,
7812 argc, argv);
7816 * Publish printer in ADS via MSRPC.
7818 * @param c A net_context structure.
7819 * @param argc Standard main() style argc.
7820 * @param argv Standard main() style argv. Initial components are already
7821 * stripped.
7823 * @return A shell status integer (0 for success).
7825 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7826 const char **argv)
7828 if (c->display_usage) {
7829 d_printf( "%s\n"
7830 "net rpc printer publish publish\n"
7831 " %s\n",
7832 _("Usage:"),
7833 _("Publish printer in ADS via MSRPC"));
7834 return 0;
7837 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7838 rpc_printer_publish_publish_internals,
7839 argc, argv);
7843 * Update printer in ADS via MSRPC.
7845 * @param c A net_context structure.
7846 * @param argc Standard main() style argc.
7847 * @param argv Standard main() style argv. Initial components are already
7848 * stripped.
7850 * @return A shell status integer (0 for success).
7852 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7854 if (c->display_usage) {
7855 d_printf( "%s\n"
7856 "net rpc printer publish update\n"
7857 " %s\n",
7858 _("Usage:"),
7859 _("Update printer in ADS via MSRPC"));
7860 return 0;
7863 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7864 rpc_printer_publish_update_internals,
7865 argc, argv);
7869 * UnPublish printer in ADS via MSRPC.
7871 * @param c A net_context structure.
7872 * @param argc Standard main() style argc.
7873 * @param argv Standard main() style argv. Initial components are already
7874 * stripped.
7876 * @return A shell status integer (0 for success).
7878 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7879 const char **argv)
7881 if (c->display_usage) {
7882 d_printf( "%s\n"
7883 "net rpc printer publish unpublish\n"
7884 " %s\n",
7885 _("Usage:\n"),
7886 _("UnPublish printer in ADS via MSRPC"));
7887 return 0;
7890 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7891 rpc_printer_publish_unpublish_internals,
7892 argc, argv);
7896 * List published printers via MSRPC.
7898 * @param c A net_context structure.
7899 * @param argc Standard main() style argc.
7900 * @param argv Standard main() style argv. Initial components are already
7901 * stripped.
7903 * @return A shell status integer (0 for success).
7905 static int rpc_printer_publish_list(struct net_context *c, int argc,
7906 const char **argv)
7908 if (c->display_usage) {
7909 d_printf( "%s\n"
7910 "net rpc printer publish list\n"
7911 " %s\n",
7912 _("Usage:"),
7913 _("List published printers via MSRPC"));
7914 return 0;
7917 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7918 rpc_printer_publish_list_internals,
7919 argc, argv);
7924 * Publish printer in ADS.
7926 * @param c A net_context structure.
7927 * @param argc Standard main() style argc.
7928 * @param argv Standard main() style argv. Initial components are already
7929 * stripped.
7931 * @return A shell status integer (0 for success).
7933 static int rpc_printer_publish(struct net_context *c, int argc,
7934 const char **argv)
7937 struct functable func[] = {
7939 "publish",
7940 rpc_printer_publish_publish,
7941 NET_TRANSPORT_RPC,
7942 N_("Publish printer in AD"),
7943 N_("net rpc printer publish publish\n"
7944 " Publish printer in AD")
7947 "update",
7948 rpc_printer_publish_update,
7949 NET_TRANSPORT_RPC,
7950 N_("Update printer in AD"),
7951 N_("net rpc printer publish update\n"
7952 " Update printer in AD")
7955 "unpublish",
7956 rpc_printer_publish_unpublish,
7957 NET_TRANSPORT_RPC,
7958 N_("Unpublish printer"),
7959 N_("net rpc printer publish unpublish\n"
7960 " Unpublish printer")
7963 "list",
7964 rpc_printer_publish_list,
7965 NET_TRANSPORT_RPC,
7966 N_("List published printers"),
7967 N_("net rpc printer publish list\n"
7968 " List published printers")
7970 {NULL, NULL, 0, NULL, NULL}
7973 if (argc == 0) {
7974 if (c->display_usage) {
7975 d_printf(_("Usage:\n"));
7976 d_printf(_("net rpc printer publish\n"
7977 " List published printers\n"
7978 " Alias of net rpc printer publish "
7979 "list\n"));
7980 net_display_usage_from_functable(func);
7981 return 0;
7983 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7984 rpc_printer_publish_list_internals,
7985 argc, argv);
7988 return net_run_function(c, argc, argv, "net rpc printer publish",func);
7994 * Display rpc printer help page.
7996 * @param c A net_context structure.
7997 * @param argc Standard main() style argc.
7998 * @param argv Standard main() style argv. Initial components are already
7999 * stripped.
8001 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
8003 d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
8004 "\tlists all printers on print-server\n\n"));
8005 d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
8006 "\tlists all printer-drivers on print-server\n\n"));
8007 d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
8008 "\tpublishes printer settings in Active Directory\n"
8009 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
8010 d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
8011 "\n\tmigrates printers from remote to local server\n\n"));
8012 d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
8013 "\n\tmigrates printer-settings from remote to local server\n\n"));
8014 d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
8015 "\n\tmigrates printer-drivers from remote to local server\n\n"));
8016 d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
8017 "\n\tmigrates printer-forms from remote to local server\n\n"));
8018 d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
8019 "\n\tmigrates printer-ACLs from remote to local server\n\n"));
8020 d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
8021 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
8022 "\tremote to local print-server\n\n"));
8023 net_common_methods_usage(c, argc, argv);
8024 net_common_flags_usage(c, argc, argv);
8025 d_printf(_(
8026 "\t-v or --verbose\t\t\tgive verbose output\n"
8027 "\t --destination\t\tmigration target server (default: localhost)\n"));
8029 return -1;
8033 * 'net rpc printer' entrypoint.
8035 * @param c A net_context structure.
8036 * @param argc Standard main() style argc.
8037 * @param argv Standard main() style argv. Initial components are already
8038 * stripped.
8040 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
8042 struct functable func[] = {
8044 "list",
8045 rpc_printer_list,
8046 NET_TRANSPORT_RPC,
8047 N_("List all printers on print server"),
8048 N_("net rpc printer list\n"
8049 " List all printers on print server")
8052 "migrate",
8053 rpc_printer_migrate,
8054 NET_TRANSPORT_RPC,
8055 N_("Migrate printer to local server"),
8056 N_("net rpc printer migrate\n"
8057 " Migrate printer to local server")
8060 "driver",
8061 rpc_printer_driver_list,
8062 NET_TRANSPORT_RPC,
8063 N_("List printer drivers"),
8064 N_("net rpc printer driver\n"
8065 " List printer drivers")
8068 "publish",
8069 rpc_printer_publish,
8070 NET_TRANSPORT_RPC,
8071 N_("Publish printer in AD"),
8072 N_("net rpc printer publish\n"
8073 " Publish printer in AD")
8075 {NULL, NULL, 0, NULL, NULL}
8078 if (argc == 0) {
8079 if (c->display_usage) {
8080 d_printf(_("Usage:\n"));
8081 d_printf(_("net rpc printer\n"
8082 " List printers\n"));
8083 net_display_usage_from_functable(func);
8084 return 0;
8086 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
8087 rpc_printer_list_internals,
8088 argc, argv);
8091 return net_run_function(c, argc, argv, "net rpc printer", func);
8095 * 'net rpc' entrypoint.
8097 * @param c A net_context structure.
8098 * @param argc Standard main() style argc.
8099 * @param argv Standard main() style argv. Initial components are already
8100 * stripped.
8103 int net_rpc(struct net_context *c, int argc, const char **argv)
8105 NET_API_STATUS status;
8107 struct functable func[] = {
8109 "audit",
8110 net_rpc_audit,
8111 NET_TRANSPORT_RPC,
8112 N_("Modify global audit settings"),
8113 N_("net rpc audit\n"
8114 " Modify global audit settings")
8117 "info",
8118 net_rpc_info,
8119 NET_TRANSPORT_RPC,
8120 N_("Show basic info about a domain"),
8121 N_("net rpc info\n"
8122 " Show basic info about a domain")
8125 "join",
8126 net_rpc_join,
8127 NET_TRANSPORT_RPC,
8128 N_("Join a domain"),
8129 N_("net rpc join\n"
8130 " Join a domain")
8133 "oldjoin",
8134 net_rpc_oldjoin,
8135 NET_TRANSPORT_RPC,
8136 N_("Join a domain created in server manager"),
8137 N_("net rpc oldjoin\n"
8138 " Join a domain created in server manager")
8141 "testjoin",
8142 net_rpc_testjoin,
8143 NET_TRANSPORT_RPC,
8144 N_("Test that a join is valid"),
8145 N_("net rpc testjoin\n"
8146 " Test that a join is valid")
8149 "user",
8150 net_rpc_user,
8151 NET_TRANSPORT_RPC,
8152 N_("List/modify users"),
8153 N_("net rpc user\n"
8154 " List/modify users")
8157 "password",
8158 rpc_user_password,
8159 NET_TRANSPORT_RPC,
8160 N_("Change a user password"),
8161 N_("net rpc password\n"
8162 " Change a user password\n"
8163 " Alias for net rpc user password")
8166 "group",
8167 net_rpc_group,
8168 NET_TRANSPORT_RPC,
8169 N_("List/modify groups"),
8170 N_("net rpc group\n"
8171 " List/modify groups")
8174 "share",
8175 net_rpc_share,
8176 NET_TRANSPORT_RPC,
8177 N_("List/modify shares"),
8178 N_("net rpc share\n"
8179 " List/modify shares")
8182 "file",
8183 net_rpc_file,
8184 NET_TRANSPORT_RPC,
8185 N_("List open files"),
8186 N_("net rpc file\n"
8187 " List open files")
8190 "printer",
8191 net_rpc_printer,
8192 NET_TRANSPORT_RPC,
8193 N_("List/modify printers"),
8194 N_("net rpc printer\n"
8195 " List/modify printers")
8198 "changetrustpw",
8199 net_rpc_changetrustpw,
8200 NET_TRANSPORT_RPC,
8201 N_("Change trust account password"),
8202 N_("net rpc changetrustpw\n"
8203 " Change trust account password")
8206 "trustdom",
8207 rpc_trustdom,
8208 NET_TRANSPORT_RPC,
8209 N_("Modify domain trusts"),
8210 N_("net rpc trustdom\n"
8211 " Modify domain trusts")
8214 "abortshutdown",
8215 rpc_shutdown_abort,
8216 NET_TRANSPORT_RPC,
8217 N_("Abort a remote shutdown"),
8218 N_("net rpc abortshutdown\n"
8219 " Abort a remote shutdown")
8222 "shutdown",
8223 rpc_shutdown,
8224 NET_TRANSPORT_RPC,
8225 N_("Shutdown a remote server"),
8226 N_("net rpc shutdown\n"
8227 " Shutdown a remote server")
8230 "samdump",
8231 rpc_samdump,
8232 NET_TRANSPORT_RPC,
8233 N_("Dump SAM data of remote NT PDC"),
8234 N_("net rpc samdump\n"
8235 " Dump SAM data of remote NT PDC")
8238 "vampire",
8239 rpc_vampire,
8240 NET_TRANSPORT_RPC,
8241 N_("Sync a remote NT PDC's data into local passdb"),
8242 N_("net rpc vampire\n"
8243 " Sync a remote NT PDC's data into local passdb")
8246 "getsid",
8247 net_rpc_getsid,
8248 NET_TRANSPORT_RPC,
8249 N_("Fetch the domain sid into local secrets.tdb"),
8250 N_("net rpc getsid\n"
8251 " Fetch the domain sid into local secrets.tdb")
8254 "rights",
8255 net_rpc_rights,
8256 NET_TRANSPORT_RPC,
8257 N_("Manage privileges assigned to SID"),
8258 N_("net rpc rights\n"
8259 " Manage privileges assigned to SID")
8262 "service",
8263 net_rpc_service,
8264 NET_TRANSPORT_RPC,
8265 N_("Start/stop/query remote services"),
8266 N_("net rpc service\n"
8267 " Start/stop/query remote services")
8270 "registry",
8271 net_rpc_registry,
8272 NET_TRANSPORT_RPC,
8273 N_("Manage registry hives"),
8274 N_("net rpc registry\n"
8275 " Manage registry hives")
8278 "shell",
8279 net_rpc_shell,
8280 NET_TRANSPORT_RPC,
8281 N_("Open interactive shell on remote server"),
8282 N_("net rpc shell\n"
8283 " Open interactive shell on remote server")
8286 "trust",
8287 net_rpc_trust,
8288 NET_TRANSPORT_RPC,
8289 N_("Manage trusts"),
8290 N_("net rpc trust\n"
8291 " Manage trusts")
8294 "conf",
8295 net_rpc_conf,
8296 NET_TRANSPORT_RPC,
8297 N_("Configure a remote samba server"),
8298 N_("net rpc conf\n"
8299 " Configure a remote samba server")
8301 {NULL, NULL, 0, NULL, NULL}
8304 status = libnetapi_net_init(&c->netapi_ctx);
8305 if (status != 0) {
8306 return -1;
8308 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
8309 libnetapi_set_password(c->netapi_ctx, c->opt_password);
8310 if (c->opt_kerberos) {
8311 libnetapi_set_use_kerberos(c->netapi_ctx);
8313 if (c->opt_ccache) {
8314 libnetapi_set_use_ccache(c->netapi_ctx);
8317 return net_run_function(c, argc, argv, "net rpc", func);