wafsamba: remove unused variable from copy_and_fix_python_path
[Samba.git] / source3 / utils / net_rpc.c
blobc5c4d6c2931c7a43bfe92958730f9732db9a8dec
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 "rpc_client/init_lsa.h"
41 #include "../libcli/security/security.h"
42 #include "libsmb/libsmb.h"
43 #include "libsmb/clirap.h"
44 #include "nsswitch/libwbclient/wbclient.h"
45 #include "passdb.h"
46 #include "../libcli/smb/smbXcli_base.h"
48 static int net_mode_share;
49 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
51 /**
52 * @file net_rpc.c
54 * @brief RPC based subcommands for the 'net' utility.
56 * This file should contain much of the functionality that used to
57 * be found in rpcclient, execpt that the commands should change
58 * less often, and the fucntionality should be sane (the user is not
59 * expected to know a rid/sid before they conduct an operation etc.)
61 * @todo Perhaps eventually these should be split out into a number
62 * of files, as this could get quite big.
63 **/
66 /**
67 * Many of the RPC functions need the domain sid. This function gets
68 * it at the start of every run
70 * @param cli A cli_state already connected to the remote machine
72 * @return The Domain SID of the remote machine.
73 **/
75 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
76 struct dom_sid **domain_sid,
77 const char **domain_name)
79 struct rpc_pipe_client *lsa_pipe = NULL;
80 struct policy_handle pol;
81 NTSTATUS status, result;
82 union lsa_PolicyInformation *info = NULL;
83 struct dcerpc_binding_handle *b;
85 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
86 &lsa_pipe);
87 if (!NT_STATUS_IS_OK(status)) {
88 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
89 return status;
92 b = lsa_pipe->binding_handle;
94 status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
95 SEC_FLAG_MAXIMUM_ALLOWED,
96 &pol);
97 if (!NT_STATUS_IS_OK(status)) {
98 d_fprintf(stderr, "open_policy %s: %s\n",
99 _("failed"),
100 nt_errstr(status));
101 return status;
104 status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
105 &pol,
106 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
107 &info,
108 &result);
109 if (!NT_STATUS_IS_OK(status)) {
110 d_fprintf(stderr, "lsaquery %s: %s\n",
111 _("failed"),
112 nt_errstr(status));
113 return status;
115 if (!NT_STATUS_IS_OK(result)) {
116 d_fprintf(stderr, "lsaquery %s: %s\n",
117 _("failed"),
118 nt_errstr(result));
119 return result;
122 *domain_name = info->account_domain.name.string;
123 *domain_sid = info->account_domain.sid;
125 dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
126 TALLOC_FREE(lsa_pipe);
128 return NT_STATUS_OK;
132 * Run a single RPC command, from start to finish.
134 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
135 * @param conn_flag a NET_FLAG_ combination. Passed to
136 * net_make_ipc_connection.
137 * @param argc Standard main() style argc.
138 * @param argv Standard main() style argv. Initial components are already
139 * stripped.
140 * @return A shell status integer (0 for success).
143 int run_rpc_command(struct net_context *c,
144 struct cli_state *cli_arg,
145 const struct ndr_interface_table *table,
146 int conn_flags,
147 rpc_command_fn fn,
148 int argc,
149 const char **argv)
151 struct cli_state *cli = NULL;
152 struct rpc_pipe_client *pipe_hnd = NULL;
153 TALLOC_CTX *mem_ctx;
154 NTSTATUS nt_status;
155 struct dom_sid *domain_sid;
156 const char *domain_name;
157 int ret = -1;
159 /* make use of cli_state handed over as an argument, if possible */
160 if (!cli_arg) {
161 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
162 if (!NT_STATUS_IS_OK(nt_status)) {
163 DEBUG(1, ("failed to make ipc connection: %s\n",
164 nt_errstr(nt_status)));
165 return -1;
167 } else {
168 cli = cli_arg;
171 if (!cli) {
172 return -1;
175 /* Create mem_ctx */
177 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
178 DEBUG(0, ("talloc_init() failed\n"));
179 goto fail;
182 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
183 &domain_name);
184 if (!NT_STATUS_IS_OK(nt_status)) {
185 goto fail;
188 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
189 if (lp_client_schannel()
190 && (ndr_syntax_id_equal(&table->syntax_id,
191 &ndr_table_netlogon.syntax_id))) {
192 /* Always try and create an schannel netlogon pipe. */
193 nt_status = cli_rpc_pipe_open_schannel(
194 cli, &table->syntax_id, NCACN_NP,
195 DCERPC_AUTH_LEVEL_PRIVACY, domain_name,
196 &pipe_hnd);
197 if (!NT_STATUS_IS_OK(nt_status)) {
198 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
199 nt_errstr(nt_status) ));
200 goto fail;
202 } else {
203 if (conn_flags & NET_FLAGS_SEAL) {
204 nt_status = cli_rpc_pipe_open_generic_auth(
205 cli, table,
206 (conn_flags & NET_FLAGS_TCP) ?
207 NCACN_IP_TCP : NCACN_NP,
208 DCERPC_AUTH_TYPE_NTLMSSP,
209 DCERPC_AUTH_LEVEL_PRIVACY,
210 smbXcli_conn_remote_name(cli->conn),
211 lp_workgroup(), c->opt_user_name,
212 c->opt_password, &pipe_hnd);
213 } else {
214 nt_status = cli_rpc_pipe_open_noauth(
215 cli, &table->syntax_id,
216 &pipe_hnd);
218 if (!NT_STATUS_IS_OK(nt_status)) {
219 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
220 table->name,
221 nt_errstr(nt_status) ));
222 goto fail;
227 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
229 if (!NT_STATUS_IS_OK(nt_status)) {
230 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
231 } else {
232 ret = 0;
233 DEBUG(5, ("rpc command function succedded\n"));
236 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
237 if (pipe_hnd) {
238 TALLOC_FREE(pipe_hnd);
242 fail:
243 /* close the connection only if it was opened here */
244 if (!cli_arg) {
245 cli_shutdown(cli);
248 talloc_destroy(mem_ctx);
249 return ret;
253 * Force a change of the trust acccount password.
255 * All parameters are provided by the run_rpc_command function, except for
256 * argc, argv which are passed through.
258 * @param domain_sid The domain sid acquired from the remote server.
259 * @param cli A cli_state connected to the server.
260 * @param mem_ctx Talloc context, destroyed on completion of the function.
261 * @param argc Standard main() style argc.
262 * @param argv Standard main() style argv. Initial components are already
263 * stripped.
265 * @return Normal NTSTATUS return.
268 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
269 const struct dom_sid *domain_sid,
270 const char *domain_name,
271 struct cli_state *cli,
272 struct rpc_pipe_client *pipe_hnd,
273 TALLOC_CTX *mem_ctx,
274 int argc,
275 const char **argv)
277 NTSTATUS status;
279 status = trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
280 if (!NT_STATUS_IS_OK(status)) {
281 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
282 nt_errstr(status));
283 return status;
286 return NT_STATUS_OK;
290 * Force a change of the trust acccount password.
292 * @param argc Standard main() style argc.
293 * @param argv Standard main() style argv. Initial components are already
294 * stripped.
296 * @return A shell status integer (0 for success).
299 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
301 if (c->display_usage) {
302 d_printf( "%s\n"
303 "net rpc changetrustpw\n"
304 " %s\n",
305 _("Usage:"),
306 _("Change the machine trust password"));
307 return 0;
310 return run_rpc_command(c, NULL, &ndr_table_netlogon,
311 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
312 rpc_changetrustpw_internals,
313 argc, argv);
317 * Join a domain, the old way.
319 * This uses 'machinename' as the inital password, and changes it.
321 * The password should be created with 'server manager' or equiv first.
323 * All parameters are provided by the run_rpc_command function, except for
324 * argc, argv which are passed through.
326 * @param domain_sid The domain sid acquired from the remote server.
327 * @param cli A cli_state connected to the server.
328 * @param mem_ctx Talloc context, destroyed on completion of the function.
329 * @param argc Standard main() style argc.
330 * @param argv Standard main() style argv. Initial components are already
331 * stripped.
333 * @return Normal NTSTATUS return.
336 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
337 const struct dom_sid *domain_sid,
338 const char *domain_name,
339 struct cli_state *cli,
340 struct rpc_pipe_client *pipe_hnd,
341 TALLOC_CTX *mem_ctx,
342 int argc,
343 const char **argv)
346 fstring trust_passwd;
347 unsigned char orig_trust_passwd_hash[16];
348 NTSTATUS result;
349 enum netr_SchannelType sec_channel_type;
351 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
352 &pipe_hnd);
353 if (!NT_STATUS_IS_OK(result)) {
354 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
355 "error was %s\n",
356 smbXcli_conn_remote_name(cli->conn),
357 nt_errstr(result) ));
358 return result;
362 check what type of join - if the user want's to join as
363 a BDC, the server must agree that we are a BDC.
365 if (argc >= 0) {
366 sec_channel_type = get_sec_channel_type(argv[0]);
367 } else {
368 sec_channel_type = get_sec_channel_type(NULL);
371 fstrcpy(trust_passwd, lp_netbios_name());
372 if (!strlower_m(trust_passwd)) {
373 return NT_STATUS_UNSUCCESSFUL;
377 * Machine names can be 15 characters, but the max length on
378 * a password is 14. --jerry
381 trust_passwd[14] = '\0';
383 E_md4hash(trust_passwd, orig_trust_passwd_hash);
385 result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
386 lp_netbios_name(),
387 orig_trust_passwd_hash,
388 sec_channel_type);
390 if (NT_STATUS_IS_OK(result))
391 printf(_("Joined domain %s.\n"), c->opt_target_workgroup);
394 if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
395 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
396 result = NT_STATUS_UNSUCCESSFUL;
399 return result;
403 * Join a domain, the old way.
405 * @param argc Standard main() style argc.
406 * @param argv Standard main() style argv. Initial components are already
407 * stripped.
409 * @return A shell status integer (0 for success).
412 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
414 return run_rpc_command(c, NULL, &ndr_table_netlogon,
415 NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
416 rpc_oldjoin_internals,
417 argc, argv);
421 * Join a domain, the old way. This function exists to allow
422 * the message to be displayed when oldjoin was explicitly
423 * requested, but not when it was implied by "net rpc join".
425 * @param argc Standard main() style argc.
426 * @param argv Standard main() style argv. Initial components are already
427 * stripped.
429 * @return A shell status integer (0 for success).
432 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
434 int rc = -1;
436 if (c->display_usage) {
437 d_printf( "%s\n"
438 "net rpc oldjoin\n"
439 " %s\n",
440 _("Usage:"),
441 _("Join a domain the old way"));
442 return 0;
445 rc = net_rpc_perform_oldjoin(c, argc, argv);
447 if (rc) {
448 d_fprintf(stderr, _("Failed to join domain\n"));
451 return rc;
455 * 'net rpc join' entrypoint.
456 * @param argc Standard main() style argc.
457 * @param argv Standard main() style argv. Initial components are already
458 * stripped
460 * Main 'net_rpc_join()' (where the admin username/password is used) is
461 * in net_rpc_join.c.
462 * Try to just change the password, but if that doesn't work, use/prompt
463 * for a username/password.
466 int net_rpc_join(struct net_context *c, int argc, const char **argv)
468 if (c->display_usage) {
469 d_printf("%s\n%s",
470 _("Usage:"),
471 _("net rpc join -U <username>[%%password] <type>\n"
472 " Join a domain\n"
473 " username\tName of the admin user"
474 " password\tPassword of the admin user, will "
475 "prompt if not specified\n"
476 " type\tCan be one of the following:\n"
477 "\t\tMEMBER\tJoin as member server (default)\n"
478 "\t\tBDC\tJoin as BDC\n"
479 "\t\tPDC\tJoin as PDC\n"));
480 return 0;
483 if (lp_server_role() == ROLE_STANDALONE) {
484 d_printf(_("cannot join as standalone machine\n"));
485 return -1;
488 if (strlen(lp_netbios_name()) > 15) {
489 d_printf(_("Our netbios name can be at most 15 chars long, "
490 "\"%s\" is %u chars long\n"),
491 lp_netbios_name(), (unsigned int)strlen(lp_netbios_name()));
492 return -1;
495 if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
496 return 0;
498 return net_rpc_join_newstyle(c, argc, argv);
502 * display info about a rpc domain
504 * All parameters are provided by the run_rpc_command function, except for
505 * argc, argv which are passed through.
507 * @param domain_sid The domain sid acquired from the remote server
508 * @param cli A cli_state connected to the server.
509 * @param mem_ctx Talloc context, destroyed on completion of the function.
510 * @param argc Standard main() style argc.
511 * @param argv Standard main() style argv. Initial components are already
512 * stripped.
514 * @return Normal NTSTATUS return.
517 NTSTATUS rpc_info_internals(struct net_context *c,
518 const struct dom_sid *domain_sid,
519 const char *domain_name,
520 struct cli_state *cli,
521 struct rpc_pipe_client *pipe_hnd,
522 TALLOC_CTX *mem_ctx,
523 int argc,
524 const char **argv)
526 struct policy_handle connect_pol, domain_pol;
527 NTSTATUS status, result;
528 union samr_DomainInfo *info = NULL;
529 fstring sid_str;
530 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
532 sid_to_fstring(sid_str, domain_sid);
534 /* Get sam policy handle */
535 status = dcerpc_samr_Connect2(b, mem_ctx,
536 pipe_hnd->desthost,
537 MAXIMUM_ALLOWED_ACCESS,
538 &connect_pol,
539 &result);
540 if (!NT_STATUS_IS_OK(status)) {
541 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
542 nt_errstr(status));
543 goto done;
546 if (!NT_STATUS_IS_OK(result)) {
547 status = result;
548 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
549 nt_errstr(result));
550 goto done;
553 /* Get domain policy handle */
554 status = dcerpc_samr_OpenDomain(b, mem_ctx,
555 &connect_pol,
556 MAXIMUM_ALLOWED_ACCESS,
557 discard_const_p(struct dom_sid2, domain_sid),
558 &domain_pol,
559 &result);
560 if (!NT_STATUS_IS_OK(status)) {
561 d_fprintf(stderr, _("Could not open domain: %s\n"),
562 nt_errstr(status));
563 goto done;
565 if (!NT_STATUS_IS_OK(result)) {
566 status = result;
567 d_fprintf(stderr, _("Could not open domain: %s\n"),
568 nt_errstr(result));
569 goto done;
572 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
573 &domain_pol,
575 &info,
576 &result);
577 if (!NT_STATUS_IS_OK(status)) {
578 goto done;
580 status = result;
581 if (NT_STATUS_IS_OK(result)) {
582 d_printf(_("Domain Name: %s\n"),
583 info->general.domain_name.string);
584 d_printf(_("Domain SID: %s\n"), sid_str);
585 d_printf(_("Sequence number: %llu\n"),
586 (unsigned long long)info->general.sequence_num);
587 d_printf(_("Num users: %u\n"), info->general.num_users);
588 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
589 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
592 done:
593 return status;
597 * 'net rpc info' entrypoint.
598 * @param argc Standard main() style argc.
599 * @param argv Standard main() style argv. Initial components are already
600 * stripped.
603 int net_rpc_info(struct net_context *c, int argc, const char **argv)
605 if (c->display_usage) {
606 d_printf( "%s\n"
607 "net rpc info\n"
608 " %s\n",
609 _("Usage:"),
610 _("Display information about the domain"));
611 return 0;
614 return run_rpc_command(c, NULL, &ndr_table_samr,
615 NET_FLAGS_PDC, rpc_info_internals,
616 argc, argv);
620 * Fetch domain SID into the local secrets.tdb.
622 * All parameters are provided by the run_rpc_command function, except for
623 * argc, argv which are passed through.
625 * @param domain_sid The domain sid acquired from the remote server.
626 * @param cli A cli_state connected to the server.
627 * @param mem_ctx Talloc context, destroyed on completion of the function.
628 * @param argc Standard main() style argc.
629 * @param argv Standard main() style argv. Initial components are already
630 * stripped.
632 * @return Normal NTSTATUS return.
635 static NTSTATUS rpc_getsid_internals(struct net_context *c,
636 const struct dom_sid *domain_sid,
637 const char *domain_name,
638 struct cli_state *cli,
639 struct rpc_pipe_client *pipe_hnd,
640 TALLOC_CTX *mem_ctx,
641 int argc,
642 const char **argv)
644 fstring sid_str;
646 sid_to_fstring(sid_str, domain_sid);
647 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
648 sid_str, domain_name);
650 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
651 DEBUG(0,("Can't store domain SID\n"));
652 return NT_STATUS_UNSUCCESSFUL;
655 return NT_STATUS_OK;
659 * 'net rpc getsid' entrypoint.
660 * @param argc Standard main() style argc.
661 * @param argv Standard main() style argv. Initial components are already
662 * stripped.
665 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
667 int conn_flags = NET_FLAGS_PDC;
669 if (!c->opt_user_specified) {
670 conn_flags |= NET_FLAGS_ANONYMOUS;
673 if (c->display_usage) {
674 d_printf( "%s\n"
675 "net rpc getsid\n"
676 " %s\n",
677 _("Usage:"),
678 _("Fetch domain SID into local secrets.tdb"));
679 return 0;
682 return run_rpc_command(c, NULL, &ndr_table_samr,
683 conn_flags,
684 rpc_getsid_internals,
685 argc, argv);
688 /****************************************************************************/
691 * Basic usage function for 'net rpc user'.
692 * @param argc Standard main() style argc.
693 * @param argv Standard main() style argv. Initial components are already
694 * stripped.
697 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
699 return net_user_usage(c, argc, argv);
703 * Add a new user to a remote RPC server.
705 * @param argc Standard main() style argc.
706 * @param argv Standard main() style argv. Initial components are already
707 * stripped.
709 * @return A shell status integer (0 for success).
712 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
714 NET_API_STATUS status;
715 struct USER_INFO_1 info1;
716 uint32_t parm_error = 0;
718 if (argc < 1 || c->display_usage) {
719 rpc_user_usage(c, argc, argv);
720 return 0;
723 ZERO_STRUCT(info1);
725 info1.usri1_name = argv[0];
726 if (argc == 2) {
727 info1.usri1_password = argv[1];
730 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
732 if (status != 0) {
733 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
734 argv[0], libnetapi_get_error_string(c->netapi_ctx,
735 status));
736 return -1;
737 } else {
738 d_printf(_("Added user '%s'.\n"), argv[0]);
741 return 0;
745 * Rename a user on a remote RPC server.
747 * @param argc Standard main() style argc.
748 * @param argv Standard main() style argv. Initial components are already
749 * stripped.
751 * @return A shell status integer (0 for success).
754 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
756 NET_API_STATUS status;
757 struct USER_INFO_0 u0;
758 uint32_t parm_err = 0;
760 if (argc != 2 || c->display_usage) {
761 rpc_user_usage(c, argc, argv);
762 return 0;
765 u0.usri0_name = argv[1];
767 status = NetUserSetInfo(c->opt_host, argv[0],
768 0, (uint8_t *)&u0, &parm_err);
769 if (status) {
770 d_fprintf(stderr,
771 _("Failed to rename user from %s to %s - %s\n"),
772 argv[0], argv[1],
773 libnetapi_get_error_string(c->netapi_ctx, status));
774 } else {
775 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
778 return status;
782 * Set a user's primary group
784 * @param argc Standard main() style argc.
785 * @param argv Standard main() style argv. Initial components are already
786 * stripped.
788 * @return A shell status integer (0 for success).
791 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
792 const char **argv)
794 NET_API_STATUS status;
795 uint8_t *buffer;
796 struct GROUP_INFO_2 *g2;
797 struct USER_INFO_1051 u1051;
798 uint32_t parm_err = 0;
800 if (argc != 2 || c->display_usage) {
801 rpc_user_usage(c, argc, argv);
802 return 0;
805 status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
806 if (status) {
807 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
808 argv[1],
809 libnetapi_get_error_string(c->netapi_ctx, status));
810 return status;
812 g2 = (struct GROUP_INFO_2 *)buffer;
814 u1051.usri1051_primary_group_id = g2->grpi2_group_id;
816 NetApiBufferFree(buffer);
818 status = NetUserSetInfo(c->opt_host, argv[0], 1051,
819 (uint8_t *)&u1051, &parm_err);
820 if (status) {
821 d_fprintf(stderr,
822 _("Failed to set user's primary group %s to %s - "
823 "%s\n"), argv[0], argv[1],
824 libnetapi_get_error_string(c->netapi_ctx, status));
825 } else {
826 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
827 argv[1]);
829 return status;
833 * Delete a user from a remote RPC server.
835 * @param argc Standard main() style argc.
836 * @param argv Standard main() style argv. Initial components are already
837 * stripped.
839 * @return A shell status integer (0 for success).
842 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
844 NET_API_STATUS status;
846 if (argc < 1 || c->display_usage) {
847 rpc_user_usage(c, argc, argv);
848 return 0;
851 status = NetUserDel(c->opt_host, argv[0]);
853 if (status != 0) {
854 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
855 argv[0],
856 libnetapi_get_error_string(c->netapi_ctx, status));
857 return -1;
858 } else {
859 d_printf(_("Deleted user '%s'.\n"), argv[0]);
862 return 0;
866 * Set a user's password on a remote RPC server.
868 * @param argc Standard main() style argc.
869 * @param argv Standard main() style argv. Initial components are already
870 * stripped.
872 * @return A shell status integer (0 for success).
875 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
877 NET_API_STATUS status;
878 char *prompt = NULL;
879 struct USER_INFO_1003 u1003;
880 uint32_t parm_err = 0;
881 int ret;
883 if (argc < 1 || c->display_usage) {
884 rpc_user_usage(c, argc, argv);
885 return 0;
888 if (argv[1]) {
889 u1003.usri1003_password = argv[1];
890 } else {
891 char pwd[256] = {0};
892 ret = asprintf(&prompt, _("Enter new password for %s:"),
893 argv[0]);
894 if (ret == -1) {
895 return -1;
898 ret = samba_getpass(prompt, pwd, sizeof(pwd), false, false);
899 SAFE_FREE(prompt);
900 if (ret < 0) {
901 return -1;
904 u1003.usri1003_password = talloc_strdup(c, pwd);
905 if (u1003.usri1003_password == NULL) {
906 return -1;
910 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
912 /* Display results */
913 if (status != 0) {
914 d_fprintf(stderr,
915 _("Failed to set password for '%s' with error: %s.\n"),
916 argv[0], libnetapi_get_error_string(c->netapi_ctx,
917 status));
918 return -1;
921 return 0;
925 * List a user's groups from a remote RPC server.
927 * @param argc Standard main() style argc.
928 * @param argv Standard main() style argv. Initial components are already
929 * stripped.
931 * @return A shell status integer (0 for success)
934 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
937 NET_API_STATUS status;
938 struct GROUP_USERS_INFO_0 *u0 = NULL;
939 uint32_t entries_read = 0;
940 uint32_t total_entries = 0;
941 int i;
944 if (argc < 1 || c->display_usage) {
945 rpc_user_usage(c, argc, argv);
946 return 0;
949 status = NetUserGetGroups(c->opt_host,
950 argv[0],
952 (uint8_t **)(void *)&u0,
953 (uint32_t)-1,
954 &entries_read,
955 &total_entries);
956 if (status != 0) {
957 d_fprintf(stderr,
958 _("Failed to get groups for '%s' with error: %s.\n"),
959 argv[0], libnetapi_get_error_string(c->netapi_ctx,
960 status));
961 return -1;
964 for (i=0; i < entries_read; i++) {
965 printf("%s\n", u0->grui0_name);
966 u0++;
969 return 0;
973 * List users on a remote RPC server.
975 * All parameters are provided by the run_rpc_command function, except for
976 * argc, argv which are passed through.
978 * @param domain_sid The domain sid acquired from the remote server.
979 * @param cli A cli_state connected to the server.
980 * @param mem_ctx Talloc context, destroyed on completion of the function.
981 * @param argc Standard main() style argc.
982 * @param argv Standard main() style argv. Initial components are already
983 * stripped.
985 * @return Normal NTSTATUS return.
988 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
990 NET_API_STATUS status;
991 uint32_t start_idx=0, num_entries, i, loop_count = 0;
992 struct NET_DISPLAY_USER *info = NULL;
993 void *buffer = NULL;
995 /* Query domain users */
996 if (c->opt_long_list_entries)
997 d_printf(_("\nUser name Comment"
998 "\n-----------------------------\n"));
999 do {
1000 uint32_t max_entries, max_size;
1002 dcerpc_get_query_dispinfo_params(
1003 loop_count, &max_entries, &max_size);
1005 status = NetQueryDisplayInformation(c->opt_host,
1007 start_idx,
1008 max_entries,
1009 max_size,
1010 &num_entries,
1011 &buffer);
1012 if (status != 0 && status != ERROR_MORE_DATA) {
1013 return status;
1016 info = (struct NET_DISPLAY_USER *)buffer;
1018 for (i = 0; i < num_entries; i++) {
1020 if (c->opt_long_list_entries)
1021 printf("%-21.21s %s\n", info->usri1_name,
1022 info->usri1_comment);
1023 else
1024 printf("%s\n", info->usri1_name);
1025 info++;
1028 NetApiBufferFree(buffer);
1030 loop_count++;
1031 start_idx += num_entries;
1033 } while (status == ERROR_MORE_DATA);
1035 return status;
1039 * 'net rpc user' entrypoint.
1040 * @param argc Standard main() style argc.
1041 * @param argv Standard main() style argv. Initial components are already
1042 * stripped.
1045 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1047 NET_API_STATUS status;
1049 struct functable func[] = {
1051 "add",
1052 rpc_user_add,
1053 NET_TRANSPORT_RPC,
1054 N_("Add specified user"),
1055 N_("net rpc user add\n"
1056 " Add specified user")
1059 "info",
1060 rpc_user_info,
1061 NET_TRANSPORT_RPC,
1062 N_("List domain groups of user"),
1063 N_("net rpc user info\n"
1064 " List domain groups of user")
1067 "delete",
1068 rpc_user_delete,
1069 NET_TRANSPORT_RPC,
1070 N_("Remove specified user"),
1071 N_("net rpc user delete\n"
1072 " Remove specified user")
1075 "password",
1076 rpc_user_password,
1077 NET_TRANSPORT_RPC,
1078 N_("Change user password"),
1079 N_("net rpc user password\n"
1080 " Change user password")
1083 "rename",
1084 rpc_user_rename,
1085 NET_TRANSPORT_RPC,
1086 N_("Rename specified user"),
1087 N_("net rpc user rename\n"
1088 " Rename specified user")
1091 "setprimarygroup",
1092 rpc_user_setprimarygroup,
1093 NET_TRANSPORT_RPC,
1094 "Set a user's primary group",
1095 "net rpc user setprimarygroup\n"
1096 " Set a user's primary group"
1098 {NULL, NULL, 0, NULL, NULL}
1101 status = libnetapi_net_init(&c->netapi_ctx);
1102 if (status != 0) {
1103 return -1;
1105 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1106 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1107 if (c->opt_kerberos) {
1108 libnetapi_set_use_kerberos(c->netapi_ctx);
1111 if (argc == 0) {
1112 if (c->display_usage) {
1113 d_printf( "%s\n"
1114 "net rpc user\n"
1115 " %s\n",
1116 _("Usage:"),
1117 _("List all users"));
1118 net_display_usage_from_functable(func);
1119 return 0;
1122 return rpc_user_list(c, argc, argv);
1125 return net_run_function(c, argc, argv, "net rpc user", func);
1128 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1129 TALLOC_CTX *mem_ctx,
1130 struct rpc_sh_ctx *ctx,
1131 struct rpc_pipe_client *pipe_hnd,
1132 int argc, const char **argv)
1134 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1137 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1138 TALLOC_CTX *mem_ctx,
1139 struct rpc_sh_ctx *ctx,
1140 struct rpc_pipe_client *pipe_hnd,
1141 int argc, const char **argv)
1143 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1146 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1147 TALLOC_CTX *mem_ctx,
1148 struct rpc_sh_ctx *ctx,
1149 struct rpc_pipe_client *pipe_hnd,
1150 int argc, const char **argv,
1151 NTSTATUS (*fn)(
1152 struct net_context *c,
1153 TALLOC_CTX *mem_ctx,
1154 struct rpc_sh_ctx *ctx,
1155 struct rpc_pipe_client *pipe_hnd,
1156 struct policy_handle *user_hnd,
1157 int argc, const char **argv))
1159 struct policy_handle connect_pol, domain_pol, user_pol;
1160 NTSTATUS status, result;
1161 struct dom_sid sid;
1162 uint32 rid;
1163 enum lsa_SidType type;
1164 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1166 if (argc == 0) {
1167 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1168 ctx->whoami);
1169 return NT_STATUS_INVALID_PARAMETER;
1172 ZERO_STRUCT(connect_pol);
1173 ZERO_STRUCT(domain_pol);
1174 ZERO_STRUCT(user_pol);
1176 status = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1177 argv[0], NULL, NULL, &sid, &type);
1178 if (!NT_STATUS_IS_OK(status)) {
1179 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1180 nt_errstr(status));
1181 goto done;
1184 if (type != SID_NAME_USER) {
1185 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1186 sid_type_lookup(type));
1187 status = NT_STATUS_NO_SUCH_USER;
1188 goto done;
1191 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1192 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1193 status = NT_STATUS_NO_SUCH_USER;
1194 goto done;
1197 status = dcerpc_samr_Connect2(b, mem_ctx,
1198 pipe_hnd->desthost,
1199 MAXIMUM_ALLOWED_ACCESS,
1200 &connect_pol,
1201 &result);
1202 if (!NT_STATUS_IS_OK(status)) {
1203 goto done;
1205 if (!NT_STATUS_IS_OK(result)) {
1206 status = result;
1207 goto done;
1210 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1211 &connect_pol,
1212 MAXIMUM_ALLOWED_ACCESS,
1213 ctx->domain_sid,
1214 &domain_pol,
1215 &result);
1216 if (!NT_STATUS_IS_OK(status)) {
1217 goto done;
1219 if (!NT_STATUS_IS_OK(result)) {
1220 status = result;
1221 goto done;
1224 status = dcerpc_samr_OpenUser(b, mem_ctx,
1225 &domain_pol,
1226 MAXIMUM_ALLOWED_ACCESS,
1227 rid,
1228 &user_pol,
1229 &result);
1230 if (!NT_STATUS_IS_OK(status)) {
1231 goto done;
1233 if (!NT_STATUS_IS_OK(result)) {
1234 status = result;
1235 goto done;
1238 status = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1240 done:
1241 if (is_valid_policy_hnd(&user_pol)) {
1242 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1244 if (is_valid_policy_hnd(&domain_pol)) {
1245 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1247 if (is_valid_policy_hnd(&connect_pol)) {
1248 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
1250 return status;
1253 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1254 TALLOC_CTX *mem_ctx,
1255 struct rpc_sh_ctx *ctx,
1256 struct rpc_pipe_client *pipe_hnd,
1257 struct policy_handle *user_hnd,
1258 int argc, const char **argv)
1260 NTSTATUS status, result;
1261 union samr_UserInfo *info = NULL;
1262 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1264 if (argc != 0) {
1265 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1266 ctx->whoami);
1267 return NT_STATUS_INVALID_PARAMETER;
1270 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1271 user_hnd,
1273 &info,
1274 &result);
1275 if (!NT_STATUS_IS_OK(status)) {
1276 return status;
1278 if (!NT_STATUS_IS_OK(result)) {
1279 return result;
1282 d_printf(_("user rid: %d, group rid: %d\n"),
1283 info->info21.rid,
1284 info->info21.primary_gid);
1286 return result;
1289 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1290 TALLOC_CTX *mem_ctx,
1291 struct rpc_sh_ctx *ctx,
1292 struct rpc_pipe_client *pipe_hnd,
1293 int argc, const char **argv)
1295 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1296 rpc_sh_user_show_internals);
1299 #define FETCHSTR(name, rec) \
1300 do { if (strequal(ctx->thiscmd, name)) { \
1301 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1302 } while (0);
1304 #define SETSTR(name, rec, flag) \
1305 do { if (strequal(ctx->thiscmd, name)) { \
1306 init_lsa_String(&(info->info21.rec), argv[0]); \
1307 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1308 } while (0);
1310 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1311 TALLOC_CTX *mem_ctx,
1312 struct rpc_sh_ctx *ctx,
1313 struct rpc_pipe_client *pipe_hnd,
1314 struct policy_handle *user_hnd,
1315 int argc, const char **argv)
1317 NTSTATUS status, result;
1318 const char *username;
1319 const char *oldval = "";
1320 union samr_UserInfo *info = NULL;
1321 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1323 if (argc > 1) {
1324 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1325 _("Usage:"), ctx->whoami);
1326 return NT_STATUS_INVALID_PARAMETER;
1329 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1330 user_hnd,
1332 &info,
1333 &result);
1334 if (!NT_STATUS_IS_OK(status)) {
1335 return status;
1337 if (!NT_STATUS_IS_OK(result)) {
1338 return result;
1341 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1343 FETCHSTR("fullname", full_name);
1344 FETCHSTR("homedir", home_directory);
1345 FETCHSTR("homedrive", home_drive);
1346 FETCHSTR("logonscript", logon_script);
1347 FETCHSTR("profilepath", profile_path);
1348 FETCHSTR("description", description);
1350 if (argc == 0) {
1351 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1352 goto done;
1355 if (strcmp(argv[0], "NULL") == 0) {
1356 argv[0] = "";
1359 ZERO_STRUCT(info->info21);
1361 SETSTR("fullname", full_name, FULL_NAME);
1362 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1363 SETSTR("homedrive", home_drive, HOME_DRIVE);
1364 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1365 SETSTR("profilepath", profile_path, PROFILE_PATH);
1366 SETSTR("description", description, DESCRIPTION);
1368 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1369 user_hnd,
1371 info,
1372 &result);
1373 if (!NT_STATUS_IS_OK(status)) {
1374 return status;
1377 status = result;
1379 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1380 ctx->thiscmd, oldval, argv[0]);
1382 done:
1384 return status;
1387 #define HANDLEFLG(name, rec) \
1388 do { if (strequal(ctx->thiscmd, name)) { \
1389 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1390 if (newval) { \
1391 newflags = oldflags | ACB_##rec; \
1392 } else { \
1393 newflags = oldflags & ~ACB_##rec; \
1394 } } } while (0);
1396 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1397 TALLOC_CTX *mem_ctx,
1398 struct rpc_sh_ctx *ctx,
1399 struct rpc_pipe_client *pipe_hnd,
1400 int argc, const char **argv)
1402 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1403 rpc_sh_user_str_edit_internals);
1406 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1407 TALLOC_CTX *mem_ctx,
1408 struct rpc_sh_ctx *ctx,
1409 struct rpc_pipe_client *pipe_hnd,
1410 struct policy_handle *user_hnd,
1411 int argc, const char **argv)
1413 NTSTATUS status, result;
1414 const char *username;
1415 const char *oldval = "unknown";
1416 uint32 oldflags, newflags;
1417 bool newval;
1418 union samr_UserInfo *info = NULL;
1419 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1421 if ((argc > 1) ||
1422 ((argc == 1) && !strequal(argv[0], "yes") &&
1423 !strequal(argv[0], "no"))) {
1424 /* TRANSATORS: The yes|no here are program keywords. Please do
1425 not translate. */
1426 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1427 ctx->whoami);
1428 return NT_STATUS_INVALID_PARAMETER;
1431 newval = strequal(argv[0], "yes");
1433 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1434 user_hnd,
1436 &info,
1437 &result);
1438 if (!NT_STATUS_IS_OK(status)) {
1439 return status;
1441 if (!NT_STATUS_IS_OK(result)) {
1442 return result;
1445 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1446 oldflags = info->info21.acct_flags;
1447 newflags = info->info21.acct_flags;
1449 HANDLEFLG("disabled", DISABLED);
1450 HANDLEFLG("pwnotreq", PWNOTREQ);
1451 HANDLEFLG("autolock", AUTOLOCK);
1452 HANDLEFLG("pwnoexp", PWNOEXP);
1454 if (argc == 0) {
1455 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1456 oldval);
1457 goto done;
1460 ZERO_STRUCT(info->info21);
1462 info->info21.acct_flags = newflags;
1463 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1465 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1466 user_hnd,
1468 info,
1469 &result);
1470 if (!NT_STATUS_IS_OK(status)) {
1471 goto done;
1473 status = result;
1474 if (NT_STATUS_IS_OK(result)) {
1475 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1476 ctx->thiscmd, oldval, argv[0]);
1479 done:
1481 return status;
1484 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1485 TALLOC_CTX *mem_ctx,
1486 struct rpc_sh_ctx *ctx,
1487 struct rpc_pipe_client *pipe_hnd,
1488 int argc, const char **argv)
1490 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1491 rpc_sh_user_flag_edit_internals);
1494 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1495 TALLOC_CTX *mem_ctx,
1496 struct rpc_sh_ctx *ctx)
1498 static struct rpc_sh_cmd cmds[] = {
1500 { "fullname", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1501 N_("Show/Set a user's full name") },
1503 { "homedir", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1504 N_("Show/Set a user's home directory") },
1506 { "homedrive", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1507 N_("Show/Set a user's home drive") },
1509 { "logonscript", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1510 N_("Show/Set a user's logon script") },
1512 { "profilepath", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1513 N_("Show/Set a user's profile path") },
1515 { "description", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1516 N_("Show/Set a user's description") },
1518 { "disabled", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1519 N_("Show/Set whether a user is disabled") },
1521 { "autolock", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1522 N_("Show/Set whether a user locked out") },
1524 { "pwnotreq", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1525 N_("Show/Set whether a user does not need a password") },
1527 { "pwnoexp", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1528 N_("Show/Set whether a user's password does not expire") },
1530 { NULL, NULL, 0, NULL, NULL }
1533 return cmds;
1536 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1537 TALLOC_CTX *mem_ctx,
1538 struct rpc_sh_ctx *ctx)
1540 static struct rpc_sh_cmd cmds[] = {
1542 { "list", NULL, &ndr_table_samr, rpc_sh_user_list,
1543 N_("List available users") },
1545 { "info", NULL, &ndr_table_samr, rpc_sh_user_info,
1546 N_("List the domain groups a user is member of") },
1548 { "show", NULL, &ndr_table_samr, rpc_sh_user_show,
1549 N_("Show info about a user") },
1551 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1552 N_("Show/Modify a user's fields") },
1554 { NULL, NULL, 0, NULL, NULL }
1557 return cmds;
1560 /****************************************************************************/
1563 * Basic usage function for 'net rpc group'.
1564 * @param argc Standard main() style argc.
1565 * @param argv Standard main() style argv. Initial components are already
1566 * stripped.
1569 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1571 return net_group_usage(c, argc, argv);
1575 * Delete group on a remote RPC server.
1577 * All parameters are provided by the run_rpc_command function, except for
1578 * argc, argv which are passed through.
1580 * @param domain_sid The domain sid acquired from the remote server.
1581 * @param cli A cli_state connected to the server.
1582 * @param mem_ctx Talloc context, destroyed on completion of the function.
1583 * @param argc Standard main() style argc.
1584 * @param argv Standard main() style argv. Initial components are already
1585 * stripped.
1587 * @return Normal NTSTATUS return.
1590 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1591 const struct dom_sid *domain_sid,
1592 const char *domain_name,
1593 struct cli_state *cli,
1594 struct rpc_pipe_client *pipe_hnd,
1595 TALLOC_CTX *mem_ctx,
1596 int argc,
1597 const char **argv)
1599 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1600 bool group_is_primary = false;
1601 NTSTATUS status, result;
1602 uint32_t group_rid;
1603 struct samr_RidAttrArray *rids = NULL;
1604 /* char **names; */
1605 int i;
1606 /* struct samr_RidWithAttribute *user_gids; */
1607 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1609 struct samr_Ids group_rids, name_types;
1610 struct lsa_String lsa_acct_name;
1611 union samr_UserInfo *info = NULL;
1613 if (argc < 1 || c->display_usage) {
1614 rpc_group_usage(c, argc,argv);
1615 return NT_STATUS_OK; /* ok? */
1618 status = dcerpc_samr_Connect2(b, mem_ctx,
1619 pipe_hnd->desthost,
1620 MAXIMUM_ALLOWED_ACCESS,
1621 &connect_pol,
1622 &result);
1623 if (!NT_STATUS_IS_OK(status)) {
1624 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1625 goto done;
1628 if (!NT_STATUS_IS_OK(result)) {
1629 status = result;
1630 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1631 goto done;
1634 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1635 &connect_pol,
1636 MAXIMUM_ALLOWED_ACCESS,
1637 discard_const_p(struct dom_sid2, domain_sid),
1638 &domain_pol,
1639 &result);
1640 if (!NT_STATUS_IS_OK(status)) {
1641 d_fprintf(stderr, _("Request open_domain failed\n"));
1642 goto done;
1645 if (!NT_STATUS_IS_OK(result)) {
1646 status = result;
1647 d_fprintf(stderr, _("Request open_domain failed\n"));
1648 goto done;
1651 init_lsa_String(&lsa_acct_name, argv[0]);
1653 status = dcerpc_samr_LookupNames(b, mem_ctx,
1654 &domain_pol,
1656 &lsa_acct_name,
1657 &group_rids,
1658 &name_types,
1659 &result);
1660 if (!NT_STATUS_IS_OK(status)) {
1661 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1662 goto done;
1665 if (!NT_STATUS_IS_OK(result)) {
1666 status = result;
1667 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1668 goto done;
1670 if (group_rids.count != 1) {
1671 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1672 goto done;
1674 if (name_types.count != 1) {
1675 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1676 goto done;
1679 switch (name_types.ids[0])
1681 case SID_NAME_DOM_GRP:
1682 status = dcerpc_samr_OpenGroup(b, mem_ctx,
1683 &domain_pol,
1684 MAXIMUM_ALLOWED_ACCESS,
1685 group_rids.ids[0],
1686 &group_pol,
1687 &result);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 d_fprintf(stderr, _("Request open_group failed"));
1690 goto done;
1693 if (!NT_STATUS_IS_OK(result)) {
1694 status = result;
1695 d_fprintf(stderr, _("Request open_group failed"));
1696 goto done;
1699 group_rid = group_rids.ids[0];
1701 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
1702 &group_pol,
1703 &rids,
1704 &result);
1705 if (!NT_STATUS_IS_OK(status)) {
1706 d_fprintf(stderr,
1707 _("Unable to query group members of %s"),
1708 argv[0]);
1709 goto done;
1712 if (!NT_STATUS_IS_OK(result)) {
1713 status = result;
1714 d_fprintf(stderr,
1715 _("Unable to query group members of %s"),
1716 argv[0]);
1717 goto done;
1720 if (c->opt_verbose) {
1721 d_printf(
1722 _("Domain Group %s (rid: %d) has %d members\n"),
1723 argv[0],group_rid, rids->count);
1726 /* Check if group is anyone's primary group */
1727 for (i = 0; i < rids->count; i++)
1729 status = dcerpc_samr_OpenUser(b, mem_ctx,
1730 &domain_pol,
1731 MAXIMUM_ALLOWED_ACCESS,
1732 rids->rids[i],
1733 &user_pol,
1734 &result);
1735 if (!NT_STATUS_IS_OK(status)) {
1736 d_fprintf(stderr,
1737 _("Unable to open group member %d\n"),
1738 rids->rids[i]);
1739 goto done;
1742 if (!NT_STATUS_IS_OK(result)) {
1743 status = result;
1744 d_fprintf(stderr,
1745 _("Unable to open group member %d\n"),
1746 rids->rids[i]);
1747 goto done;
1750 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1751 &user_pol,
1753 &info,
1754 &result);
1755 if (!NT_STATUS_IS_OK(status)) {
1756 d_fprintf(stderr,
1757 _("Unable to lookup userinfo for group "
1758 "member %d\n"),
1759 rids->rids[i]);
1760 goto done;
1763 if (!NT_STATUS_IS_OK(result)) {
1764 status = result;
1765 d_fprintf(stderr,
1766 _("Unable to lookup userinfo for group "
1767 "member %d\n"),
1768 rids->rids[i]);
1769 goto done;
1772 if (info->info21.primary_gid == group_rid) {
1773 if (c->opt_verbose) {
1774 d_printf(_("Group is primary group "
1775 "of %s\n"),
1776 info->info21.account_name.string);
1778 group_is_primary = true;
1781 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1784 if (group_is_primary) {
1785 d_fprintf(stderr, _("Unable to delete group because "
1786 "some of it's members have it as primary "
1787 "group\n"));
1788 status = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1789 goto done;
1792 /* remove all group members */
1793 for (i = 0; i < rids->count; i++)
1795 if (c->opt_verbose)
1796 d_printf(_("Remove group member %d..."),
1797 rids->rids[i]);
1798 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
1799 &group_pol,
1800 rids->rids[i],
1801 &result);
1802 if (!NT_STATUS_IS_OK(status)) {
1803 goto done;
1805 status = result;
1806 if (NT_STATUS_IS_OK(result)) {
1807 if (c->opt_verbose)
1808 d_printf(_("ok\n"));
1809 } else {
1810 if (c->opt_verbose)
1811 d_printf("%s\n", _("failed"));
1812 goto done;
1816 status = dcerpc_samr_DeleteDomainGroup(b, mem_ctx,
1817 &group_pol,
1818 &result);
1819 if (!NT_STATUS_IS_OK(status)) {
1820 break;
1823 status = result;
1825 break;
1826 /* removing a local group is easier... */
1827 case SID_NAME_ALIAS:
1828 status = dcerpc_samr_OpenAlias(b, mem_ctx,
1829 &domain_pol,
1830 MAXIMUM_ALLOWED_ACCESS,
1831 group_rids.ids[0],
1832 &group_pol,
1833 &result);
1834 if (!NT_STATUS_IS_OK(status)) {
1835 d_fprintf(stderr, _("Request open_alias failed\n"));
1836 goto done;
1838 if (!NT_STATUS_IS_OK(result)) {
1839 status = result;
1840 d_fprintf(stderr, _("Request open_alias failed\n"));
1841 goto done;
1844 status = dcerpc_samr_DeleteDomAlias(b, mem_ctx,
1845 &group_pol,
1846 &result);
1847 if (!NT_STATUS_IS_OK(status)) {
1848 break;
1851 status = result;
1853 break;
1854 default:
1855 d_fprintf(stderr, _("%s is of type %s. This command is only "
1856 "for deleting local or global groups\n"),
1857 argv[0],sid_type_lookup(name_types.ids[0]));
1858 status = NT_STATUS_UNSUCCESSFUL;
1859 goto done;
1862 if (NT_STATUS_IS_OK(status)) {
1863 if (c->opt_verbose)
1864 d_printf(_("Deleted %s '%s'\n"),
1865 sid_type_lookup(name_types.ids[0]), argv[0]);
1866 } else {
1867 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
1868 get_friendly_nt_error_msg(status));
1871 done:
1872 return status;
1876 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1878 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
1879 rpc_group_delete_internals, argc,argv);
1882 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1884 NET_API_STATUS status;
1885 struct GROUP_INFO_1 info1;
1886 uint32_t parm_error = 0;
1888 if (argc != 1 || c->display_usage) {
1889 rpc_group_usage(c, argc, argv);
1890 return 0;
1893 ZERO_STRUCT(info1);
1895 info1.grpi1_name = argv[0];
1896 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1897 info1.grpi1_comment = c->opt_comment;
1900 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1902 if (status != 0) {
1903 d_fprintf(stderr,
1904 _("Failed to add group '%s' with error: %s.\n"),
1905 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1906 status));
1907 return -1;
1908 } else {
1909 d_printf(_("Added group '%s'.\n"), argv[0]);
1912 return 0;
1915 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
1917 NET_API_STATUS status;
1918 struct LOCALGROUP_INFO_1 info1;
1919 uint32_t parm_error = 0;
1921 if (argc != 1 || c->display_usage) {
1922 rpc_group_usage(c, argc, argv);
1923 return 0;
1926 ZERO_STRUCT(info1);
1928 info1.lgrpi1_name = argv[0];
1929 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1930 info1.lgrpi1_comment = c->opt_comment;
1933 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1935 if (status != 0) {
1936 d_fprintf(stderr,
1937 _("Failed to add alias '%s' with error: %s.\n"),
1938 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1939 status));
1940 return -1;
1941 } else {
1942 d_printf(_("Added alias '%s'.\n"), argv[0]);
1945 return 0;
1948 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1950 if (c->opt_localgroup)
1951 return rpc_alias_add_internals(c, argc, argv);
1953 return rpc_group_add_internals(c, argc, argv);
1956 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1957 TALLOC_CTX *mem_ctx,
1958 const char *name,
1959 struct dom_sid *sid,
1960 enum lsa_SidType *type)
1962 struct dom_sid *sids = NULL;
1963 enum lsa_SidType *types = NULL;
1964 struct rpc_pipe_client *pipe_hnd = NULL;
1965 struct policy_handle lsa_pol;
1966 NTSTATUS status, result;
1967 struct dcerpc_binding_handle *b;
1969 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1970 &pipe_hnd);
1971 if (!NT_STATUS_IS_OK(status)) {
1972 goto done;
1975 b = pipe_hnd->binding_handle;
1977 status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1978 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1980 if (!NT_STATUS_IS_OK(status)) {
1981 goto done;
1984 status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1985 &name, NULL, 1, &sids, &types);
1987 if (NT_STATUS_IS_OK(status)) {
1988 sid_copy(sid, &sids[0]);
1989 *type = types[0];
1992 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
1994 done:
1995 if (pipe_hnd) {
1996 TALLOC_FREE(pipe_hnd);
1999 if (!NT_STATUS_IS_OK(status) && (strncasecmp_m(name, "S-", 2) == 0)) {
2001 /* Try as S-1-5-whatever */
2003 struct dom_sid tmp_sid;
2005 if (string_to_sid(&tmp_sid, name)) {
2006 sid_copy(sid, &tmp_sid);
2007 *type = SID_NAME_UNKNOWN;
2008 status = NT_STATUS_OK;
2012 return status;
2015 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
2016 TALLOC_CTX *mem_ctx,
2017 const struct dom_sid *group_sid,
2018 const char *member)
2020 struct policy_handle connect_pol, domain_pol;
2021 NTSTATUS status, result;
2022 uint32 group_rid;
2023 struct policy_handle group_pol;
2024 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2026 struct samr_Ids rids, rid_types;
2027 struct lsa_String lsa_acct_name;
2029 struct dom_sid sid;
2031 sid_copy(&sid, group_sid);
2033 if (!sid_split_rid(&sid, &group_rid)) {
2034 return NT_STATUS_UNSUCCESSFUL;
2037 /* Get sam policy handle */
2038 status = dcerpc_samr_Connect2(b, mem_ctx,
2039 pipe_hnd->desthost,
2040 MAXIMUM_ALLOWED_ACCESS,
2041 &connect_pol,
2042 &result);
2043 if (!NT_STATUS_IS_OK(status)) {
2044 return status;
2046 if (!NT_STATUS_IS_OK(result)) {
2047 return result;
2050 /* Get domain policy handle */
2051 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2052 &connect_pol,
2053 MAXIMUM_ALLOWED_ACCESS,
2054 &sid,
2055 &domain_pol,
2056 &result);
2057 if (!NT_STATUS_IS_OK(status)) {
2058 return status;
2060 if (!NT_STATUS_IS_OK(result)) {
2061 return result;
2064 init_lsa_String(&lsa_acct_name, member);
2066 status = dcerpc_samr_LookupNames(b, mem_ctx,
2067 &domain_pol,
2069 &lsa_acct_name,
2070 &rids,
2071 &rid_types,
2072 &result);
2073 if (!NT_STATUS_IS_OK(status)) {
2074 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2075 member);
2076 goto done;
2079 if (!NT_STATUS_IS_OK(result)) {
2080 status = result;
2081 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2082 member);
2083 goto done;
2085 if (rids.count != 1) {
2086 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2087 goto done;
2089 if (rid_types.count != 1) {
2090 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2091 goto done;
2094 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2095 &domain_pol,
2096 MAXIMUM_ALLOWED_ACCESS,
2097 group_rid,
2098 &group_pol,
2099 &result);
2100 if (!NT_STATUS_IS_OK(status)) {
2101 goto done;
2104 if (!NT_STATUS_IS_OK(result)) {
2105 status = result;
2106 goto done;
2109 status = dcerpc_samr_AddGroupMember(b, mem_ctx,
2110 &group_pol,
2111 rids.ids[0],
2112 0x0005, /* unknown flags */
2113 &result);
2114 if (!NT_STATUS_IS_OK(status)) {
2115 goto done;
2118 status = result;
2120 done:
2121 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2122 return status;
2125 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2126 TALLOC_CTX *mem_ctx,
2127 const struct dom_sid *alias_sid,
2128 const char *member)
2130 struct policy_handle connect_pol, domain_pol;
2131 NTSTATUS status, result;
2132 uint32 alias_rid;
2133 struct policy_handle alias_pol;
2134 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2136 struct dom_sid member_sid;
2137 enum lsa_SidType member_type;
2139 struct dom_sid sid;
2141 sid_copy(&sid, alias_sid);
2143 if (!sid_split_rid(&sid, &alias_rid)) {
2144 return NT_STATUS_UNSUCCESSFUL;
2147 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2148 member, &member_sid, &member_type);
2150 if (!NT_STATUS_IS_OK(result)) {
2151 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2152 member);
2153 return result;
2156 /* Get sam policy handle */
2157 status = dcerpc_samr_Connect2(b, mem_ctx,
2158 pipe_hnd->desthost,
2159 MAXIMUM_ALLOWED_ACCESS,
2160 &connect_pol,
2161 &result);
2162 if (!NT_STATUS_IS_OK(status)) {
2163 goto done;
2165 if (!NT_STATUS_IS_OK(result)) {
2166 status = result;
2167 goto done;
2170 /* Get domain policy handle */
2171 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2172 &connect_pol,
2173 MAXIMUM_ALLOWED_ACCESS,
2174 &sid,
2175 &domain_pol,
2176 &result);
2177 if (!NT_STATUS_IS_OK(status)) {
2178 goto done;
2180 if (!NT_STATUS_IS_OK(result)) {
2181 status = result;
2182 goto done;
2185 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2186 &domain_pol,
2187 MAXIMUM_ALLOWED_ACCESS,
2188 alias_rid,
2189 &alias_pol,
2190 &result);
2191 if (!NT_STATUS_IS_OK(status)) {
2192 return status;
2194 if (!NT_STATUS_IS_OK(result)) {
2195 return result;
2198 status = dcerpc_samr_AddAliasMember(b, mem_ctx,
2199 &alias_pol,
2200 &member_sid,
2201 &result);
2202 if (!NT_STATUS_IS_OK(status)) {
2203 return status;
2206 status = result;
2208 done:
2209 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2210 return status;
2213 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2214 const struct dom_sid *domain_sid,
2215 const char *domain_name,
2216 struct cli_state *cli,
2217 struct rpc_pipe_client *pipe_hnd,
2218 TALLOC_CTX *mem_ctx,
2219 int argc,
2220 const char **argv)
2222 struct dom_sid group_sid;
2223 enum lsa_SidType group_type;
2225 if (argc != 2 || c->display_usage) {
2226 d_printf("%s\n%s",
2227 _("Usage:"),
2228 _("net rpc group addmem <group> <member>\n"
2229 " Add a member to a group\n"
2230 " group\tGroup to add member to\n"
2231 " member\tMember to add to group\n"));
2232 return NT_STATUS_UNSUCCESSFUL;
2235 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2236 &group_sid, &group_type))) {
2237 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2238 argv[0]);
2239 return NT_STATUS_UNSUCCESSFUL;
2242 if (group_type == SID_NAME_DOM_GRP) {
2243 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2244 &group_sid, argv[1]);
2246 if (!NT_STATUS_IS_OK(result)) {
2247 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2248 argv[1], argv[0], nt_errstr(result));
2250 return result;
2253 if (group_type == SID_NAME_ALIAS) {
2254 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2255 &group_sid, argv[1]);
2257 if (!NT_STATUS_IS_OK(result)) {
2258 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2259 argv[1], argv[0], nt_errstr(result));
2261 return result;
2264 d_fprintf(stderr, _("Can only add members to global or local groups "
2265 "which %s is not\n"), argv[0]);
2267 return NT_STATUS_UNSUCCESSFUL;
2270 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2272 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2273 rpc_group_addmem_internals,
2274 argc, argv);
2277 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2278 struct rpc_pipe_client *pipe_hnd,
2279 TALLOC_CTX *mem_ctx,
2280 const struct dom_sid *group_sid,
2281 const char *member)
2283 struct policy_handle connect_pol, domain_pol;
2284 NTSTATUS status, result;
2285 uint32 group_rid;
2286 struct policy_handle group_pol;
2287 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2289 struct samr_Ids rids, rid_types;
2290 struct lsa_String lsa_acct_name;
2292 struct dom_sid sid;
2294 sid_copy(&sid, group_sid);
2296 if (!sid_split_rid(&sid, &group_rid))
2297 return NT_STATUS_UNSUCCESSFUL;
2299 /* Get sam policy handle */
2300 status = dcerpc_samr_Connect2(b, mem_ctx,
2301 pipe_hnd->desthost,
2302 MAXIMUM_ALLOWED_ACCESS,
2303 &connect_pol,
2304 &result);
2305 if (!NT_STATUS_IS_OK(status)) {
2306 return status;
2308 if (!NT_STATUS_IS_OK(result)) {
2309 return result;
2313 /* Get domain policy handle */
2314 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2315 &connect_pol,
2316 MAXIMUM_ALLOWED_ACCESS,
2317 &sid,
2318 &domain_pol,
2319 &result);
2320 if (!NT_STATUS_IS_OK(status)) {
2321 return status;
2323 if (!NT_STATUS_IS_OK(result)) {
2324 return result;
2327 init_lsa_String(&lsa_acct_name, member);
2329 status = dcerpc_samr_LookupNames(b, mem_ctx,
2330 &domain_pol,
2332 &lsa_acct_name,
2333 &rids,
2334 &rid_types,
2335 &result);
2336 if (!NT_STATUS_IS_OK(status)) {
2337 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2338 member);
2339 goto done;
2342 if (!NT_STATUS_IS_OK(result)) {
2343 status = result;
2344 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2345 member);
2346 goto done;
2348 if (rids.count != 1) {
2349 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2350 goto done;
2352 if (rid_types.count != 1) {
2353 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2354 goto done;
2357 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2358 &domain_pol,
2359 MAXIMUM_ALLOWED_ACCESS,
2360 group_rid,
2361 &group_pol,
2362 &result);
2363 if (!NT_STATUS_IS_OK(status)) {
2364 goto done;
2366 if (!NT_STATUS_IS_OK(result)) {
2367 status = result;
2368 goto done;
2371 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2372 &group_pol,
2373 rids.ids[0],
2374 &result);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 goto done;
2379 status = result;
2380 done:
2381 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2382 return status;
2385 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2386 TALLOC_CTX *mem_ctx,
2387 const struct dom_sid *alias_sid,
2388 const char *member)
2390 struct policy_handle connect_pol, domain_pol;
2391 NTSTATUS status, result;
2392 uint32 alias_rid;
2393 struct policy_handle alias_pol;
2394 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2396 struct dom_sid member_sid;
2397 enum lsa_SidType member_type;
2399 struct dom_sid sid;
2401 sid_copy(&sid, alias_sid);
2403 if (!sid_split_rid(&sid, &alias_rid))
2404 return NT_STATUS_UNSUCCESSFUL;
2406 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2407 member, &member_sid, &member_type);
2409 if (!NT_STATUS_IS_OK(result)) {
2410 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2411 member);
2412 return result;
2415 /* Get sam policy handle */
2416 status = dcerpc_samr_Connect2(b, mem_ctx,
2417 pipe_hnd->desthost,
2418 MAXIMUM_ALLOWED_ACCESS,
2419 &connect_pol,
2420 &result);
2421 if (!NT_STATUS_IS_OK(status)) {
2422 goto done;
2424 if (!NT_STATUS_IS_OK(result)) {
2425 status = result;
2426 goto done;
2429 /* Get domain policy handle */
2430 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2431 &connect_pol,
2432 MAXIMUM_ALLOWED_ACCESS,
2433 &sid,
2434 &domain_pol,
2435 &result);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 goto done;
2439 if (!NT_STATUS_IS_OK(result)) {
2440 status = result;
2441 goto done;
2444 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2445 &domain_pol,
2446 MAXIMUM_ALLOWED_ACCESS,
2447 alias_rid,
2448 &alias_pol,
2449 &result);
2450 if (!NT_STATUS_IS_OK(status)) {
2451 return status;
2454 if (!NT_STATUS_IS_OK(result)) {
2455 return result;
2458 status = dcerpc_samr_DeleteAliasMember(b, mem_ctx,
2459 &alias_pol,
2460 &member_sid,
2461 &result);
2463 if (!NT_STATUS_IS_OK(status)) {
2464 return status;
2467 status = result;
2469 done:
2470 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2471 return status;
2474 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2475 const struct dom_sid *domain_sid,
2476 const char *domain_name,
2477 struct cli_state *cli,
2478 struct rpc_pipe_client *pipe_hnd,
2479 TALLOC_CTX *mem_ctx,
2480 int argc,
2481 const char **argv)
2483 struct dom_sid group_sid;
2484 enum lsa_SidType group_type;
2486 if (argc != 2 || c->display_usage) {
2487 d_printf("%s\n%s",
2488 _("Usage:"),
2489 _("net rpc group delmem <group> <member>\n"
2490 " Delete a member from a group\n"
2491 " group\tGroup to delete member from\n"
2492 " member\tMember to delete from group\n"));
2493 return NT_STATUS_UNSUCCESSFUL;
2496 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2497 &group_sid, &group_type))) {
2498 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2499 argv[0]);
2500 return NT_STATUS_UNSUCCESSFUL;
2503 if (group_type == SID_NAME_DOM_GRP) {
2504 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2505 &group_sid, argv[1]);
2507 if (!NT_STATUS_IS_OK(result)) {
2508 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2509 argv[1], argv[0], nt_errstr(result));
2511 return result;
2514 if (group_type == SID_NAME_ALIAS) {
2515 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2516 &group_sid, argv[1]);
2518 if (!NT_STATUS_IS_OK(result)) {
2519 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2520 argv[1], argv[0], nt_errstr(result));
2522 return result;
2525 d_fprintf(stderr, _("Can only delete members from global or local "
2526 "groups which %s is not\n"), argv[0]);
2528 return NT_STATUS_UNSUCCESSFUL;
2531 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2533 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2534 rpc_group_delmem_internals,
2535 argc, argv);
2539 * List groups on a remote RPC server.
2541 * All parameters are provided by the run_rpc_command function, except for
2542 * argc, argv which are passes through.
2544 * @param domain_sid The domain sid acquired from the remote server.
2545 * @param cli A cli_state connected to the server.
2546 * @param mem_ctx Talloc context, destroyed on completion of the function.
2547 * @param argc Standard main() style argc.
2548 * @param argv Standard main() style argv. Initial components are already
2549 * stripped.
2551 * @return Normal NTSTATUS return.
2554 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2555 const struct dom_sid *domain_sid,
2556 const char *domain_name,
2557 struct cli_state *cli,
2558 struct rpc_pipe_client *pipe_hnd,
2559 TALLOC_CTX *mem_ctx,
2560 int argc,
2561 const char **argv)
2563 struct policy_handle connect_pol, domain_pol;
2564 NTSTATUS status, result;
2565 uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2566 struct samr_SamArray *groups = NULL;
2567 bool global = false;
2568 bool local = false;
2569 bool builtin = false;
2570 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2572 if (c->display_usage) {
2573 d_printf("%s\n%s",
2574 _("Usage:"),
2575 _("net rpc group list [global] [local] [builtin]\n"
2576 " List groups on RPC server\n"
2577 " global\tList global groups\n"
2578 " local\tList local groups\n"
2579 " builtin\tList builtin groups\n"
2580 " If none of global, local or builtin is "
2581 "specified, all three options are considered "
2582 "set\n"));
2583 return NT_STATUS_OK;
2586 if (argc == 0) {
2587 global = true;
2588 local = true;
2589 builtin = true;
2592 for (i=0; i<argc; i++) {
2593 if (strequal(argv[i], "global"))
2594 global = true;
2596 if (strequal(argv[i], "local"))
2597 local = true;
2599 if (strequal(argv[i], "builtin"))
2600 builtin = true;
2603 /* Get sam policy handle */
2605 status = dcerpc_samr_Connect2(b, mem_ctx,
2606 pipe_hnd->desthost,
2607 MAXIMUM_ALLOWED_ACCESS,
2608 &connect_pol,
2609 &result);
2610 if (!NT_STATUS_IS_OK(status)) {
2611 goto done;
2613 if (!NT_STATUS_IS_OK(result)) {
2614 status = result;
2615 goto done;
2618 /* Get domain policy handle */
2620 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2621 &connect_pol,
2622 MAXIMUM_ALLOWED_ACCESS,
2623 discard_const_p(struct dom_sid2, domain_sid),
2624 &domain_pol,
2625 &result);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 goto done;
2629 if (!NT_STATUS_IS_OK(result)) {
2630 status = result;
2631 goto done;
2634 /* Query domain groups */
2635 if (c->opt_long_list_entries)
2636 d_printf(_("\nGroup name Comment"
2637 "\n-----------------------------\n"));
2638 do {
2639 uint32_t max_size, total_size, returned_size;
2640 union samr_DispInfo info;
2642 if (!global) break;
2644 dcerpc_get_query_dispinfo_params(
2645 loop_count, &max_entries, &max_size);
2647 status = dcerpc_samr_QueryDisplayInfo(b, mem_ctx,
2648 &domain_pol,
2650 start_idx,
2651 max_entries,
2652 max_size,
2653 &total_size,
2654 &returned_size,
2655 &info,
2656 &result);
2657 if (!NT_STATUS_IS_OK(status)) {
2658 goto done;
2660 num_entries = info.info3.count;
2661 start_idx += info.info3.count;
2663 if (!NT_STATUS_IS_OK(result) &&
2664 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2665 break;
2667 for (i = 0; i < num_entries; i++) {
2669 const char *group = NULL;
2670 const char *desc = NULL;
2672 group = info.info3.entries[i].account_name.string;
2673 desc = info.info3.entries[i].description.string;
2675 if (c->opt_long_list_entries)
2676 printf("%-21.21s %-50.50s\n",
2677 group, desc);
2678 else
2679 printf("%s\n", group);
2681 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2682 /* query domain aliases */
2683 start_idx = 0;
2684 do {
2685 if (!local) break;
2687 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2688 &domain_pol,
2689 &start_idx,
2690 &groups,
2691 0xffff,
2692 &num_entries,
2693 &result);
2694 if (!NT_STATUS_IS_OK(status)) {
2695 goto done;
2697 if (!NT_STATUS_IS_OK(result) &&
2698 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2699 break;
2701 for (i = 0; i < num_entries; i++) {
2703 const char *description = NULL;
2705 if (c->opt_long_list_entries) {
2707 struct policy_handle alias_pol;
2708 union samr_AliasInfo *info = NULL;
2709 NTSTATUS _result;
2711 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2712 &domain_pol,
2713 0x8,
2714 groups->entries[i].idx,
2715 &alias_pol,
2716 &_result);
2717 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2718 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2719 &alias_pol,
2721 &info,
2722 &_result);
2723 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2724 status = dcerpc_samr_Close(b, mem_ctx,
2725 &alias_pol,
2726 &_result);
2727 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2728 description = info->description.string;
2734 if (description != NULL) {
2735 printf("%-21.21s %-50.50s\n",
2736 groups->entries[i].name.string,
2737 description);
2738 } else {
2739 printf("%s\n", groups->entries[i].name.string);
2742 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2743 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
2744 /* Get builtin policy handle */
2746 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2747 &connect_pol,
2748 MAXIMUM_ALLOWED_ACCESS,
2749 discard_const_p(struct dom_sid2, &global_sid_Builtin),
2750 &domain_pol,
2751 &result);
2752 if (!NT_STATUS_IS_OK(status)) {
2753 goto done;
2755 if (!NT_STATUS_IS_OK(result)) {
2756 status = result;
2757 goto done;
2760 /* query builtin aliases */
2761 start_idx = 0;
2762 do {
2763 if (!builtin) break;
2765 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2766 &domain_pol,
2767 &start_idx,
2768 &groups,
2769 max_entries,
2770 &num_entries,
2771 &result);
2772 if (!NT_STATUS_IS_OK(status)) {
2773 break;
2775 if (!NT_STATUS_IS_OK(result) &&
2776 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
2777 status = result;
2778 break;
2781 for (i = 0; i < num_entries; i++) {
2783 const char *description = NULL;
2785 if (c->opt_long_list_entries) {
2787 struct policy_handle alias_pol;
2788 union samr_AliasInfo *info = NULL;
2789 NTSTATUS _result;
2791 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2792 &domain_pol,
2793 0x8,
2794 groups->entries[i].idx,
2795 &alias_pol,
2796 &_result);
2797 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2798 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2799 &alias_pol,
2801 &info,
2802 &_result);
2803 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2804 status = dcerpc_samr_Close(b, mem_ctx,
2805 &alias_pol,
2806 &_result);
2807 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2808 description = info->description.string;
2814 if (description != NULL) {
2815 printf("%-21.21s %-50.50s\n",
2816 groups->entries[i].name.string,
2817 description);
2818 } else {
2819 printf("%s\n", groups->entries[i].name.string);
2822 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2824 status = result;
2826 done:
2827 return status;
2830 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2832 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2833 rpc_group_list_internals,
2834 argc, argv);
2837 static NTSTATUS rpc_list_group_members(struct net_context *c,
2838 struct rpc_pipe_client *pipe_hnd,
2839 TALLOC_CTX *mem_ctx,
2840 const char *domain_name,
2841 const struct dom_sid *domain_sid,
2842 struct policy_handle *domain_pol,
2843 uint32 rid)
2845 NTSTATUS result, status;
2846 struct policy_handle group_pol;
2847 uint32 num_members, *group_rids;
2848 int i;
2849 struct samr_RidAttrArray *rids = NULL;
2850 struct lsa_Strings names;
2851 struct samr_Ids types;
2852 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2854 fstring sid_str;
2855 sid_to_fstring(sid_str, domain_sid);
2857 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2858 domain_pol,
2859 MAXIMUM_ALLOWED_ACCESS,
2860 rid,
2861 &group_pol,
2862 &result);
2863 if (!NT_STATUS_IS_OK(status)) {
2864 return status;
2866 if (!NT_STATUS_IS_OK(result)) {
2867 return result;
2870 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
2871 &group_pol,
2872 &rids,
2873 &result);
2874 if (!NT_STATUS_IS_OK(status)) {
2875 return status;
2877 if (!NT_STATUS_IS_OK(result)) {
2878 return result;
2881 num_members = rids->count;
2882 group_rids = rids->rids;
2884 while (num_members > 0) {
2885 int this_time = 512;
2887 if (num_members < this_time)
2888 this_time = num_members;
2890 status = dcerpc_samr_LookupRids(b, mem_ctx,
2891 domain_pol,
2892 this_time,
2893 group_rids,
2894 &names,
2895 &types,
2896 &result);
2897 if (!NT_STATUS_IS_OK(status)) {
2898 return status;
2900 if (!NT_STATUS_IS_OK(result)) {
2901 return result;
2903 if (names.count != this_time) {
2904 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2906 if (types.count != this_time) {
2907 return NT_STATUS_INVALID_NETWORK_RESPONSE;
2909 /* We only have users as members, but make the output
2910 the same as the output of alias members */
2912 for (i = 0; i < this_time; i++) {
2914 if (c->opt_long_list_entries) {
2915 printf("%s-%d %s\\%s %d\n", sid_str,
2916 group_rids[i], domain_name,
2917 names.names[i].string,
2918 SID_NAME_USER);
2919 } else {
2920 printf("%s\\%s\n", domain_name,
2921 names.names[i].string);
2925 num_members -= this_time;
2926 group_rids += 512;
2929 return NT_STATUS_OK;
2932 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2933 struct rpc_pipe_client *pipe_hnd,
2934 TALLOC_CTX *mem_ctx,
2935 struct policy_handle *domain_pol,
2936 uint32 rid)
2938 NTSTATUS result, status;
2939 struct rpc_pipe_client *lsa_pipe;
2940 struct policy_handle alias_pol, lsa_pol;
2941 uint32 num_members;
2942 struct dom_sid *alias_sids;
2943 char **domains;
2944 char **names;
2945 enum lsa_SidType *types;
2946 int i;
2947 struct lsa_SidArray sid_array;
2948 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2950 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2951 domain_pol,
2952 MAXIMUM_ALLOWED_ACCESS,
2953 rid,
2954 &alias_pol,
2955 &result);
2956 if (!NT_STATUS_IS_OK(status)) {
2957 return status;
2959 if (!NT_STATUS_IS_OK(result)) {
2960 return result;
2963 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
2964 &alias_pol,
2965 &sid_array,
2966 &result);
2967 if (!NT_STATUS_IS_OK(status)) {
2968 d_fprintf(stderr, _("Couldn't list alias members\n"));
2969 return status;
2971 if (!NT_STATUS_IS_OK(result)) {
2972 d_fprintf(stderr, _("Couldn't list alias members\n"));
2973 return result;
2976 num_members = sid_array.num_sids;
2978 if (num_members == 0) {
2979 return NT_STATUS_OK;
2982 result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2983 &ndr_table_lsarpc.syntax_id,
2984 &lsa_pipe);
2985 if (!NT_STATUS_IS_OK(result)) {
2986 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
2987 nt_errstr(result) );
2988 return result;
2991 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2992 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2994 if (!NT_STATUS_IS_OK(result)) {
2995 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
2996 TALLOC_FREE(lsa_pipe);
2997 return result;
3000 alias_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
3001 if (!alias_sids) {
3002 d_fprintf(stderr, _("Out of memory\n"));
3003 TALLOC_FREE(lsa_pipe);
3004 return NT_STATUS_NO_MEMORY;
3007 for (i=0; i<num_members; i++) {
3008 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
3011 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
3012 num_members, alias_sids,
3013 &domains, &names, &types);
3015 if (!NT_STATUS_IS_OK(result) &&
3016 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
3017 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
3018 TALLOC_FREE(lsa_pipe);
3019 return result;
3022 for (i = 0; i < num_members; i++) {
3023 fstring sid_str;
3024 sid_to_fstring(sid_str, &alias_sids[i]);
3026 if (c->opt_long_list_entries) {
3027 printf("%s %s\\%s %d\n", sid_str,
3028 domains[i] ? domains[i] : _("*unknown*"),
3029 names[i] ? names[i] : _("*unknown*"), types[i]);
3030 } else {
3031 if (domains[i])
3032 printf("%s\\%s\n", domains[i], names[i]);
3033 else
3034 printf("%s\n", sid_str);
3038 TALLOC_FREE(lsa_pipe);
3039 return NT_STATUS_OK;
3042 static NTSTATUS rpc_group_members_internals(struct net_context *c,
3043 const struct dom_sid *domain_sid,
3044 const char *domain_name,
3045 struct cli_state *cli,
3046 struct rpc_pipe_client *pipe_hnd,
3047 TALLOC_CTX *mem_ctx,
3048 int argc,
3049 const char **argv)
3051 NTSTATUS result, status;
3052 struct policy_handle connect_pol, domain_pol;
3053 struct samr_Ids rids, rid_types;
3054 struct lsa_String lsa_acct_name;
3055 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3057 /* Get sam policy handle */
3059 status = dcerpc_samr_Connect2(b, mem_ctx,
3060 pipe_hnd->desthost,
3061 MAXIMUM_ALLOWED_ACCESS,
3062 &connect_pol,
3063 &result);
3064 if (!NT_STATUS_IS_OK(status)) {
3065 return status;
3067 if (!NT_STATUS_IS_OK(result)) {
3068 return result;
3071 /* Get domain policy handle */
3073 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3074 &connect_pol,
3075 MAXIMUM_ALLOWED_ACCESS,
3076 discard_const_p(struct dom_sid2, domain_sid),
3077 &domain_pol,
3078 &result);
3079 if (!NT_STATUS_IS_OK(status)) {
3080 return status;
3082 if (!NT_STATUS_IS_OK(result)) {
3083 return result;
3086 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
3088 status = dcerpc_samr_LookupNames(b, mem_ctx,
3089 &domain_pol,
3091 &lsa_acct_name,
3092 &rids,
3093 &rid_types,
3094 &result);
3095 if (!NT_STATUS_IS_OK(status)) {
3096 return status;
3099 if (!NT_STATUS_IS_OK(result)) {
3101 /* Ok, did not find it in the global sam, try with builtin */
3103 struct dom_sid sid_Builtin;
3105 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
3107 sid_copy(&sid_Builtin, &global_sid_Builtin);
3109 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3110 &connect_pol,
3111 MAXIMUM_ALLOWED_ACCESS,
3112 &sid_Builtin,
3113 &domain_pol,
3114 &result);
3115 if (!NT_STATUS_IS_OK(status)) {
3116 return status;
3118 if (!NT_STATUS_IS_OK(result)) {
3119 d_fprintf(stderr, _("Couldn't find group %s\n"),
3120 argv[0]);
3121 return result;
3124 status = dcerpc_samr_LookupNames(b, mem_ctx,
3125 &domain_pol,
3127 &lsa_acct_name,
3128 &rids,
3129 &rid_types,
3130 &result);
3131 if (!NT_STATUS_IS_OK(status)) {
3132 return status;
3134 if (!NT_STATUS_IS_OK(result)) {
3135 d_fprintf(stderr, _("Couldn't find group %s\n"),
3136 argv[0]);
3137 return result;
3141 if (rids.count != 1) {
3142 d_fprintf(stderr, _("Couldn't find group %s\n"),
3143 argv[0]);
3144 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3146 if (rid_types.count != 1) {
3147 d_fprintf(stderr, _("Couldn't find group %s\n"),
3148 argv[0]);
3149 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3153 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
3154 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
3155 domain_sid, &domain_pol,
3156 rids.ids[0]);
3159 if (rid_types.ids[0] == SID_NAME_ALIAS) {
3160 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
3161 rids.ids[0]);
3164 return NT_STATUS_NO_SUCH_GROUP;
3167 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
3169 if (argc != 1 || c->display_usage) {
3170 return rpc_group_usage(c, argc, argv);
3173 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3174 rpc_group_members_internals,
3175 argc, argv);
3178 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
3180 NET_API_STATUS status;
3181 struct GROUP_INFO_0 g0;
3182 uint32_t parm_err;
3184 if (argc != 2) {
3185 d_printf(_("Usage:\n"));
3186 d_printf("net rpc group rename group newname\n");
3187 return -1;
3190 g0.grpi0_name = argv[1];
3192 status = NetGroupSetInfo(c->opt_host,
3193 argv[0],
3195 (uint8_t *)&g0,
3196 &parm_err);
3198 if (status != 0) {
3199 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
3200 argv[0], libnetapi_get_error_string(c->netapi_ctx,
3201 status));
3202 return -1;
3205 return 0;
3208 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
3210 if (argc != 2 || c->display_usage) {
3211 return rpc_group_usage(c, argc, argv);
3214 return rpc_group_rename_internals(c, argc, argv);
3218 * 'net rpc group' entrypoint.
3219 * @param argc Standard main() style argc.
3220 * @param argv Standard main() style argv. Initial components are already
3221 * stripped.
3224 int net_rpc_group(struct net_context *c, int argc, const char **argv)
3226 NET_API_STATUS status;
3228 struct functable func[] = {
3230 "add",
3231 rpc_group_add,
3232 NET_TRANSPORT_RPC,
3233 N_("Create specified group"),
3234 N_("net rpc group add\n"
3235 " Create specified group")
3238 "delete",
3239 rpc_group_delete,
3240 NET_TRANSPORT_RPC,
3241 N_("Delete specified group"),
3242 N_("net rpc group delete\n"
3243 " Delete specified group")
3246 "addmem",
3247 rpc_group_addmem,
3248 NET_TRANSPORT_RPC,
3249 N_("Add member to group"),
3250 N_("net rpc group addmem\n"
3251 " Add member to group")
3254 "delmem",
3255 rpc_group_delmem,
3256 NET_TRANSPORT_RPC,
3257 N_("Remove member from group"),
3258 N_("net rpc group delmem\n"
3259 " Remove member from group")
3262 "list",
3263 rpc_group_list,
3264 NET_TRANSPORT_RPC,
3265 N_("List groups"),
3266 N_("net rpc group list\n"
3267 " List groups")
3270 "members",
3271 rpc_group_members,
3272 NET_TRANSPORT_RPC,
3273 N_("List group members"),
3274 N_("net rpc group members\n"
3275 " List group members")
3278 "rename",
3279 rpc_group_rename,
3280 NET_TRANSPORT_RPC,
3281 N_("Rename group"),
3282 N_("net rpc group rename\n"
3283 " Rename group")
3285 {NULL, NULL, 0, NULL, NULL}
3288 status = libnetapi_net_init(&c->netapi_ctx);
3289 if (status != 0) {
3290 return -1;
3292 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
3293 libnetapi_set_password(c->netapi_ctx, c->opt_password);
3294 if (c->opt_kerberos) {
3295 libnetapi_set_use_kerberos(c->netapi_ctx);
3298 if (argc == 0) {
3299 if (c->display_usage) {
3300 d_printf(_("Usage:\n"));
3301 d_printf(_("net rpc group\n"
3302 " Alias for net rpc group list global "
3303 "local builtin\n"));
3304 net_display_usage_from_functable(func);
3305 return 0;
3308 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3309 rpc_group_list_internals,
3310 argc, argv);
3313 return net_run_function(c, argc, argv, "net rpc group", func);
3316 /****************************************************************************/
3318 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
3320 return net_share_usage(c, argc, argv);
3324 * Add a share on a remote RPC server.
3326 * @param argc Standard main() style argc.
3327 * @param argv Standard main() style argv. Initial components are already
3328 * stripped.
3330 * @return A shell status integer (0 for success).
3333 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3335 NET_API_STATUS status;
3336 char *sharename;
3337 char *path;
3338 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3339 uint32 num_users=0, perms=0;
3340 char *password=NULL; /* don't allow a share password */
3341 struct SHARE_INFO_2 i2;
3342 uint32_t parm_error = 0;
3344 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3345 return rpc_share_usage(c, argc, argv);
3348 if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
3349 return -1;
3352 path = strchr(sharename, '=');
3353 if (!path) {
3354 return -1;
3357 *path++ = '\0';
3359 i2.shi2_netname = sharename;
3360 i2.shi2_type = type;
3361 i2.shi2_remark = c->opt_comment;
3362 i2.shi2_permissions = perms;
3363 i2.shi2_max_uses = c->opt_maxusers;
3364 i2.shi2_current_uses = num_users;
3365 i2.shi2_path = path;
3366 i2.shi2_passwd = password;
3368 status = NetShareAdd(c->opt_host,
3370 (uint8_t *)&i2,
3371 &parm_error);
3372 if (status != 0) {
3373 printf(_("NetShareAdd failed with: %s\n"),
3374 libnetapi_get_error_string(c->netapi_ctx, status));
3377 return status;
3381 * Delete a share on a remote RPC server.
3383 * @param domain_sid The domain sid acquired from the remote server.
3384 * @param argc Standard main() style argc.
3385 * @param argv Standard main() style argv. Initial components are already
3386 * stripped.
3388 * @return A shell status integer (0 for success).
3390 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3392 if (argc < 1 || c->display_usage) {
3393 return rpc_share_usage(c, argc, argv);
3396 return NetShareDel(c->opt_host, argv[0], 0);
3400 * Formatted print of share info
3402 * @param r pointer to SHARE_INFO_1 to format
3405 static void display_share_info_1(struct net_context *c,
3406 struct SHARE_INFO_1 *r)
3408 if (c->opt_long_list_entries) {
3409 d_printf("%-12s %-8.8s %-50s\n",
3410 r->shi1_netname,
3411 net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3412 r->shi1_remark);
3413 } else {
3414 d_printf("%s\n", r->shi1_netname);
3418 static WERROR get_share_info(struct net_context *c,
3419 struct rpc_pipe_client *pipe_hnd,
3420 TALLOC_CTX *mem_ctx,
3421 uint32 level,
3422 int argc,
3423 const char **argv,
3424 struct srvsvc_NetShareInfoCtr *info_ctr)
3426 WERROR result;
3427 NTSTATUS status;
3428 union srvsvc_NetShareInfo info;
3429 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3431 /* no specific share requested, enumerate all */
3432 if (argc == 0) {
3434 uint32_t preferred_len = 0xffffffff;
3435 uint32_t total_entries = 0;
3436 uint32_t resume_handle = 0;
3438 info_ctr->level = level;
3440 status = dcerpc_srvsvc_NetShareEnumAll(b, mem_ctx,
3441 pipe_hnd->desthost,
3442 info_ctr,
3443 preferred_len,
3444 &total_entries,
3445 &resume_handle,
3446 &result);
3447 if (!NT_STATUS_IS_OK(status)) {
3448 return ntstatus_to_werror(status);
3450 return result;
3453 /* request just one share */
3454 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
3455 pipe_hnd->desthost,
3456 argv[0],
3457 level,
3458 &info,
3459 &result);
3461 if (!NT_STATUS_IS_OK(status)) {
3462 result = ntstatus_to_werror(status);
3463 goto done;
3466 if (!W_ERROR_IS_OK(result)) {
3467 goto done;
3470 /* construct ctr */
3471 ZERO_STRUCTP(info_ctr);
3473 info_ctr->level = level;
3475 switch (level) {
3476 case 1:
3478 struct srvsvc_NetShareCtr1 *ctr1;
3480 ctr1 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr1);
3481 W_ERROR_HAVE_NO_MEMORY(ctr1);
3483 ctr1->count = 1;
3484 ctr1->array = info.info1;
3486 info_ctr->ctr.ctr1 = ctr1;
3488 break;
3490 case 2:
3492 struct srvsvc_NetShareCtr2 *ctr2;
3494 ctr2 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr2);
3495 W_ERROR_HAVE_NO_MEMORY(ctr2);
3497 ctr2->count = 1;
3498 ctr2->array = info.info2;
3500 info_ctr->ctr.ctr2 = ctr2;
3502 break;
3504 case 502:
3506 struct srvsvc_NetShareCtr502 *ctr502;
3508 ctr502 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr502);
3509 W_ERROR_HAVE_NO_MEMORY(ctr502);
3511 ctr502->count = 1;
3512 ctr502->array = info.info502;
3514 info_ctr->ctr.ctr502 = ctr502;
3516 break;
3518 } /* switch */
3519 done:
3520 return result;
3523 /***
3524 * 'net rpc share list' entrypoint.
3525 * @param argc Standard main() style argc.
3526 * @param argv Standard main() style argv. Initial components are already
3527 * stripped.
3529 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3531 NET_API_STATUS status;
3532 struct SHARE_INFO_1 *i1 = NULL;
3533 uint32_t entries_read = 0;
3534 uint32_t total_entries = 0;
3535 uint32_t resume_handle = 0;
3536 uint32_t i, level = 1;
3538 if (c->display_usage) {
3539 d_printf( "%s\n"
3540 "net rpc share list\n"
3541 " %s\n",
3542 _("Usage:"),
3543 _("List shares on remote server"));
3544 return 0;
3547 status = NetShareEnum(c->opt_host,
3548 level,
3549 (uint8_t **)(void *)&i1,
3550 (uint32_t)-1,
3551 &entries_read,
3552 &total_entries,
3553 &resume_handle);
3554 if (status != 0) {
3555 goto done;
3558 /* Display results */
3560 if (c->opt_long_list_entries) {
3561 d_printf(_(
3562 "\nEnumerating shared resources (exports) on remote server:\n\n"
3563 "\nShare name Type Description\n"
3564 "---------- ---- -----------\n"));
3566 for (i = 0; i < entries_read; i++)
3567 display_share_info_1(c, &i1[i]);
3568 done:
3569 return status;
3572 static bool check_share_availability(struct cli_state *cli, const char *netname)
3574 NTSTATUS status;
3576 status = cli_tree_connect(cli, netname, "A:", "", 0);
3577 if (!NT_STATUS_IS_OK(status)) {
3578 d_printf(_("skipping [%s]: not a file share.\n"), netname);
3579 return false;
3582 status = cli_tdis(cli);
3583 if (!NT_STATUS_IS_OK(status)) {
3584 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3585 return false;
3588 return true;
3591 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3592 const char *netname, uint32 type)
3594 /* only support disk shares */
3595 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3596 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3597 type);
3598 return false;
3601 /* skip builtin shares */
3602 /* FIXME: should print$ be added too ? */
3603 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3604 strequal(netname,"global"))
3605 return false;
3607 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3608 printf(_("excluding [%s]\n"), netname);
3609 return false;
3612 return check_share_availability(cli, netname);
3616 * Migrate shares from a remote RPC server to the local RPC server.
3618 * All parameters are provided by the run_rpc_command function, except for
3619 * argc, argv which are passed through.
3621 * @param domain_sid The domain sid acquired from the remote server.
3622 * @param cli A cli_state connected to the server.
3623 * @param mem_ctx Talloc context, destroyed on completion of the function.
3624 * @param argc Standard main() style argc.
3625 * @param argv Standard main() style argv. Initial components are already
3626 * stripped.
3628 * @return Normal NTSTATUS return.
3631 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3632 const struct dom_sid *domain_sid,
3633 const char *domain_name,
3634 struct cli_state *cli,
3635 struct rpc_pipe_client *pipe_hnd,
3636 TALLOC_CTX *mem_ctx,
3637 int argc,
3638 const char **argv)
3640 WERROR result;
3641 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3642 struct srvsvc_NetShareInfoCtr ctr_src;
3643 uint32 i;
3644 struct rpc_pipe_client *srvsvc_pipe = NULL;
3645 struct cli_state *cli_dst = NULL;
3646 uint32 level = 502; /* includes secdesc */
3647 uint32_t parm_error = 0;
3648 struct dcerpc_binding_handle *b;
3650 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3651 &ctr_src);
3652 if (!W_ERROR_IS_OK(result))
3653 goto done;
3655 /* connect destination PI_SRVSVC */
3656 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3657 &ndr_table_srvsvc.syntax_id);
3658 if (!NT_STATUS_IS_OK(nt_status))
3659 return nt_status;
3661 b = srvsvc_pipe->binding_handle;
3663 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3665 union srvsvc_NetShareInfo info;
3666 struct srvsvc_NetShareInfo502 info502 =
3667 ctr_src.ctr.ctr502->array[i];
3669 /* reset error-code */
3670 nt_status = NT_STATUS_UNSUCCESSFUL;
3672 if (!check_share_sanity(c, cli, info502.name, info502.type))
3673 continue;
3675 /* finally add the share on the dst server */
3677 printf(_("migrating: [%s], path: %s, comment: %s, without "
3678 "share-ACLs\n"),
3679 info502.name, info502.path, info502.comment);
3681 info.info502 = &info502;
3683 nt_status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
3684 srvsvc_pipe->desthost,
3685 502,
3686 &info,
3687 &parm_error,
3688 &result);
3689 if (!NT_STATUS_IS_OK(nt_status)) {
3690 printf(_("cannot add share: %s\n"),
3691 nt_errstr(nt_status));
3692 goto done;
3694 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3695 printf(_(" [%s] does already exist\n"),
3696 info502.name);
3697 continue;
3700 if (!W_ERROR_IS_OK(result)) {
3701 nt_status = werror_to_ntstatus(result);
3702 printf(_("cannot add share: %s\n"),
3703 win_errstr(result));
3704 goto done;
3709 nt_status = NT_STATUS_OK;
3711 done:
3712 if (cli_dst) {
3713 cli_shutdown(cli_dst);
3716 return nt_status;
3721 * Migrate shares from a RPC server to another.
3723 * @param argc Standard main() style argc.
3724 * @param argv Standard main() style argv. Initial components are already
3725 * stripped.
3727 * @return A shell status integer (0 for success).
3729 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3730 const char **argv)
3732 if (c->display_usage) {
3733 d_printf( "%s\n"
3734 "net rpc share migrate shares\n"
3735 " %s\n",
3736 _("Usage:"),
3737 _("Migrate shares to local server"));
3738 return 0;
3741 if (!c->opt_host) {
3742 printf(_("no server to migrate\n"));
3743 return -1;
3746 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
3747 rpc_share_migrate_shares_internals,
3748 argc, argv);
3752 * Copy a file/dir
3754 * @param f file_info
3755 * @param mask current search mask
3756 * @param state arg-pointer
3759 static NTSTATUS copy_fn(const char *mnt, struct file_info *f,
3760 const char *mask, void *state)
3762 static NTSTATUS nt_status;
3763 static struct copy_clistate *local_state;
3764 static fstring filename, new_mask;
3765 fstring dir;
3766 char *old_dir;
3767 struct net_context *c;
3769 local_state = (struct copy_clistate *)state;
3770 nt_status = NT_STATUS_UNSUCCESSFUL;
3772 c = local_state->c;
3774 if (strequal(f->name, ".") || strequal(f->name, ".."))
3775 return NT_STATUS_OK;
3777 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3779 /* DIRECTORY */
3780 if (f->mode & FILE_ATTRIBUTE_DIRECTORY) {
3782 DEBUG(3,("got dir: %s\n", f->name));
3784 fstrcpy(dir, local_state->cwd);
3785 fstrcat(dir, "\\");
3786 fstrcat(dir, f->name);
3788 switch (net_mode_share)
3790 case NET_MODE_SHARE_MIGRATE:
3791 /* create that directory */
3792 nt_status = net_copy_file(c, local_state->mem_ctx,
3793 local_state->cli_share_src,
3794 local_state->cli_share_dst,
3795 dir, dir,
3796 c->opt_acls? true : false,
3797 c->opt_attrs? true : false,
3798 c->opt_timestamps? true:false,
3799 false);
3800 break;
3801 default:
3802 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3803 return NT_STATUS_INTERNAL_ERROR;
3806 if (!NT_STATUS_IS_OK(nt_status)) {
3807 printf(_("could not handle dir %s: %s\n"),
3808 dir, nt_errstr(nt_status));
3809 return nt_status;
3812 /* search below that directory */
3813 if (strlcpy(new_mask, dir, sizeof(new_mask)) >= sizeof(new_mask)) {
3814 return NT_STATUS_NO_MEMORY;
3816 if (strlcat(new_mask, "\\*", sizeof(new_mask)) >= sizeof(new_mask)) {
3817 return NT_STATUS_NO_MEMORY;
3820 old_dir = local_state->cwd;
3821 local_state->cwd = dir;
3822 nt_status = sync_files(local_state, new_mask);
3823 if (!NT_STATUS_IS_OK(nt_status)) {
3824 printf(_("could not handle files\n"));
3826 local_state->cwd = old_dir;
3828 return nt_status;
3832 /* FILE */
3833 fstrcpy(filename, local_state->cwd);
3834 fstrcat(filename, "\\");
3835 fstrcat(filename, f->name);
3837 DEBUG(3,("got file: %s\n", filename));
3839 switch (net_mode_share)
3841 case NET_MODE_SHARE_MIGRATE:
3842 nt_status = net_copy_file(c, local_state->mem_ctx,
3843 local_state->cli_share_src,
3844 local_state->cli_share_dst,
3845 filename, filename,
3846 c->opt_acls? true : false,
3847 c->opt_attrs? true : false,
3848 c->opt_timestamps? true: false,
3849 true);
3850 break;
3851 default:
3852 d_fprintf(stderr, _("Unsupported file mode %d\n"),
3853 net_mode_share);
3854 return NT_STATUS_INTERNAL_ERROR;
3857 if (!NT_STATUS_IS_OK(nt_status))
3858 printf(_("could not handle file %s: %s\n"),
3859 filename, nt_errstr(nt_status));
3860 return nt_status;
3864 * sync files, can be called recursivly to list files
3865 * and then call copy_fn for each file
3867 * @param cp_clistate pointer to the copy_clistate we work with
3868 * @param mask the current search mask
3870 * @return Boolean result
3872 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask)
3874 struct cli_state *targetcli;
3875 char *targetpath = NULL;
3876 NTSTATUS status;
3878 DEBUG(3,("calling cli_list with mask: %s\n", mask));
3880 status = cli_resolve_path(talloc_tos(), "", NULL,
3881 cp_clistate->cli_share_src,
3882 mask, &targetcli, &targetpath);
3883 if (!NT_STATUS_IS_OK(status)) {
3884 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
3885 "%s\n"),
3886 mask, nt_errstr(status));
3887 return status;
3890 status = cli_list(targetcli, targetpath, cp_clistate->attribute,
3891 copy_fn, cp_clistate);
3892 if (!NT_STATUS_IS_OK(status)) {
3893 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
3894 mask, nt_errstr(status));
3897 return status;
3902 * Set the top level directory permissions before we do any further copies.
3903 * Should set up ACL inheritance.
3906 bool copy_top_level_perms(struct net_context *c,
3907 struct copy_clistate *cp_clistate,
3908 const char *sharename)
3910 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3912 switch (net_mode_share) {
3913 case NET_MODE_SHARE_MIGRATE:
3914 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3915 nt_status = net_copy_fileattr(c,
3916 cp_clistate->mem_ctx,
3917 cp_clistate->cli_share_src,
3918 cp_clistate->cli_share_dst,
3919 "\\", "\\",
3920 c->opt_acls? true : false,
3921 c->opt_attrs? true : false,
3922 c->opt_timestamps? true: false,
3923 false);
3924 break;
3925 default:
3926 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3927 break;
3930 if (!NT_STATUS_IS_OK(nt_status)) {
3931 printf(_("Could handle directory attributes for top level "
3932 "directory of share %s. Error %s\n"),
3933 sharename, nt_errstr(nt_status));
3934 return false;
3937 return true;
3941 * Sync all files inside a remote share to another share (over smb).
3943 * All parameters are provided by the run_rpc_command function, except for
3944 * argc, argv which are passed through.
3946 * @param domain_sid The domain sid acquired from the remote server.
3947 * @param cli A cli_state connected to the server.
3948 * @param mem_ctx Talloc context, destroyed on completion of the function.
3949 * @param argc Standard main() style argc.
3950 * @param argv Standard main() style argv. Initial components are already
3951 * stripped.
3953 * @return Normal NTSTATUS return.
3956 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
3957 const struct dom_sid *domain_sid,
3958 const char *domain_name,
3959 struct cli_state *cli,
3960 struct rpc_pipe_client *pipe_hnd,
3961 TALLOC_CTX *mem_ctx,
3962 int argc,
3963 const char **argv)
3965 WERROR result;
3966 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3967 struct srvsvc_NetShareInfoCtr ctr_src;
3968 uint32 i;
3969 uint32 level = 502;
3970 struct copy_clistate cp_clistate;
3971 bool got_src_share = false;
3972 bool got_dst_share = false;
3973 const char *mask = "\\*";
3974 char *dst = NULL;
3976 dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3977 if (dst == NULL) {
3978 nt_status = NT_STATUS_NO_MEMORY;
3979 goto done;
3982 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3983 &ctr_src);
3985 if (!W_ERROR_IS_OK(result))
3986 goto done;
3988 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3990 struct srvsvc_NetShareInfo502 info502 =
3991 ctr_src.ctr.ctr502->array[i];
3993 if (!check_share_sanity(c, cli, info502.name, info502.type))
3994 continue;
3996 /* one might not want to mirror whole discs :) */
3997 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3998 d_printf(_("skipping [%s]: builtin/hidden share\n"),
3999 info502.name);
4000 continue;
4003 switch (net_mode_share)
4005 case NET_MODE_SHARE_MIGRATE:
4006 printf("syncing");
4007 break;
4008 default:
4009 d_fprintf(stderr, _("Unsupported mode %d\n"),
4010 net_mode_share);
4011 break;
4013 printf(_(" [%s] files and directories %s ACLs, %s DOS "
4014 "Attributes %s\n"),
4015 info502.name,
4016 c->opt_acls ? _("including") : _("without"),
4017 c->opt_attrs ? _("including") : _("without"),
4018 c->opt_timestamps ? _("(preserving timestamps)") : "");
4020 cp_clistate.mem_ctx = mem_ctx;
4021 cp_clistate.cli_share_src = NULL;
4022 cp_clistate.cli_share_dst = NULL;
4023 cp_clistate.cwd = NULL;
4024 cp_clistate.attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
4025 cp_clistate.c = c;
4027 /* open share source */
4028 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
4029 smbXcli_conn_remote_sockaddr(cli->conn),
4030 smbXcli_conn_remote_name(cli->conn),
4031 info502.name, "A:");
4032 if (!NT_STATUS_IS_OK(nt_status))
4033 goto done;
4035 got_src_share = true;
4037 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
4038 /* open share destination */
4039 nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
4040 NULL, dst, info502.name, "A:");
4041 if (!NT_STATUS_IS_OK(nt_status))
4042 goto done;
4044 got_dst_share = true;
4047 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
4048 d_fprintf(stderr, _("Could not handle the top level "
4049 "directory permissions for the "
4050 "share: %s\n"), info502.name);
4051 nt_status = NT_STATUS_UNSUCCESSFUL;
4052 goto done;
4055 nt_status = sync_files(&cp_clistate, mask);
4056 if (!NT_STATUS_IS_OK(nt_status)) {
4057 d_fprintf(stderr, _("could not handle files for share: "
4058 "%s\n"), info502.name);
4059 goto done;
4063 nt_status = NT_STATUS_OK;
4065 done:
4067 if (got_src_share)
4068 cli_shutdown(cp_clistate.cli_share_src);
4070 if (got_dst_share)
4071 cli_shutdown(cp_clistate.cli_share_dst);
4073 SAFE_FREE(dst);
4074 return nt_status;
4078 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
4080 if (c->display_usage) {
4081 d_printf( "%s\n"
4082 "net share migrate files\n"
4083 " %s\n",
4084 _("Usage:"),
4085 _("Migrate files to local server"));
4086 return 0;
4089 if (!c->opt_host) {
4090 d_printf(_("no server to migrate\n"));
4091 return -1;
4094 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4095 rpc_share_migrate_files_internals,
4096 argc, argv);
4100 * Migrate share-ACLs from a remote RPC server to the local RPC server.
4102 * All parameters are provided by the run_rpc_command function, except for
4103 * argc, argv which are passed through.
4105 * @param domain_sid The domain sid acquired from the remote server.
4106 * @param cli A cli_state connected to the server.
4107 * @param mem_ctx Talloc context, destroyed on completion of the function.
4108 * @param argc Standard main() style argc.
4109 * @param argv Standard main() style argv. Initial components are already
4110 * stripped.
4112 * @return Normal NTSTATUS return.
4115 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
4116 const struct dom_sid *domain_sid,
4117 const char *domain_name,
4118 struct cli_state *cli,
4119 struct rpc_pipe_client *pipe_hnd,
4120 TALLOC_CTX *mem_ctx,
4121 int argc,
4122 const char **argv)
4124 WERROR result;
4125 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4126 struct srvsvc_NetShareInfoCtr ctr_src;
4127 union srvsvc_NetShareInfo info;
4128 uint32 i;
4129 struct rpc_pipe_client *srvsvc_pipe = NULL;
4130 struct cli_state *cli_dst = NULL;
4131 uint32 level = 502; /* includes secdesc */
4132 uint32_t parm_error = 0;
4133 struct dcerpc_binding_handle *b;
4135 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
4136 &ctr_src);
4138 if (!W_ERROR_IS_OK(result))
4139 goto done;
4141 /* connect destination PI_SRVSVC */
4142 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
4143 &ndr_table_srvsvc.syntax_id);
4144 if (!NT_STATUS_IS_OK(nt_status))
4145 return nt_status;
4147 b = srvsvc_pipe->binding_handle;
4149 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
4151 struct srvsvc_NetShareInfo502 info502 =
4152 ctr_src.ctr.ctr502->array[i];
4154 /* reset error-code */
4155 nt_status = NT_STATUS_UNSUCCESSFUL;
4157 if (!check_share_sanity(c, cli, info502.name, info502.type))
4158 continue;
4160 printf(_("migrating: [%s], path: %s, comment: %s, including "
4161 "share-ACLs\n"),
4162 info502.name, info502.path, info502.comment);
4164 if (c->opt_verbose)
4165 display_sec_desc(info502.sd_buf.sd);
4167 /* FIXME: shouldn't we be able to just set the security descriptor ? */
4168 info.info502 = &info502;
4170 /* finally modify the share on the dst server */
4171 nt_status = dcerpc_srvsvc_NetShareSetInfo(b, mem_ctx,
4172 srvsvc_pipe->desthost,
4173 info502.name,
4174 level,
4175 &info,
4176 &parm_error,
4177 &result);
4178 if (!NT_STATUS_IS_OK(nt_status)) {
4179 printf(_("cannot set share-acl: %s\n"),
4180 nt_errstr(nt_status));
4181 goto done;
4183 if (!W_ERROR_IS_OK(result)) {
4184 nt_status = werror_to_ntstatus(result);
4185 printf(_("cannot set share-acl: %s\n"),
4186 win_errstr(result));
4187 goto done;
4192 nt_status = NT_STATUS_OK;
4194 done:
4195 if (cli_dst) {
4196 cli_shutdown(cli_dst);
4199 return nt_status;
4204 * Migrate share-acls from a RPC server to another.
4206 * @param argc Standard main() style argc.
4207 * @param argv Standard main() style argv. Initial components are already
4208 * stripped.
4210 * @return A shell status integer (0 for success).
4212 static int rpc_share_migrate_security(struct net_context *c, int argc,
4213 const char **argv)
4215 if (c->display_usage) {
4216 d_printf( "%s\n"
4217 "net rpc share migrate security\n"
4218 " %s\n",
4219 _("Usage:"),
4220 _("Migrate share-acls to local server"));
4221 return 0;
4224 if (!c->opt_host) {
4225 d_printf(_("no server to migrate\n"));
4226 return -1;
4229 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4230 rpc_share_migrate_security_internals,
4231 argc, argv);
4235 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
4236 * from one server to another.
4238 * @param argc Standard main() style argc.
4239 * @param argv Standard main() style argv. Initial components are already
4240 * stripped.
4242 * @return A shell status integer (0 for success).
4245 static int rpc_share_migrate_all(struct net_context *c, int argc,
4246 const char **argv)
4248 int ret;
4250 if (c->display_usage) {
4251 d_printf( "%s\n"
4252 "net rpc share migrate all\n"
4253 " %s\n",
4254 _("Usage:"),
4255 _("Migrates shares including all share settings"));
4256 return 0;
4259 if (!c->opt_host) {
4260 d_printf(_("no server to migrate\n"));
4261 return -1;
4264 /* order is important. we don't want to be locked out by the share-acl
4265 * before copying files - gd */
4267 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4268 rpc_share_migrate_shares_internals, argc, argv);
4269 if (ret)
4270 return ret;
4272 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4273 rpc_share_migrate_files_internals, argc, argv);
4274 if (ret)
4275 return ret;
4277 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
4278 rpc_share_migrate_security_internals, argc,
4279 argv);
4284 * 'net rpc share migrate' entrypoint.
4285 * @param argc Standard main() style argc.
4286 * @param argv Standard main() style argv. Initial components are already
4287 * stripped.
4289 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
4292 struct functable func[] = {
4294 "all",
4295 rpc_share_migrate_all,
4296 NET_TRANSPORT_RPC,
4297 N_("Migrate shares from remote to local server"),
4298 N_("net rpc share migrate all\n"
4299 " Migrate shares from remote to local server")
4302 "files",
4303 rpc_share_migrate_files,
4304 NET_TRANSPORT_RPC,
4305 N_("Migrate files from remote to local server"),
4306 N_("net rpc share migrate files\n"
4307 " Migrate files from remote to local server")
4310 "security",
4311 rpc_share_migrate_security,
4312 NET_TRANSPORT_RPC,
4313 N_("Migrate share-ACLs from remote to local server"),
4314 N_("net rpc share migrate security\n"
4315 " Migrate share-ACLs from remote to local server")
4318 "shares",
4319 rpc_share_migrate_shares,
4320 NET_TRANSPORT_RPC,
4321 N_("Migrate shares from remote to local server"),
4322 N_("net rpc share migrate shares\n"
4323 " Migrate shares from remote to local server")
4325 {NULL, NULL, 0, NULL, NULL}
4328 net_mode_share = NET_MODE_SHARE_MIGRATE;
4330 return net_run_function(c, argc, argv, "net rpc share migrate", func);
4333 struct full_alias {
4334 struct dom_sid sid;
4335 uint32 num_members;
4336 struct dom_sid *members;
4339 static int num_server_aliases;
4340 static struct full_alias *server_aliases;
4343 * Add an alias to the static list.
4345 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
4347 if (server_aliases == NULL)
4348 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
4350 server_aliases[num_server_aliases] = *alias;
4351 num_server_aliases += 1;
4355 * For a specific domain on the server, fetch all the aliases
4356 * and their members. Add all of them to the server_aliases.
4359 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4360 TALLOC_CTX *mem_ctx,
4361 struct policy_handle *connect_pol,
4362 const struct dom_sid *domain_sid)
4364 uint32 start_idx, max_entries, num_entries, i;
4365 struct samr_SamArray *groups = NULL;
4366 NTSTATUS result, status;
4367 struct policy_handle domain_pol;
4368 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4370 /* Get domain policy handle */
4372 status = dcerpc_samr_OpenDomain(b, mem_ctx,
4373 connect_pol,
4374 MAXIMUM_ALLOWED_ACCESS,
4375 discard_const_p(struct dom_sid2, domain_sid),
4376 &domain_pol,
4377 &result);
4378 if (!NT_STATUS_IS_OK(status)) {
4379 return status;
4381 if (!NT_STATUS_IS_OK(result)) {
4382 return result;
4385 start_idx = 0;
4386 max_entries = 250;
4388 do {
4389 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
4390 &domain_pol,
4391 &start_idx,
4392 &groups,
4393 max_entries,
4394 &num_entries,
4395 &result);
4396 if (!NT_STATUS_IS_OK(status)) {
4397 goto done;
4399 for (i = 0; i < num_entries; i++) {
4401 struct policy_handle alias_pol;
4402 struct full_alias alias;
4403 struct lsa_SidArray sid_array;
4404 int j;
4405 NTSTATUS _result;
4407 status = dcerpc_samr_OpenAlias(b, mem_ctx,
4408 &domain_pol,
4409 MAXIMUM_ALLOWED_ACCESS,
4410 groups->entries[i].idx,
4411 &alias_pol,
4412 &_result);
4413 if (!NT_STATUS_IS_OK(status)) {
4414 goto done;
4416 if (!NT_STATUS_IS_OK(_result)) {
4417 status = _result;
4418 goto done;
4421 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
4422 &alias_pol,
4423 &sid_array,
4424 &_result);
4425 if (!NT_STATUS_IS_OK(status)) {
4426 goto done;
4428 if (!NT_STATUS_IS_OK(_result)) {
4429 status = _result;
4430 goto done;
4433 alias.num_members = sid_array.num_sids;
4435 status = dcerpc_samr_Close(b, mem_ctx, &alias_pol, &_result);
4436 if (!NT_STATUS_IS_OK(status)) {
4437 goto done;
4439 if (!NT_STATUS_IS_OK(_result)) {
4440 status = _result;
4441 goto done;
4444 alias.members = NULL;
4446 if (alias.num_members > 0) {
4447 alias.members = SMB_MALLOC_ARRAY(struct dom_sid, alias.num_members);
4449 for (j = 0; j < alias.num_members; j++)
4450 sid_copy(&alias.members[j],
4451 sid_array.sids[j].sid);
4454 sid_compose(&alias.sid, domain_sid,
4455 groups->entries[i].idx);
4457 push_alias(mem_ctx, &alias);
4459 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4461 status = NT_STATUS_OK;
4463 done:
4464 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
4466 return status;
4470 * Dump server_aliases as names for debugging purposes.
4473 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4474 const struct dom_sid *domain_sid,
4475 const char *domain_name,
4476 struct cli_state *cli,
4477 struct rpc_pipe_client *pipe_hnd,
4478 TALLOC_CTX *mem_ctx,
4479 int argc,
4480 const char **argv)
4482 int i;
4483 NTSTATUS result;
4484 struct policy_handle lsa_pol;
4485 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4487 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4488 SEC_FLAG_MAXIMUM_ALLOWED,
4489 &lsa_pol);
4490 if (!NT_STATUS_IS_OK(result))
4491 return result;
4493 for (i=0; i<num_server_aliases; i++) {
4494 char **names;
4495 char **domains;
4496 enum lsa_SidType *types;
4497 int j;
4499 struct full_alias *alias = &server_aliases[i];
4501 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4502 &alias->sid,
4503 &domains, &names, &types);
4504 if (!NT_STATUS_IS_OK(result))
4505 continue;
4507 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4509 if (alias->num_members == 0) {
4510 DEBUG(1, ("\n"));
4511 continue;
4514 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4515 alias->num_members,
4516 alias->members,
4517 &domains, &names, &types);
4519 if (!NT_STATUS_IS_OK(result) &&
4520 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4521 continue;
4523 for (j=0; j<alias->num_members; j++)
4524 DEBUG(1, ("%s\\%s (%d); ",
4525 domains[j] ? domains[j] : "*unknown*",
4526 names[j] ? names[j] : "*unknown*",types[j]));
4527 DEBUG(1, ("\n"));
4530 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
4532 return NT_STATUS_OK;
4536 * Fetch a list of all server aliases and their members into
4537 * server_aliases.
4540 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4541 const struct dom_sid *domain_sid,
4542 const char *domain_name,
4543 struct cli_state *cli,
4544 struct rpc_pipe_client *pipe_hnd,
4545 TALLOC_CTX *mem_ctx,
4546 int argc,
4547 const char **argv)
4549 NTSTATUS result, status;
4550 struct policy_handle connect_pol;
4551 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4553 status = dcerpc_samr_Connect2(b, mem_ctx,
4554 pipe_hnd->desthost,
4555 MAXIMUM_ALLOWED_ACCESS,
4556 &connect_pol,
4557 &result);
4558 if (!NT_STATUS_IS_OK(status)) {
4559 goto done;
4561 if (!NT_STATUS_IS_OK(result)) {
4562 status = result;
4563 goto done;
4566 status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4567 &global_sid_Builtin);
4568 if (!NT_STATUS_IS_OK(status)) {
4569 goto done;
4572 status = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4573 domain_sid);
4575 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
4576 done:
4577 return status;
4580 static void init_user_token(struct security_token *token, struct dom_sid *user_sid)
4582 token->num_sids = 4;
4584 if (!(token->sids = SMB_MALLOC_ARRAY(struct dom_sid, 4))) {
4585 d_fprintf(stderr, "malloc %s\n",_("failed"));
4586 token->num_sids = 0;
4587 return;
4590 token->sids[0] = *user_sid;
4591 sid_copy(&token->sids[1], &global_sid_World);
4592 sid_copy(&token->sids[2], &global_sid_Network);
4593 sid_copy(&token->sids[3], &global_sid_Authenticated_Users);
4596 static void free_user_token(struct security_token *token)
4598 SAFE_FREE(token->sids);
4601 static void add_sid_to_token(struct security_token *token, struct dom_sid *sid)
4603 if (security_token_has_sid(token, sid))
4604 return;
4606 token->sids = SMB_REALLOC_ARRAY(token->sids, struct dom_sid, token->num_sids+1);
4607 if (!token->sids) {
4608 return;
4611 sid_copy(&token->sids[token->num_sids], sid);
4613 token->num_sids += 1;
4616 struct user_token {
4617 fstring name;
4618 struct security_token token;
4621 static void dump_user_token(struct user_token *token)
4623 int i;
4625 d_printf("%s\n", token->name);
4627 for (i=0; i<token->token.num_sids; i++) {
4628 d_printf(" %s\n", sid_string_tos(&token->token.sids[i]));
4632 static bool is_alias_member(struct dom_sid *sid, struct full_alias *alias)
4634 int i;
4636 for (i=0; i<alias->num_members; i++) {
4637 if (dom_sid_compare(sid, &alias->members[i]) == 0)
4638 return true;
4641 return false;
4644 static void collect_sid_memberships(struct security_token *token, struct dom_sid sid)
4646 int i;
4648 for (i=0; i<num_server_aliases; i++) {
4649 if (is_alias_member(&sid, &server_aliases[i]))
4650 add_sid_to_token(token, &server_aliases[i].sid);
4655 * We got a user token with all the SIDs we can know about without asking the
4656 * server directly. These are the user and domain group sids. All of these can
4657 * be members of aliases. So scan the list of aliases for each of the SIDs and
4658 * add them to the token.
4661 static void collect_alias_memberships(struct security_token *token)
4663 int num_global_sids = token->num_sids;
4664 int i;
4666 for (i=0; i<num_global_sids; i++) {
4667 collect_sid_memberships(token, token->sids[i]);
4671 static bool get_user_sids(const char *domain, const char *user, struct security_token *token)
4673 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4674 enum wbcSidType type;
4675 fstring full_name;
4676 struct wbcDomainSid wsid;
4677 char sid_str[WBC_SID_STRING_BUFLEN];
4678 struct dom_sid user_sid;
4679 uint32_t num_groups;
4680 gid_t *groups = NULL;
4681 uint32_t i;
4683 fstr_sprintf(full_name, "%s%c%s",
4684 domain, *lp_winbind_separator(), user);
4686 /* First let's find out the user sid */
4688 wbc_status = wbcLookupName(domain, user, &wsid, &type);
4690 if (!WBC_ERROR_IS_OK(wbc_status)) {
4691 DEBUG(1, ("winbind could not find %s: %s\n",
4692 full_name, wbcErrorString(wbc_status)));
4693 return false;
4696 wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4698 if (type != WBC_SID_NAME_USER) {
4699 DEBUG(1, ("%s is not a user\n", full_name));
4700 return false;
4703 if (!string_to_sid(&user_sid, sid_str)) {
4704 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4705 return false;
4708 init_user_token(token, &user_sid);
4710 /* And now the groups winbind knows about */
4712 wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4713 if (!WBC_ERROR_IS_OK(wbc_status)) {
4714 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4715 full_name, wbcErrorString(wbc_status)));
4716 return false;
4719 for (i = 0; i < num_groups; i++) {
4720 gid_t gid = groups[i];
4721 struct dom_sid sid;
4722 bool ok;
4724 wbc_status = wbcGidToSid(gid, &wsid);
4725 if (!WBC_ERROR_IS_OK(wbc_status)) {
4726 DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4727 (unsigned int)gid, wbcErrorString(wbc_status)));
4728 wbcFreeMemory(groups);
4729 return false;
4732 wbcSidToStringBuf(&wsid, sid_str, sizeof(sid_str));
4734 DEBUG(3, (" %s\n", sid_str));
4736 ok = string_to_sid(&sid, sid_str);
4737 if (!ok) {
4738 DEBUG(1, ("Failed to convert string to SID\n"));
4739 wbcFreeMemory(groups);
4740 return false;
4742 add_sid_to_token(token, &sid);
4744 wbcFreeMemory(groups);
4746 return true;
4750 * Get a list of all user tokens we want to look at
4753 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4754 struct user_token **user_tokens)
4756 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4757 uint32_t i, num_users;
4758 const char **users;
4759 struct user_token *result;
4760 TALLOC_CTX *frame = NULL;
4762 if (lp_winbind_use_default_domain() &&
4763 (c->opt_target_workgroup == NULL)) {
4764 d_fprintf(stderr, _("winbind use default domain = yes set, "
4765 "please specify a workgroup\n"));
4766 return false;
4769 /* Send request to winbind daemon */
4771 wbc_status = wbcListUsers(NULL, &num_users, &users);
4772 if (!WBC_ERROR_IS_OK(wbc_status)) {
4773 DEBUG(1, (_("winbind could not list users: %s\n"),
4774 wbcErrorString(wbc_status)));
4775 return false;
4778 result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4780 if (result == NULL) {
4781 DEBUG(1, ("Could not malloc sid array\n"));
4782 wbcFreeMemory(users);
4783 return false;
4786 frame = talloc_stackframe();
4787 for (i=0; i < num_users; i++) {
4788 fstring domain, user;
4789 char *p;
4791 fstrcpy(result[i].name, users[i]);
4793 p = strchr(users[i], *lp_winbind_separator());
4795 DEBUG(3, ("%s\n", users[i]));
4797 if (p == NULL) {
4798 fstrcpy(domain, c->opt_target_workgroup);
4799 fstrcpy(user, users[i]);
4800 } else {
4801 *p++ = '\0';
4802 fstrcpy(domain, users[i]);
4803 if (!strupper_m(domain)) {
4804 DEBUG(1, ("strupper_m %s failed\n", domain));
4805 wbcFreeMemory(users);
4806 return false;
4808 fstrcpy(user, p);
4811 get_user_sids(domain, user, &(result[i].token));
4813 TALLOC_FREE(frame);
4814 wbcFreeMemory(users);
4816 *num_tokens = num_users;
4817 *user_tokens = result;
4819 return true;
4822 static bool get_user_tokens_from_file(FILE *f,
4823 int *num_tokens,
4824 struct user_token **tokens)
4826 struct user_token *token = NULL;
4828 while (!feof(f)) {
4829 fstring line;
4831 if (fgets(line, sizeof(line)-1, f) == NULL) {
4832 return true;
4835 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
4836 line[strlen(line)-1] = '\0';
4839 if (line[0] == ' ') {
4840 /* We have a SID */
4842 struct dom_sid sid;
4843 if(!string_to_sid(&sid, &line[1])) {
4844 DEBUG(1,("get_user_tokens_from_file: Could "
4845 "not convert sid %s \n",&line[1]));
4846 return false;
4849 if (token == NULL) {
4850 DEBUG(0, ("File does not begin with username"));
4851 return false;
4854 add_sid_to_token(&token->token, &sid);
4855 continue;
4858 /* And a new user... */
4860 *num_tokens += 1;
4861 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4862 if (*tokens == NULL) {
4863 DEBUG(0, ("Could not realloc tokens\n"));
4864 return false;
4867 token = &((*tokens)[*num_tokens-1]);
4869 if (strlcpy(token->name, line, sizeof(token->name)) >= sizeof(token->name)) {
4870 return false;
4872 token->token.num_sids = 0;
4873 token->token.sids = NULL;
4874 continue;
4877 return false;
4882 * Show the list of all users that have access to a share
4885 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4886 TALLOC_CTX *mem_ctx,
4887 const char *netname,
4888 int num_tokens,
4889 struct user_token *tokens)
4891 uint16_t fnum;
4892 struct security_descriptor *share_sd = NULL;
4893 struct security_descriptor *root_sd = NULL;
4894 struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4895 int i;
4896 union srvsvc_NetShareInfo info;
4897 WERROR result;
4898 NTSTATUS status;
4899 uint16 cnum;
4900 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4902 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
4903 pipe_hnd->desthost,
4904 netname,
4905 502,
4906 &info,
4907 &result);
4909 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4910 DEBUG(1, ("Coult not query secdesc for share %s\n",
4911 netname));
4912 return;
4915 share_sd = info.info502->sd_buf.sd;
4916 if (share_sd == NULL) {
4917 DEBUG(1, ("Got no secdesc for share %s\n",
4918 netname));
4921 cnum = cli_state_get_tid(cli);
4923 if (!NT_STATUS_IS_OK(cli_tree_connect(cli, netname, "A:", "", 0))) {
4924 return;
4927 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
4928 FILE_SHARE_READ|FILE_SHARE_WRITE,
4929 FILE_OPEN, 0x0, 0x0, &fnum, NULL))) {
4930 cli_query_secdesc(cli, fnum, mem_ctx, &root_sd);
4933 for (i=0; i<num_tokens; i++) {
4934 uint32 acc_granted;
4936 if (share_sd != NULL) {
4937 status = se_access_check(share_sd, &tokens[i].token,
4938 1, &acc_granted);
4940 if (!NT_STATUS_IS_OK(status)) {
4941 DEBUG(1, ("Could not check share_sd for "
4942 "user %s\n",
4943 tokens[i].name));
4944 continue;
4948 if (root_sd == NULL) {
4949 d_printf(" %s\n", tokens[i].name);
4950 continue;
4953 status = se_access_check(root_sd, &tokens[i].token,
4954 1, &acc_granted);
4955 if (!NT_STATUS_IS_OK(status)) {
4956 DEBUG(1, ("Could not check root_sd for user %s\n",
4957 tokens[i].name));
4958 continue;
4960 d_printf(" %s\n", tokens[i].name);
4963 if (fnum != (uint16_t)-1)
4964 cli_close(cli, fnum);
4965 cli_tdis(cli);
4966 cli_state_set_tid(cli, cnum);
4968 return;
4972 * List shares on a remote RPC server, including the security descriptors.
4974 * All parameters are provided by the run_rpc_command function, except for
4975 * argc, argv which are passed through.
4977 * @param domain_sid The domain sid acquired from the remote server.
4978 * @param cli A cli_state connected to the server.
4979 * @param mem_ctx Talloc context, destroyed on completion of the function.
4980 * @param argc Standard main() style argc.
4981 * @param argv Standard main() style argv. Initial components are already
4982 * stripped.
4984 * @return Normal NTSTATUS return.
4987 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
4988 const struct dom_sid *domain_sid,
4989 const char *domain_name,
4990 struct cli_state *cli,
4991 struct rpc_pipe_client *pipe_hnd,
4992 TALLOC_CTX *mem_ctx,
4993 int argc,
4994 const char **argv)
4996 bool r;
4997 FILE *f;
4998 NTSTATUS nt_status = NT_STATUS_OK;
4999 uint32_t total_entries = 0;
5000 uint32_t resume_handle = 0;
5001 uint32_t preferred_len = 0xffffffff;
5002 uint32_t i;
5003 struct dcerpc_binding_handle *b = NULL;
5004 struct srvsvc_NetShareInfoCtr info_ctr;
5005 struct srvsvc_NetShareCtr1 ctr1;
5006 WERROR result;
5008 struct user_token *tokens = NULL;
5009 int num_tokens = 0;
5011 if (argc == 0) {
5012 f = stdin;
5013 } else {
5014 f = fopen(argv[0], "r");
5017 if (f == NULL) {
5018 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
5019 return NT_STATUS_UNSUCCESSFUL;
5022 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
5024 if (f != stdin)
5025 fclose(f);
5027 if (!r) {
5028 DEBUG(0, ("Could not read users from file\n"));
5029 return NT_STATUS_UNSUCCESSFUL;
5032 for (i=0; i<num_tokens; i++)
5033 collect_alias_memberships(&tokens[i].token);
5035 ZERO_STRUCT(info_ctr);
5036 ZERO_STRUCT(ctr1);
5038 info_ctr.level = 1;
5039 info_ctr.ctr.ctr1 = &ctr1;
5041 b = pipe_hnd->binding_handle;
5043 /* Issue the NetShareEnum RPC call and retrieve the response */
5044 nt_status = dcerpc_srvsvc_NetShareEnumAll(b,
5045 talloc_tos(),
5046 pipe_hnd->desthost,
5047 &info_ctr,
5048 preferred_len,
5049 &total_entries,
5050 &resume_handle,
5051 &result);
5053 /* Was it successful? */
5054 if (!NT_STATUS_IS_OK(nt_status)) {
5055 /* Nope. Go clean up. */
5056 goto done;
5059 if (!W_ERROR_IS_OK(result)) {
5060 /* Nope. Go clean up. */
5061 nt_status = werror_to_ntstatus(result);
5062 goto done;
5065 if (total_entries == 0) {
5066 goto done;
5069 /* For each returned entry... */
5070 for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {
5071 const char *netname = info_ctr.ctr.ctr1->array[i].name;
5073 if (info_ctr.ctr.ctr1->array[i].type != STYPE_DISKTREE) {
5074 continue;
5077 d_printf("%s\n", netname);
5079 show_userlist(pipe_hnd, mem_ctx, netname,
5080 num_tokens, tokens);
5082 done:
5083 for (i=0; i<num_tokens; i++) {
5084 free_user_token(&tokens[i].token);
5086 SAFE_FREE(tokens);
5088 return nt_status;
5091 static int rpc_share_allowedusers(struct net_context *c, int argc,
5092 const char **argv)
5094 int result;
5096 if (c->display_usage) {
5097 d_printf( "%s\n"
5098 "net rpc share allowedusers\n"
5099 " %s\n",
5100 _("Usage:"),
5101 _("List allowed users"));
5102 return 0;
5105 result = run_rpc_command(c, NULL, &ndr_table_samr, 0,
5106 rpc_aliaslist_internals,
5107 argc, argv);
5108 if (result != 0)
5109 return result;
5111 result = run_rpc_command(c, NULL, &ndr_table_lsarpc, 0,
5112 rpc_aliaslist_dump,
5113 argc, argv);
5114 if (result != 0)
5115 return result;
5117 return run_rpc_command(c, NULL, &ndr_table_srvsvc, 0,
5118 rpc_share_allowedusers_internals,
5119 argc, argv);
5122 int net_usersidlist(struct net_context *c, int argc, const char **argv)
5124 int num_tokens = 0;
5125 struct user_token *tokens = NULL;
5126 int i;
5128 if (argc != 0) {
5129 net_usersidlist_usage(c, argc, argv);
5130 return 0;
5133 if (!get_user_tokens(c, &num_tokens, &tokens)) {
5134 DEBUG(0, ("Could not get the user/sid list\n"));
5135 return -1;
5138 for (i=0; i<num_tokens; i++) {
5139 dump_user_token(&tokens[i]);
5140 free_user_token(&tokens[i].token);
5143 SAFE_FREE(tokens);
5144 return 0;
5147 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
5149 d_printf(_("net usersidlist\n"
5150 "\tprints out a list of all users the running winbind knows\n"
5151 "\tabout, together with all their SIDs. This is used as\n"
5152 "\tinput to the 'net rpc share allowedusers' command.\n\n"));
5154 net_common_flags_usage(c, argc, argv);
5155 return -1;
5159 * 'net rpc share' entrypoint.
5160 * @param argc Standard main() style argc.
5161 * @param argv Standard main() style argv. Initial components are already
5162 * stripped.
5165 int net_rpc_share(struct net_context *c, int argc, const char **argv)
5167 NET_API_STATUS status;
5169 struct functable func[] = {
5171 "add",
5172 rpc_share_add,
5173 NET_TRANSPORT_RPC,
5174 N_("Add share"),
5175 N_("net rpc share add\n"
5176 " Add share")
5179 "delete",
5180 rpc_share_delete,
5181 NET_TRANSPORT_RPC,
5182 N_("Remove share"),
5183 N_("net rpc share delete\n"
5184 " Remove share")
5187 "allowedusers",
5188 rpc_share_allowedusers,
5189 NET_TRANSPORT_RPC,
5190 N_("Modify allowed users"),
5191 N_("net rpc share allowedusers\n"
5192 " Modify allowed users")
5195 "migrate",
5196 rpc_share_migrate,
5197 NET_TRANSPORT_RPC,
5198 N_("Migrate share to local server"),
5199 N_("net rpc share migrate\n"
5200 " Migrate share to local server")
5203 "list",
5204 rpc_share_list,
5205 NET_TRANSPORT_RPC,
5206 N_("List shares"),
5207 N_("net rpc share list\n"
5208 " List shares")
5210 {NULL, NULL, 0, NULL, NULL}
5213 status = libnetapi_net_init(&c->netapi_ctx);
5214 if (status != 0) {
5215 return -1;
5217 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5218 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5219 if (c->opt_kerberos) {
5220 libnetapi_set_use_kerberos(c->netapi_ctx);
5223 if (argc == 0) {
5224 if (c->display_usage) {
5225 d_printf("%s\n%s",
5226 _("Usage:"),
5227 _("net rpc share\n"
5228 " List shares\n"
5229 " Alias for net rpc share list\n"));
5230 net_display_usage_from_functable(func);
5231 return 0;
5234 return rpc_share_list(c, argc, argv);
5237 return net_run_function(c, argc, argv, "net rpc share", func);
5240 static NTSTATUS rpc_sh_share_list(struct net_context *c,
5241 TALLOC_CTX *mem_ctx,
5242 struct rpc_sh_ctx *ctx,
5243 struct rpc_pipe_client *pipe_hnd,
5244 int argc, const char **argv)
5247 return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
5250 static NTSTATUS rpc_sh_share_add(struct net_context *c,
5251 TALLOC_CTX *mem_ctx,
5252 struct rpc_sh_ctx *ctx,
5253 struct rpc_pipe_client *pipe_hnd,
5254 int argc, const char **argv)
5256 NET_API_STATUS status;
5257 uint32_t parm_err = 0;
5258 struct SHARE_INFO_2 i2;
5260 if ((argc < 2) || (argc > 3)) {
5261 d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
5262 ctx->whoami);
5263 return NT_STATUS_INVALID_PARAMETER;
5266 i2.shi2_netname = argv[0];
5267 i2.shi2_type = STYPE_DISKTREE;
5268 i2.shi2_remark = (argc == 3) ? argv[2] : "";
5269 i2.shi2_permissions = 0;
5270 i2.shi2_max_uses = 0;
5271 i2.shi2_current_uses = 0;
5272 i2.shi2_path = argv[1];
5273 i2.shi2_passwd = NULL;
5275 status = NetShareAdd(pipe_hnd->desthost,
5277 (uint8_t *)&i2,
5278 &parm_err);
5280 return werror_to_ntstatus(W_ERROR(status));
5283 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
5284 TALLOC_CTX *mem_ctx,
5285 struct rpc_sh_ctx *ctx,
5286 struct rpc_pipe_client *pipe_hnd,
5287 int argc, const char **argv)
5289 if (argc != 1) {
5290 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5291 return NT_STATUS_INVALID_PARAMETER;
5294 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
5297 static NTSTATUS rpc_sh_share_info(struct net_context *c,
5298 TALLOC_CTX *mem_ctx,
5299 struct rpc_sh_ctx *ctx,
5300 struct rpc_pipe_client *pipe_hnd,
5301 int argc, const char **argv)
5303 union srvsvc_NetShareInfo info;
5304 WERROR result;
5305 NTSTATUS status;
5306 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5308 if (argc != 1) {
5309 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5310 return NT_STATUS_INVALID_PARAMETER;
5313 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5314 pipe_hnd->desthost,
5315 argv[0],
5317 &info,
5318 &result);
5319 if (!NT_STATUS_IS_OK(status)) {
5320 result = ntstatus_to_werror(status);
5321 goto done;
5323 if (!W_ERROR_IS_OK(result)) {
5324 goto done;
5327 d_printf(_("Name: %s\n"), info.info2->name);
5328 d_printf(_("Comment: %s\n"), info.info2->comment);
5329 d_printf(_("Path: %s\n"), info.info2->path);
5330 d_printf(_("Password: %s\n"), info.info2->password);
5332 done:
5333 return werror_to_ntstatus(result);
5336 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
5337 struct rpc_sh_ctx *ctx)
5339 static struct rpc_sh_cmd cmds[] = {
5341 { "list", NULL, &ndr_table_srvsvc, rpc_sh_share_list,
5342 N_("List available shares") },
5344 { "add", NULL, &ndr_table_srvsvc, rpc_sh_share_add,
5345 N_("Add a share") },
5347 { "delete", NULL, &ndr_table_srvsvc, rpc_sh_share_delete,
5348 N_("Delete a share") },
5350 { "info", NULL, &ndr_table_srvsvc, rpc_sh_share_info,
5351 N_("Get information about a share") },
5353 { NULL, NULL, 0, NULL, NULL }
5356 return cmds;
5359 /****************************************************************************/
5361 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
5363 return net_file_usage(c, argc, argv);
5367 * Close a file on a remote RPC server.
5369 * @param argc Standard main() style argc.
5370 * @param argv Standard main() style argv. Initial components are already
5371 * stripped.
5373 * @return A shell status integer (0 for success).
5375 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5377 if (argc < 1 || c->display_usage) {
5378 return rpc_file_usage(c, argc, argv);
5381 return NetFileClose(c->opt_host, atoi(argv[0]));
5385 * Formatted print of open file info
5387 * @param r struct FILE_INFO_3 contents
5390 static void display_file_info_3(struct FILE_INFO_3 *r)
5392 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5393 r->fi3_id, r->fi3_username, r->fi3_permissions,
5394 r->fi3_num_locks, r->fi3_pathname);
5398 * List files for a user on a remote RPC server.
5400 * @param argc Standard main() style argc.
5401 * @param argv Standard main() style argv. Initial components are already
5402 * stripped.
5404 * @return A shell status integer (0 for success)..
5407 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5409 NET_API_STATUS status;
5410 uint32 preferred_len = 0xffffffff, i;
5411 char *username=NULL;
5412 uint32_t total_entries = 0;
5413 uint32_t entries_read = 0;
5414 uint32_t resume_handle = 0;
5415 struct FILE_INFO_3 *i3 = NULL;
5417 if (c->display_usage) {
5418 return rpc_file_usage(c, argc, argv);
5421 /* if argc > 0, must be user command */
5422 if (argc > 0) {
5423 username = smb_xstrdup(argv[0]);
5426 status = NetFileEnum(c->opt_host,
5427 NULL,
5428 username,
5430 (uint8_t **)(void *)&i3,
5431 preferred_len,
5432 &entries_read,
5433 &total_entries,
5434 &resume_handle);
5436 if (status != 0) {
5437 goto done;
5440 /* Display results */
5442 d_printf(_(
5443 "\nEnumerating open files on remote server:\n\n"
5444 "\nFileId Opened by Perms Locks Path"
5445 "\n------ --------- ----- ----- ---- \n"));
5446 for (i = 0; i < entries_read; i++) {
5447 display_file_info_3(&i3[i]);
5449 done:
5450 SAFE_FREE(username);
5451 return status;
5455 * 'net rpc file' entrypoint.
5456 * @param argc Standard main() style argc.
5457 * @param argv Standard main() style argv. Initial components are already
5458 * stripped.
5461 int net_rpc_file(struct net_context *c, int argc, const char **argv)
5463 NET_API_STATUS status;
5465 struct functable func[] = {
5467 "close",
5468 rpc_file_close,
5469 NET_TRANSPORT_RPC,
5470 N_("Close opened file"),
5471 N_("net rpc file close\n"
5472 " Close opened file")
5475 "user",
5476 rpc_file_user,
5477 NET_TRANSPORT_RPC,
5478 N_("List files opened by user"),
5479 N_("net rpc file user\n"
5480 " List files opened by user")
5482 #if 0
5484 "info",
5485 rpc_file_info,
5486 NET_TRANSPORT_RPC,
5487 N_("Display information about opened file"),
5488 N_("net rpc file info\n"
5489 " Display information about opened file")
5491 #endif
5492 {NULL, NULL, 0, NULL, NULL}
5495 status = libnetapi_net_init(&c->netapi_ctx);
5496 if (status != 0) {
5497 return -1;
5499 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5500 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5501 if (c->opt_kerberos) {
5502 libnetapi_set_use_kerberos(c->netapi_ctx);
5505 if (argc == 0) {
5506 if (c->display_usage) {
5507 d_printf(_("Usage:\n"));
5508 d_printf(_("net rpc file\n"
5509 " List opened files\n"));
5510 net_display_usage_from_functable(func);
5511 return 0;
5514 return rpc_file_user(c, argc, argv);
5517 return net_run_function(c, argc, argv, "net rpc file", func);
5521 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5523 * All parameters are provided by the run_rpc_command function, except for
5524 * argc, argv which are passed through.
5526 * @param c A net_context structure.
5527 * @param domain_sid The domain sid acquired from the remote server.
5528 * @param cli A cli_state connected to the server.
5529 * @param mem_ctx Talloc context, destroyed on completion of the function.
5530 * @param argc Standard main() style argc.
5531 * @param argv Standard main() style argv. Initial components are already
5532 * stripped.
5534 * @return Normal NTSTATUS return.
5537 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5538 const struct dom_sid *domain_sid,
5539 const char *domain_name,
5540 struct cli_state *cli,
5541 struct rpc_pipe_client *pipe_hnd,
5542 TALLOC_CTX *mem_ctx,
5543 int argc,
5544 const char **argv)
5546 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5547 WERROR result;
5548 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5550 status = dcerpc_initshutdown_Abort(b, mem_ctx, NULL, &result);
5551 if (!NT_STATUS_IS_OK(status)) {
5552 return status;
5554 if (W_ERROR_IS_OK(result)) {
5555 d_printf(_("\nShutdown successfully aborted\n"));
5556 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5557 } else
5558 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5560 return werror_to_ntstatus(result);
5564 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5566 * All parameters are provided by the run_rpc_command function, except for
5567 * argc, argv which are passed through.
5569 * @param c A net_context structure.
5570 * @param domain_sid The domain sid acquired from the remote server.
5571 * @param cli A cli_state connected to the server.
5572 * @param mem_ctx Talloc context, destroyed on completion of the function.
5573 * @param argc Standard main() style argc.
5574 * @param argv Standard main() style argv. Initial components are already
5575 * stripped.
5577 * @return Normal NTSTATUS return.
5580 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5581 const struct dom_sid *domain_sid,
5582 const char *domain_name,
5583 struct cli_state *cli,
5584 struct rpc_pipe_client *pipe_hnd,
5585 TALLOC_CTX *mem_ctx,
5586 int argc,
5587 const char **argv)
5589 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5590 WERROR werr;
5591 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5593 result = dcerpc_winreg_AbortSystemShutdown(b, mem_ctx, NULL, &werr);
5595 if (!NT_STATUS_IS_OK(result)) {
5596 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5597 return result;
5599 if (W_ERROR_IS_OK(werr)) {
5600 d_printf(_("\nShutdown successfully aborted\n"));
5601 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5602 } else
5603 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5605 return werror_to_ntstatus(werr);
5609 * ABORT the shutdown of a remote RPC server.
5611 * @param argc Standard main() style argc.
5612 * @param argv Standard main() style argv. Initial components are already
5613 * stripped.
5615 * @return A shell status integer (0 for success).
5618 static int rpc_shutdown_abort(struct net_context *c, int argc,
5619 const char **argv)
5621 int rc = -1;
5623 if (c->display_usage) {
5624 d_printf( "%s\n"
5625 "net rpc abortshutdown\n"
5626 " %s\n",
5627 _("Usage:"),
5628 _("Abort a scheduled shutdown"));
5629 return 0;
5632 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5633 rpc_shutdown_abort_internals, argc, argv);
5635 if (rc == 0)
5636 return rc;
5638 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5640 return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5641 rpc_reg_shutdown_abort_internals,
5642 argc, argv);
5646 * Shut down a remote RPC Server via initshutdown pipe.
5648 * All parameters are provided by the run_rpc_command function, except for
5649 * argc, argv which are passed through.
5651 * @param c A net_context structure.
5652 * @param domain_sid The domain sid acquired from the remote server.
5653 * @param cli A cli_state connected to the server.
5654 * @param mem_ctx Talloc context, destroyed on completion of the function.
5655 * @param argc Standard main() style argc.
5656 * @param argv Standard main() style argv. Initial components are already
5657 * stripped.
5659 * @return Normal NTSTATUS return.
5662 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5663 const struct dom_sid *domain_sid,
5664 const char *domain_name,
5665 struct cli_state *cli,
5666 struct rpc_pipe_client *pipe_hnd,
5667 TALLOC_CTX *mem_ctx,
5668 int argc,
5669 const char **argv)
5671 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5672 WERROR result;
5673 const char *msg = N_("This machine will be shutdown shortly");
5674 uint32 timeout = 20;
5675 struct lsa_StringLarge msg_string;
5676 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5678 if (c->opt_comment) {
5679 msg = c->opt_comment;
5681 if (c->opt_timeout) {
5682 timeout = c->opt_timeout;
5685 msg_string.string = msg;
5687 /* create an entry */
5688 status = dcerpc_initshutdown_Init(b, mem_ctx, NULL,
5689 &msg_string, timeout, c->opt_force, c->opt_reboot,
5690 &result);
5691 if (!NT_STATUS_IS_OK(status)) {
5692 return status;
5694 if (W_ERROR_IS_OK(result)) {
5695 d_printf(_("\nShutdown of remote machine succeeded\n"));
5696 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5697 } else {
5698 DEBUG(1,("Shutdown of remote machine failed!\n"));
5700 return werror_to_ntstatus(result);
5704 * Shut down a remote RPC Server via winreg pipe.
5706 * All parameters are provided by the run_rpc_command function, except for
5707 * argc, argv which are passed through.
5709 * @param c A net_context structure.
5710 * @param domain_sid The domain sid acquired from the remote server.
5711 * @param cli A cli_state connected to the server.
5712 * @param mem_ctx Talloc context, destroyed on completion of the function.
5713 * @param argc Standard main() style argc.
5714 * @param argv Standard main() style argv. Initial components are already
5715 * stripped.
5717 * @return Normal NTSTATUS return.
5720 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5721 const struct dom_sid *domain_sid,
5722 const char *domain_name,
5723 struct cli_state *cli,
5724 struct rpc_pipe_client *pipe_hnd,
5725 TALLOC_CTX *mem_ctx,
5726 int argc,
5727 const char **argv)
5729 const char *msg = N_("This machine will be shutdown shortly");
5730 uint32 timeout = 20;
5731 struct lsa_StringLarge msg_string;
5732 NTSTATUS result;
5733 WERROR werr;
5734 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5736 if (c->opt_comment) {
5737 msg = c->opt_comment;
5739 msg_string.string = msg;
5741 if (c->opt_timeout) {
5742 timeout = c->opt_timeout;
5745 /* create an entry */
5746 result = dcerpc_winreg_InitiateSystemShutdown(b, mem_ctx, NULL,
5747 &msg_string, timeout, c->opt_force, c->opt_reboot,
5748 &werr);
5749 if (!NT_STATUS_IS_OK(result)) {
5750 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5751 return result;
5754 if (W_ERROR_IS_OK(werr)) {
5755 d_printf(_("\nShutdown of remote machine succeeded\n"));
5756 } else {
5757 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5758 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5759 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5760 else
5761 d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5764 return werror_to_ntstatus(werr);
5768 * Shut down a remote RPC server.
5770 * @param argc Standard main() style argc.
5771 * @param argv Standard main() style argv. Initial components are already
5772 * stripped.
5774 * @return A shell status integer (0 for success).
5777 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5779 int rc = -1;
5781 if (c->display_usage) {
5782 d_printf( "%s\n"
5783 "net rpc shutdown\n"
5784 " %s\n",
5785 _("Usage:"),
5786 _("Shut down a remote RPC server"));
5787 return 0;
5790 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown, 0,
5791 rpc_init_shutdown_internals, argc, argv);
5793 if (rc) {
5794 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5795 rc = run_rpc_command(c, NULL, &ndr_table_winreg, 0,
5796 rpc_reg_shutdown_internals, argc, argv);
5799 return rc;
5802 /***************************************************************************
5803 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5804 ***************************************************************************/
5807 * Add interdomain trust account to the RPC server.
5808 * All parameters (except for argc and argv) are passed by run_rpc_command
5809 * function.
5811 * @param c A net_context structure.
5812 * @param domain_sid The domain sid acquired from the server.
5813 * @param cli A cli_state connected to the server.
5814 * @param mem_ctx Talloc context, destroyed on completion of the function.
5815 * @param argc Standard main() style argc.
5816 * @param argv Standard main() style argv. Initial components are already
5817 * stripped.
5819 * @return normal NTSTATUS return code.
5822 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
5823 const struct dom_sid *domain_sid,
5824 const char *domain_name,
5825 struct cli_state *cli,
5826 struct rpc_pipe_client *pipe_hnd,
5827 TALLOC_CTX *mem_ctx,
5828 int argc,
5829 const char **argv)
5831 struct policy_handle connect_pol, domain_pol, user_pol;
5832 NTSTATUS status, result;
5833 char *acct_name;
5834 struct lsa_String lsa_acct_name;
5835 uint32 acb_info;
5836 uint32 acct_flags=0;
5837 uint32 user_rid;
5838 uint32_t access_granted = 0;
5839 union samr_UserInfo info;
5840 unsigned int orig_timeout;
5841 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5842 DATA_BLOB session_key = data_blob_null;
5844 if (argc != 2) {
5845 d_printf("%s\n%s",
5846 _("Usage:"),
5847 _(" net rpc trustdom add <domain_name> "
5848 "<trust password>\n"));
5849 return NT_STATUS_INVALID_PARAMETER;
5853 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5856 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5857 return NT_STATUS_NO_MEMORY;
5860 if (!strupper_m(acct_name)) {
5861 SAFE_FREE(acct_name);
5862 return NT_STATUS_INVALID_PARAMETER;
5865 init_lsa_String(&lsa_acct_name, acct_name);
5867 status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
5868 if (!NT_STATUS_IS_OK(status)) {
5869 DEBUG(0,("Error getting session_key of SAM pipe. Error was %s\n",
5870 nt_errstr(status)));
5871 goto done;
5874 /* Get samr policy handle */
5875 status = dcerpc_samr_Connect2(b, mem_ctx,
5876 pipe_hnd->desthost,
5877 MAXIMUM_ALLOWED_ACCESS,
5878 &connect_pol,
5879 &result);
5880 if (!NT_STATUS_IS_OK(status)) {
5881 goto done;
5883 if (!NT_STATUS_IS_OK(result)) {
5884 status = result;
5885 goto done;
5888 /* Get domain policy handle */
5889 status = dcerpc_samr_OpenDomain(b, mem_ctx,
5890 &connect_pol,
5891 MAXIMUM_ALLOWED_ACCESS,
5892 discard_const_p(struct dom_sid2, domain_sid),
5893 &domain_pol,
5894 &result);
5895 if (!NT_STATUS_IS_OK(status)) {
5896 goto done;
5898 if (!NT_STATUS_IS_OK(result)) {
5899 status = result;
5900 goto done;
5903 /* This call can take a long time - allow the server to time out.
5904 * 35 seconds should do it. */
5906 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5908 /* Create trusting domain's account */
5909 acb_info = ACB_NORMAL;
5910 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5911 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5912 SAMR_USER_ACCESS_SET_PASSWORD |
5913 SAMR_USER_ACCESS_GET_ATTRIBUTES |
5914 SAMR_USER_ACCESS_SET_ATTRIBUTES;
5916 status = dcerpc_samr_CreateUser2(b, mem_ctx,
5917 &domain_pol,
5918 &lsa_acct_name,
5919 acb_info,
5920 acct_flags,
5921 &user_pol,
5922 &access_granted,
5923 &user_rid,
5924 &result);
5925 if (!NT_STATUS_IS_OK(status)) {
5926 goto done;
5928 /* And restore our original timeout. */
5929 rpccli_set_timeout(pipe_hnd, orig_timeout);
5931 if (!NT_STATUS_IS_OK(result)) {
5932 status = result;
5933 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
5934 acct_name, nt_errstr(result));
5935 goto done;
5939 struct samr_CryptPassword crypt_pwd;
5941 ZERO_STRUCT(info.info23);
5943 init_samr_CryptPassword(argv[1],
5944 &session_key,
5945 &crypt_pwd);
5947 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
5948 SAMR_FIELD_NT_PASSWORD_PRESENT;
5949 info.info23.info.acct_flags = ACB_DOMTRUST;
5950 info.info23.password = crypt_pwd;
5952 status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
5953 &user_pol,
5955 &info,
5956 &result);
5957 if (!NT_STATUS_IS_OK(status)) {
5958 goto done;
5961 if (!NT_STATUS_IS_OK(result)) {
5962 status = result;
5963 DEBUG(0,("Could not set trust account password: %s\n",
5964 nt_errstr(result)));
5965 goto done;
5969 done:
5970 SAFE_FREE(acct_name);
5971 data_blob_clear_free(&session_key);
5972 return status;
5976 * Create interdomain trust account for a remote domain.
5978 * @param argc Standard argc.
5979 * @param argv Standard argv without initial components.
5981 * @return Integer status (0 means success).
5984 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5986 if (argc > 0 && !c->display_usage) {
5987 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
5988 rpc_trustdom_add_internals, argc, argv);
5989 } else {
5990 d_printf("%s\n%s",
5991 _("Usage:"),
5992 _("net rpc trustdom add <domain_name> <trust "
5993 "password>\n"));
5994 return -1;
6000 * Remove interdomain trust account from the RPC server.
6001 * All parameters (except for argc and argv) are passed by run_rpc_command
6002 * function.
6004 * @param c A net_context structure.
6005 * @param domain_sid The domain sid acquired from the server.
6006 * @param cli A cli_state connected to the server.
6007 * @param mem_ctx Talloc context, destroyed on completion of the function.
6008 * @param argc Standard main() style argc.
6009 * @param argv Standard main() style argv. Initial components are already
6010 * stripped.
6012 * @return normal NTSTATUS return code.
6015 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
6016 const struct dom_sid *domain_sid,
6017 const char *domain_name,
6018 struct cli_state *cli,
6019 struct rpc_pipe_client *pipe_hnd,
6020 TALLOC_CTX *mem_ctx,
6021 int argc,
6022 const char **argv)
6024 struct policy_handle connect_pol, domain_pol, user_pol;
6025 NTSTATUS status, result;
6026 char *acct_name;
6027 struct dom_sid trust_acct_sid;
6028 struct samr_Ids user_rids, name_types;
6029 struct lsa_String lsa_acct_name;
6030 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6032 if (argc != 1) {
6033 d_printf("%s\n%s",
6034 _("Usage:"),
6035 _(" net rpc trustdom del <domain_name>\n"));
6036 return NT_STATUS_INVALID_PARAMETER;
6040 * Make valid trusting domain account (ie. uppercased and with '$' appended)
6042 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
6044 if (acct_name == NULL)
6045 return NT_STATUS_NO_MEMORY;
6047 if (!strupper_m(acct_name)) {
6048 TALLOC_FREE(acct_name);
6049 return NT_STATUS_INVALID_PARAMETER;
6052 /* Get samr policy handle */
6053 status = dcerpc_samr_Connect2(b, mem_ctx,
6054 pipe_hnd->desthost,
6055 MAXIMUM_ALLOWED_ACCESS,
6056 &connect_pol,
6057 &result);
6058 if (!NT_STATUS_IS_OK(status)) {
6059 goto done;
6061 if (!NT_STATUS_IS_OK(result)) {
6062 status = result;
6063 goto done;
6066 /* Get domain policy handle */
6067 status = dcerpc_samr_OpenDomain(b, mem_ctx,
6068 &connect_pol,
6069 MAXIMUM_ALLOWED_ACCESS,
6070 discard_const_p(struct dom_sid2, domain_sid),
6071 &domain_pol,
6072 &result);
6073 if (!NT_STATUS_IS_OK(status)) {
6074 goto done;
6076 if (!NT_STATUS_IS_OK(result)) {
6077 status = result;
6078 goto done;
6081 init_lsa_String(&lsa_acct_name, acct_name);
6083 status = dcerpc_samr_LookupNames(b, mem_ctx,
6084 &domain_pol,
6086 &lsa_acct_name,
6087 &user_rids,
6088 &name_types,
6089 &result);
6090 if (!NT_STATUS_IS_OK(status)) {
6091 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6092 "failed %s\n"),
6093 acct_name, nt_errstr(status));
6094 goto done;
6096 if (!NT_STATUS_IS_OK(result)) {
6097 status = result;
6098 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6099 "failed %s\n"),
6100 acct_name, nt_errstr(result) );
6101 goto done;
6103 if (user_rids.count != 1) {
6104 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6105 goto done;
6107 if (name_types.count != 1) {
6108 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
6109 goto done;
6112 status = dcerpc_samr_OpenUser(b, mem_ctx,
6113 &domain_pol,
6114 MAXIMUM_ALLOWED_ACCESS,
6115 user_rids.ids[0],
6116 &user_pol,
6117 &result);
6118 if (!NT_STATUS_IS_OK(status)) {
6119 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6120 "%s\n"),
6121 acct_name, nt_errstr(status) );
6122 goto done;
6125 if (!NT_STATUS_IS_OK(result)) {
6126 status = result;
6127 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6128 "%s\n"),
6129 acct_name, nt_errstr(result) );
6130 goto done;
6133 /* append the rid to the domain sid */
6134 if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
6135 goto done;
6138 /* remove the sid */
6140 status = dcerpc_samr_RemoveMemberFromForeignDomain(b, mem_ctx,
6141 &user_pol,
6142 &trust_acct_sid,
6143 &result);
6144 if (!NT_STATUS_IS_OK(status)) {
6145 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6146 " on user %s failed %s\n"),
6147 acct_name, nt_errstr(status));
6148 goto done;
6150 if (!NT_STATUS_IS_OK(result)) {
6151 status = result;
6152 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6153 " on user %s failed %s\n"),
6154 acct_name, nt_errstr(result) );
6155 goto done;
6159 /* Delete user */
6161 status = dcerpc_samr_DeleteUser(b, mem_ctx,
6162 &user_pol,
6163 &result);
6164 if (!NT_STATUS_IS_OK(status)) {
6165 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6166 "%s\n"),
6167 acct_name, nt_errstr(status));
6168 goto done;
6171 if (!NT_STATUS_IS_OK(result)) {
6172 result = status;
6173 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6174 "%s\n"),
6175 acct_name, nt_errstr(result) );
6176 goto done;
6179 if (!NT_STATUS_IS_OK(result)) {
6180 d_printf(_("Could not set trust account password: %s\n"),
6181 nt_errstr(result));
6182 goto done;
6185 done:
6186 return status;
6190 * Delete interdomain trust account for a remote domain.
6192 * @param argc Standard argc.
6193 * @param argv Standard argv without initial components.
6195 * @return Integer status (0 means success).
6198 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
6200 if (argc > 0 && !c->display_usage) {
6201 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
6202 rpc_trustdom_del_internals, argc, argv);
6203 } else {
6204 d_printf("%s\n%s",
6205 _("Usage:"),
6206 _("net rpc trustdom del <domain>\n"));
6207 return -1;
6211 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
6212 struct cli_state *cli,
6213 TALLOC_CTX *mem_ctx,
6214 const char *domain_name)
6216 char *dc_name = NULL;
6217 const char *buffer = NULL;
6218 struct rpc_pipe_client *netr;
6219 NTSTATUS status;
6220 WERROR result;
6221 struct dcerpc_binding_handle *b;
6223 /* Use NetServerEnum2 */
6225 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
6226 SAFE_FREE(dc_name);
6227 return NT_STATUS_OK;
6230 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
6231 for domain %s\n", domain_name));
6233 /* Try netr_GetDcName */
6235 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
6236 &netr);
6237 if (!NT_STATUS_IS_OK(status)) {
6238 return status;
6241 b = netr->binding_handle;
6243 status = dcerpc_netr_GetDcName(b, mem_ctx,
6244 netr->desthost,
6245 domain_name,
6246 &buffer,
6247 &result);
6248 TALLOC_FREE(netr);
6250 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
6251 return status;
6254 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
6255 for domain %s\n", domain_name));
6257 if (!NT_STATUS_IS_OK(status)) {
6258 return status;
6261 return werror_to_ntstatus(result);
6265 * Establish trust relationship to a trusting domain.
6266 * Interdomain account must already be created on remote PDC.
6268 * @param c A net_context structure.
6269 * @param argc Standard argc.
6270 * @param argv Standard argv without initial components.
6272 * @return Integer status (0 means success).
6275 static int rpc_trustdom_establish(struct net_context *c, int argc,
6276 const char **argv)
6278 struct cli_state *cli = NULL;
6279 struct sockaddr_storage server_ss;
6280 struct rpc_pipe_client *pipe_hnd = NULL;
6281 struct policy_handle connect_hnd;
6282 TALLOC_CTX *mem_ctx;
6283 NTSTATUS nt_status, result;
6284 struct dom_sid *domain_sid;
6286 char* domain_name;
6287 char* acct_name;
6288 fstring pdc_name;
6289 union lsa_PolicyInformation *info = NULL;
6290 struct dcerpc_binding_handle *b;
6293 * Connect to \\server\ipc$ as 'our domain' account with password
6296 if (argc != 1 || c->display_usage) {
6297 d_printf("%s\n%s",
6298 _("Usage:"),
6299 _("net rpc trustdom establish <domain_name>\n"));
6300 return -1;
6303 domain_name = smb_xstrdup(argv[0]);
6304 if (!strupper_m(domain_name)) {
6305 SAFE_FREE(domain_name);
6306 return -1;
6309 /* account name used at first is our domain's name with '$' */
6310 if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
6311 return -1;
6313 if (!strupper_m(acct_name)) {
6314 SAFE_FREE(domain_name);
6315 SAFE_FREE(acct_name);
6316 return -1;
6320 * opt_workgroup will be used by connection functions further,
6321 * hence it should be set to remote domain name instead of ours
6323 if (c->opt_workgroup) {
6324 c->opt_workgroup = smb_xstrdup(domain_name);
6327 c->opt_user_name = acct_name;
6329 /* find the domain controller */
6330 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
6331 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
6332 return -1;
6335 /* connect to ipc$ as username/password */
6336 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
6337 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
6339 /* Is it trusting domain account for sure ? */
6340 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
6341 nt_errstr(nt_status)));
6342 return -1;
6345 /* store who we connected to */
6347 saf_store( domain_name, pdc_name );
6350 * Connect to \\server\ipc$ again (this time anonymously)
6353 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
6354 (char*)pdc_name);
6356 if (NT_STATUS_IS_ERR(nt_status)) {
6357 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
6358 domain_name, nt_errstr(nt_status)));
6359 return -1;
6362 if (!(mem_ctx = talloc_init("establishing trust relationship to "
6363 "domain %s", domain_name))) {
6364 DEBUG(0, ("talloc_init() failed\n"));
6365 cli_shutdown(cli);
6366 return -1;
6369 /* Make sure we're talking to a proper server */
6371 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
6372 if (!NT_STATUS_IS_OK(nt_status)) {
6373 cli_shutdown(cli);
6374 talloc_destroy(mem_ctx);
6375 return -1;
6379 * Call LsaOpenPolicy and LsaQueryInfo
6382 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6383 &pipe_hnd);
6384 if (!NT_STATUS_IS_OK(nt_status)) {
6385 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
6386 cli_shutdown(cli);
6387 talloc_destroy(mem_ctx);
6388 return -1;
6391 b = pipe_hnd->binding_handle;
6393 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
6394 &connect_hnd);
6395 if (NT_STATUS_IS_ERR(nt_status)) {
6396 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6397 nt_errstr(nt_status)));
6398 cli_shutdown(cli);
6399 talloc_destroy(mem_ctx);
6400 return -1;
6403 /* Querying info level 5 */
6405 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6406 &connect_hnd,
6407 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6408 &info,
6409 &result);
6410 if (NT_STATUS_IS_ERR(nt_status)) {
6411 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6412 nt_errstr(nt_status)));
6413 cli_shutdown(cli);
6414 talloc_destroy(mem_ctx);
6415 return -1;
6417 if (NT_STATUS_IS_ERR(result)) {
6418 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6419 nt_errstr(result)));
6420 cli_shutdown(cli);
6421 talloc_destroy(mem_ctx);
6422 return -1;
6425 domain_sid = info->account_domain.sid;
6427 /* There should be actually query info level 3 (following nt serv behaviour),
6428 but I still don't know if it's _really_ necessary */
6431 * Store the password in secrets db
6434 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6435 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6436 cli_shutdown(cli);
6437 talloc_destroy(mem_ctx);
6438 return -1;
6442 * Close the pipes and clean up
6445 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6446 if (NT_STATUS_IS_ERR(nt_status)) {
6447 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6448 nt_errstr(nt_status)));
6449 cli_shutdown(cli);
6450 talloc_destroy(mem_ctx);
6451 return -1;
6454 cli_shutdown(cli);
6456 talloc_destroy(mem_ctx);
6458 d_printf(_("Trust to domain %s established\n"), domain_name);
6459 return 0;
6463 * Revoke trust relationship to the remote domain.
6465 * @param c A net_context structure.
6466 * @param argc Standard argc.
6467 * @param argv Standard argv without initial components.
6469 * @return Integer status (0 means success).
6472 static int rpc_trustdom_revoke(struct net_context *c, int argc,
6473 const char **argv)
6475 char* domain_name;
6476 int rc = -1;
6478 if (argc < 1 || c->display_usage) {
6479 d_printf("%s\n%s",
6480 _("Usage:"),
6481 _("net rpc trustdom revoke <domain_name>\n"
6482 " Revoke trust relationship\n"
6483 " domain_name\tName of domain to revoke trust\n"));
6484 return -1;
6487 /* generate upper cased domain name */
6488 domain_name = smb_xstrdup(argv[0]);
6489 if (!strupper_m(domain_name)) {
6490 SAFE_FREE(domain_name);
6491 return -1;
6494 /* delete password of the trust */
6495 if (!pdb_del_trusteddom_pw(domain_name)) {
6496 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6497 domain_name));
6498 goto done;
6501 rc = 0;
6502 done:
6503 SAFE_FREE(domain_name);
6504 return rc;
6507 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6508 const struct dom_sid *domain_sid,
6509 const char *domain_name,
6510 struct cli_state *cli,
6511 struct rpc_pipe_client *pipe_hnd,
6512 TALLOC_CTX *mem_ctx,
6513 int argc,
6514 const char **argv)
6516 fstring str_sid;
6517 if (!sid_to_fstring(str_sid, domain_sid)) {
6518 return NT_STATUS_UNSUCCESSFUL;
6520 d_printf("%s\n", str_sid);
6521 return NT_STATUS_OK;
6524 static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
6526 fstring ascii_sid;
6528 /* convert sid into ascii string */
6529 sid_to_fstring(ascii_sid, dom_sid);
6531 d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
6534 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6535 TALLOC_CTX *mem_ctx,
6536 struct policy_handle *pol,
6537 struct dom_sid dom_sid,
6538 const char *trusted_dom_name)
6540 NTSTATUS nt_status, result;
6541 union lsa_TrustedDomainInfo *info = NULL;
6542 char *cleartextpwd = NULL;
6543 DATA_BLOB session_key;
6544 DATA_BLOB data = data_blob_null;
6545 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
6547 nt_status = dcerpc_lsa_QueryTrustedDomainInfoBySid(b, mem_ctx,
6548 pol,
6549 &dom_sid,
6550 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6551 &info,
6552 &result);
6553 if (NT_STATUS_IS_ERR(nt_status)) {
6554 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6555 nt_errstr(nt_status)));
6556 goto done;
6558 if (NT_STATUS_IS_ERR(result)) {
6559 nt_status = result;
6560 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6561 nt_errstr(result)));
6562 goto done;
6565 data = data_blob(info->password.password->data,
6566 info->password.password->length);
6568 nt_status = cli_get_session_key(mem_ctx, pipe_hnd, &session_key);
6569 if (!NT_STATUS_IS_OK(nt_status)) {
6570 DEBUG(0, ("Could not retrieve session key: %s\n", nt_errstr(nt_status)));
6571 goto done;
6574 cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key);
6575 data_blob_free(&session_key);
6577 if (cleartextpwd == NULL) {
6578 DEBUG(0,("retrieved NULL password\n"));
6579 nt_status = NT_STATUS_UNSUCCESSFUL;
6580 goto done;
6583 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6584 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6585 nt_status = NT_STATUS_UNSUCCESSFUL;
6586 goto done;
6589 #ifdef DEBUG_PASSWORD
6590 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
6591 "password: [%s]\n", trusted_dom_name,
6592 sid_string_dbg(&dom_sid), cleartextpwd));
6593 #endif
6595 done:
6596 SAFE_FREE(cleartextpwd);
6597 data_blob_free(&data);
6599 return nt_status;
6602 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6603 const char **argv)
6605 /* common variables */
6606 TALLOC_CTX* mem_ctx;
6607 struct cli_state *cli = NULL;
6608 struct rpc_pipe_client *pipe_hnd = NULL;
6609 NTSTATUS nt_status, result;
6610 const char *domain_name = NULL;
6611 struct policy_handle connect_hnd;
6612 union lsa_PolicyInformation *info = NULL;
6614 /* trusted domains listing variables */
6615 unsigned int enum_ctx = 0;
6616 int i;
6617 struct lsa_DomainList dom_list;
6618 fstring pdc_name;
6619 struct dcerpc_binding_handle *b;
6621 if (c->display_usage) {
6622 d_printf( "%s\n"
6623 "net rpc trustdom vampire\n"
6624 " %s\n",
6625 _("Usage:"),
6626 _("Vampire trust relationship from remote server"));
6627 return 0;
6631 * Listing trusted domains (stored in secrets.tdb, if local)
6634 mem_ctx = talloc_init("trust relationships vampire");
6637 * set domain and pdc name to local samba server (default)
6638 * or to remote one given in command line
6641 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6642 domain_name = c->opt_workgroup;
6643 c->opt_target_workgroup = c->opt_workgroup;
6644 } else {
6645 fstrcpy(pdc_name, lp_netbios_name());
6646 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6647 c->opt_target_workgroup = domain_name;
6650 /* open \PIPE\lsarpc and open policy handle */
6651 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6652 if (!NT_STATUS_IS_OK(nt_status)) {
6653 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6654 nt_errstr(nt_status)));
6655 talloc_destroy(mem_ctx);
6656 return -1;
6659 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6660 &pipe_hnd);
6661 if (!NT_STATUS_IS_OK(nt_status)) {
6662 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6663 nt_errstr(nt_status) ));
6664 cli_shutdown(cli);
6665 talloc_destroy(mem_ctx);
6666 return -1;
6669 b = pipe_hnd->binding_handle;
6671 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6672 &connect_hnd);
6673 if (NT_STATUS_IS_ERR(nt_status)) {
6674 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6675 nt_errstr(nt_status)));
6676 cli_shutdown(cli);
6677 talloc_destroy(mem_ctx);
6678 return -1;
6681 /* query info level 5 to obtain sid of a domain being queried */
6682 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6683 &connect_hnd,
6684 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6685 &info,
6686 &result);
6688 if (NT_STATUS_IS_ERR(nt_status)) {
6689 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6690 nt_errstr(nt_status)));
6691 cli_shutdown(cli);
6692 talloc_destroy(mem_ctx);
6693 return -1;
6695 if (NT_STATUS_IS_ERR(result)) {
6696 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6697 nt_errstr(result)));
6698 cli_shutdown(cli);
6699 talloc_destroy(mem_ctx);
6700 return -1;
6704 * Keep calling LsaEnumTrustdom over opened pipe until
6705 * the end of enumeration is reached
6708 d_printf(_("Vampire trusted domains:\n\n"));
6710 do {
6711 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
6712 &connect_hnd,
6713 &enum_ctx,
6714 &dom_list,
6715 (uint32_t)-1,
6716 &result);
6717 if (NT_STATUS_IS_ERR(nt_status)) {
6718 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6719 nt_errstr(nt_status)));
6720 cli_shutdown(cli);
6721 talloc_destroy(mem_ctx);
6722 return -1;
6724 if (NT_STATUS_IS_ERR(result)) {
6725 nt_status = result;
6726 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6727 nt_errstr(result)));
6728 cli_shutdown(cli);
6729 talloc_destroy(mem_ctx);
6730 return -1;
6734 for (i = 0; i < dom_list.count; i++) {
6736 print_trusted_domain(dom_list.domains[i].sid,
6737 dom_list.domains[i].name.string);
6739 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
6740 *dom_list.domains[i].sid,
6741 dom_list.domains[i].name.string);
6742 if (!NT_STATUS_IS_OK(nt_status)) {
6743 cli_shutdown(cli);
6744 talloc_destroy(mem_ctx);
6745 return -1;
6750 * in case of no trusted domains say something rather
6751 * than just display blank line
6753 if (!dom_list.count) d_printf(_("none\n"));
6755 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6757 /* close this connection before doing next one */
6758 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6759 if (NT_STATUS_IS_ERR(nt_status)) {
6760 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6761 nt_errstr(nt_status)));
6762 cli_shutdown(cli);
6763 talloc_destroy(mem_ctx);
6764 return -1;
6767 /* close lsarpc pipe and connection to IPC$ */
6768 cli_shutdown(cli);
6770 talloc_destroy(mem_ctx);
6771 return 0;
6774 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6776 /* common variables */
6777 TALLOC_CTX* mem_ctx;
6778 struct cli_state *cli = NULL, *remote_cli = NULL;
6779 struct rpc_pipe_client *pipe_hnd = NULL;
6780 NTSTATUS nt_status, result;
6781 const char *domain_name = NULL;
6782 struct dom_sid *queried_dom_sid;
6783 int ascii_dom_name_len;
6784 struct policy_handle connect_hnd;
6785 union lsa_PolicyInformation *info = NULL;
6786 struct dcerpc_binding_handle *b = NULL;
6788 /* trusted domains listing variables */
6789 unsigned int num_domains, enum_ctx = 0;
6790 int i;
6791 struct lsa_DomainList dom_list;
6792 fstring pdc_name;
6793 bool found_domain;
6795 /* trusting domains listing variables */
6796 struct policy_handle domain_hnd;
6797 struct samr_SamArray *trusts = NULL;
6799 if (c->display_usage) {
6800 d_printf( "%s\n"
6801 "net rpc trustdom list\n"
6802 " %s\n",
6803 _("Usage:"),
6804 _("List incoming and outgoing trust relationships"));
6805 return 0;
6809 * Listing trusted domains (stored in secrets.tdb, if local)
6812 mem_ctx = talloc_init("trust relationships listing");
6815 * set domain and pdc name to local samba server (default)
6816 * or to remote one given in command line
6819 if (strcasecmp_m(c->opt_workgroup, lp_workgroup())) {
6820 domain_name = c->opt_workgroup;
6821 c->opt_target_workgroup = c->opt_workgroup;
6822 } else {
6823 fstrcpy(pdc_name, lp_netbios_name());
6824 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6825 c->opt_target_workgroup = domain_name;
6828 /* open \PIPE\lsarpc and open policy handle */
6829 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6830 if (!NT_STATUS_IS_OK(nt_status)) {
6831 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6832 nt_errstr(nt_status)));
6833 talloc_destroy(mem_ctx);
6834 return -1;
6837 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6838 &pipe_hnd);
6839 if (!NT_STATUS_IS_OK(nt_status)) {
6840 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6841 nt_errstr(nt_status) ));
6842 cli_shutdown(cli);
6843 talloc_destroy(mem_ctx);
6844 return -1;
6847 b = pipe_hnd->binding_handle;
6849 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6850 &connect_hnd);
6851 if (NT_STATUS_IS_ERR(nt_status)) {
6852 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6853 nt_errstr(nt_status)));
6854 cli_shutdown(cli);
6855 talloc_destroy(mem_ctx);
6856 return -1;
6859 /* query info level 5 to obtain sid of a domain being queried */
6860 nt_status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
6861 &connect_hnd,
6862 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6863 &info,
6864 &result);
6866 if (NT_STATUS_IS_ERR(nt_status)) {
6867 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6868 nt_errstr(nt_status)));
6869 cli_shutdown(cli);
6870 talloc_destroy(mem_ctx);
6871 return -1;
6873 if (NT_STATUS_IS_ERR(result)) {
6874 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6875 nt_errstr(result)));
6876 cli_shutdown(cli);
6877 talloc_destroy(mem_ctx);
6878 return -1;
6881 queried_dom_sid = info->account_domain.sid;
6884 * Keep calling LsaEnumTrustdom over opened pipe until
6885 * the end of enumeration is reached
6888 d_printf(_("Trusted domains list:\n\n"));
6890 found_domain = false;
6892 do {
6893 nt_status = dcerpc_lsa_EnumTrustDom(b, mem_ctx,
6894 &connect_hnd,
6895 &enum_ctx,
6896 &dom_list,
6897 (uint32_t)-1,
6898 &result);
6899 if (NT_STATUS_IS_ERR(nt_status)) {
6900 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6901 nt_errstr(nt_status)));
6902 cli_shutdown(cli);
6903 talloc_destroy(mem_ctx);
6904 return -1;
6906 if (NT_STATUS_IS_ERR(result)) {
6907 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6908 nt_errstr(result)));
6909 cli_shutdown(cli);
6910 talloc_destroy(mem_ctx);
6911 return -1;
6915 for (i = 0; i < dom_list.count; i++) {
6916 print_trusted_domain(dom_list.domains[i].sid,
6917 dom_list.domains[i].name.string);
6918 found_domain = true;
6922 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6925 * in case of no trusted domains say something rather
6926 * than just display blank line
6928 if (!found_domain) {
6929 d_printf(_("none\n"));
6932 /* close this connection before doing next one */
6933 nt_status = dcerpc_lsa_Close(b, mem_ctx, &connect_hnd, &result);
6934 if (NT_STATUS_IS_ERR(nt_status)) {
6935 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6936 nt_errstr(nt_status)));
6937 cli_shutdown(cli);
6938 talloc_destroy(mem_ctx);
6939 return -1;
6942 TALLOC_FREE(pipe_hnd);
6945 * Listing trusting domains (stored in passdb backend, if local)
6948 d_printf(_("\nTrusting domains list:\n\n"));
6951 * Open \PIPE\samr and get needed policy handles
6953 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6954 &pipe_hnd);
6955 if (!NT_STATUS_IS_OK(nt_status)) {
6956 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6957 cli_shutdown(cli);
6958 talloc_destroy(mem_ctx);
6959 return -1;
6962 b = pipe_hnd->binding_handle;
6964 /* SamrConnect2 */
6965 nt_status = dcerpc_samr_Connect2(b, mem_ctx,
6966 pipe_hnd->desthost,
6967 SAMR_ACCESS_LOOKUP_DOMAIN,
6968 &connect_hnd,
6969 &result);
6970 if (!NT_STATUS_IS_OK(nt_status)) {
6971 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6972 nt_errstr(nt_status)));
6973 cli_shutdown(cli);
6974 talloc_destroy(mem_ctx);
6975 return -1;
6977 if (!NT_STATUS_IS_OK(result)) {
6978 nt_status = result;
6979 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6980 nt_errstr(result)));
6981 cli_shutdown(cli);
6982 talloc_destroy(mem_ctx);
6983 return -1;
6986 /* SamrOpenDomain - we have to open domain policy handle in order to be
6987 able to enumerate accounts*/
6988 nt_status = dcerpc_samr_OpenDomain(b, mem_ctx,
6989 &connect_hnd,
6990 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6991 queried_dom_sid,
6992 &domain_hnd,
6993 &result);
6994 if (!NT_STATUS_IS_OK(nt_status)) {
6995 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6996 nt_errstr(nt_status)));
6997 cli_shutdown(cli);
6998 talloc_destroy(mem_ctx);
6999 return -1;
7001 if (!NT_STATUS_IS_OK(result)) {
7002 nt_status = result;
7003 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
7004 nt_errstr(result)));
7005 cli_shutdown(cli);
7006 talloc_destroy(mem_ctx);
7007 return -1;
7011 * perform actual enumeration
7014 found_domain = false;
7016 enum_ctx = 0; /* reset enumeration context from last enumeration */
7017 do {
7019 nt_status = dcerpc_samr_EnumDomainUsers(b, mem_ctx,
7020 &domain_hnd,
7021 &enum_ctx,
7022 ACB_DOMTRUST,
7023 &trusts,
7024 0xffff,
7025 &num_domains,
7026 &result);
7027 if (NT_STATUS_IS_ERR(nt_status)) {
7028 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7029 nt_errstr(nt_status)));
7030 cli_shutdown(cli);
7031 talloc_destroy(mem_ctx);
7032 return -1;
7034 if (NT_STATUS_IS_ERR(result)) {
7035 nt_status = result;
7036 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
7037 nt_errstr(result)));
7038 cli_shutdown(cli);
7039 talloc_destroy(mem_ctx);
7040 return -1;
7043 for (i = 0; i < num_domains; i++) {
7045 char *str = discard_const_p(char, trusts->entries[i].name.string);
7047 found_domain = true;
7050 * get each single domain's sid (do we _really_ need this ?):
7051 * 1) connect to domain's pdc
7052 * 2) query the pdc for domain's sid
7055 /* get rid of '$' tail */
7056 ascii_dom_name_len = strlen(str);
7057 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
7058 str[ascii_dom_name_len - 1] = '\0';
7060 /* set opt_* variables to remote domain */
7061 if (!strupper_m(str)) {
7062 cli_shutdown(cli);
7063 talloc_destroy(mem_ctx);
7064 return -1;
7066 c->opt_workgroup = talloc_strdup(mem_ctx, str);
7067 c->opt_target_workgroup = c->opt_workgroup;
7069 d_printf("%-20s", str);
7071 /* connect to remote domain controller */
7072 nt_status = net_make_ipc_connection(c,
7073 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
7074 &remote_cli);
7075 if (NT_STATUS_IS_OK(nt_status)) {
7076 /* query for domain's sid */
7077 if (run_rpc_command(
7078 c, remote_cli,
7079 &ndr_table_lsarpc, 0,
7080 rpc_query_domain_sid, argc,
7081 argv))
7082 d_printf(_("strange - couldn't get domain's sid\n"));
7084 cli_shutdown(remote_cli);
7086 } else {
7087 d_fprintf(stderr, _("domain controller is not "
7088 "responding: %s\n"),
7089 nt_errstr(nt_status));
7090 d_printf(_("couldn't get domain's sid\n"));
7094 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
7096 if (!found_domain) {
7097 d_printf("none\n");
7100 /* close opened samr and domain policy handles */
7101 nt_status = dcerpc_samr_Close(b, mem_ctx, &domain_hnd, &result);
7102 if (!NT_STATUS_IS_OK(nt_status)) {
7103 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
7106 nt_status = dcerpc_samr_Close(b, mem_ctx, &connect_hnd, &result);
7107 if (!NT_STATUS_IS_OK(nt_status)) {
7108 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
7111 /* close samr pipe and connection to IPC$ */
7112 cli_shutdown(cli);
7114 talloc_destroy(mem_ctx);
7115 return 0;
7119 * Entrypoint for 'net rpc trustdom' code.
7121 * @param argc Standard argc.
7122 * @param argv Standard argv without initial components.
7124 * @return Integer status (0 means success).
7127 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
7129 struct functable func[] = {
7131 "add",
7132 rpc_trustdom_add,
7133 NET_TRANSPORT_RPC,
7134 N_("Add trusting domain's account"),
7135 N_("net rpc trustdom add\n"
7136 " Add trusting domain's account")
7139 "del",
7140 rpc_trustdom_del,
7141 NET_TRANSPORT_RPC,
7142 N_("Remove trusting domain's account"),
7143 N_("net rpc trustdom del\n"
7144 " Remove trusting domain's account")
7147 "establish",
7148 rpc_trustdom_establish,
7149 NET_TRANSPORT_RPC,
7150 N_("Establish outgoing trust relationship"),
7151 N_("net rpc trustdom establish\n"
7152 " Establish outgoing trust relationship")
7155 "revoke",
7156 rpc_trustdom_revoke,
7157 NET_TRANSPORT_RPC,
7158 N_("Revoke outgoing trust relationship"),
7159 N_("net rpc trustdom revoke\n"
7160 " Revoke outgoing trust relationship")
7163 "list",
7164 rpc_trustdom_list,
7165 NET_TRANSPORT_RPC,
7166 N_("List in- and outgoing domain trusts"),
7167 N_("net rpc trustdom list\n"
7168 " List in- and outgoing domain trusts")
7171 "vampire",
7172 rpc_trustdom_vampire,
7173 NET_TRANSPORT_RPC,
7174 N_("Vampire trusts from remote server"),
7175 N_("net rpc trustdom vampire\n"
7176 " Vampire trusts from remote server")
7178 {NULL, NULL, 0, NULL, NULL}
7181 return net_run_function(c, argc, argv, "net rpc trustdom", func);
7185 * Check if a server will take rpc commands
7186 * @param flags Type of server to connect to (PDC, DMB, localhost)
7187 * if the host is not explicitly specified
7188 * @return bool (true means rpc supported)
7190 bool net_rpc_check(struct net_context *c, unsigned flags)
7192 struct cli_state *cli;
7193 bool ret = false;
7194 struct sockaddr_storage server_ss;
7195 char *server_name = NULL;
7196 NTSTATUS status;
7198 /* flags (i.e. server type) may depend on command */
7199 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
7200 return false;
7202 status = cli_connect_nb(server_name, &server_ss, 0, 0x20,
7203 lp_netbios_name(), SMB_SIGNING_DEFAULT,
7204 0, &cli);
7205 if (!NT_STATUS_IS_OK(status)) {
7206 return false;
7208 status = smbXcli_negprot(cli->conn, cli->timeout, PROTOCOL_CORE,
7209 PROTOCOL_NT1);
7210 if (!NT_STATUS_IS_OK(status))
7211 goto done;
7212 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_NT1)
7213 goto done;
7215 ret = true;
7216 done:
7217 cli_shutdown(cli);
7218 return ret;
7221 /* dump sam database via samsync rpc calls */
7222 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
7223 if (c->display_usage) {
7224 d_printf( "%s\n"
7225 "net rpc samdump\n"
7226 " %s\n",
7227 _("Usage:"),
7228 _("Dump remote SAM database"));
7229 return 0;
7232 return run_rpc_command(c, NULL, &ndr_table_netlogon,
7233 NET_FLAGS_ANONYMOUS,
7234 rpc_samdump_internals, argc, argv);
7237 /* syncronise sam database via samsync rpc calls */
7238 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
7240 struct functable func[] = {
7242 "ldif",
7243 rpc_vampire_ldif,
7244 NET_TRANSPORT_RPC,
7245 N_("Dump remote SAM database to ldif"),
7246 N_("net rpc vampire ldif\n"
7247 " Dump remote SAM database to LDIF file or "
7248 "stdout")
7251 "keytab",
7252 rpc_vampire_keytab,
7253 NET_TRANSPORT_RPC,
7254 N_("Dump remote SAM database to Kerberos Keytab"),
7255 N_("net rpc vampire keytab\n"
7256 " Dump remote SAM database to Kerberos keytab "
7257 "file")
7260 "passdb",
7261 rpc_vampire_passdb,
7262 NET_TRANSPORT_RPC,
7263 N_("Dump remote SAM database to passdb"),
7264 N_("net rpc vampire passdb\n"
7265 " Dump remote SAM database to passdb")
7268 {NULL, NULL, 0, NULL, NULL}
7271 if (argc == 0) {
7272 if (c->display_usage) {
7273 d_printf( "%s\n"
7274 "net rpc vampire\n"
7275 " %s\n",
7276 _("Usage:"),
7277 _("Vampire remote SAM database"));
7278 return 0;
7281 return rpc_vampire_passdb(c, argc, argv);
7284 return net_run_function(c, argc, argv, "net rpc vampire", func);
7288 * Migrate everything from a print server.
7290 * @param c A net_context structure.
7291 * @param argc Standard main() style argc.
7292 * @param argv Standard main() style argv. Initial components are already
7293 * stripped.
7295 * @return A shell status integer (0 for success).
7297 * The order is important !
7298 * To successfully add drivers the print queues have to exist !
7299 * Applying ACLs should be the last step, because you're easily locked out.
7302 static int rpc_printer_migrate_all(struct net_context *c, int argc,
7303 const char **argv)
7305 int ret;
7307 if (c->display_usage) {
7308 d_printf( "%s\n"
7309 "net rpc printer migrate all\n"
7310 " %s\n",
7311 _("Usage:"),
7312 _("Migrate everything from a print server"));
7313 return 0;
7316 if (!c->opt_host) {
7317 d_printf(_("no server to migrate\n"));
7318 return -1;
7321 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7322 rpc_printer_migrate_printers_internals, argc,
7323 argv);
7324 if (ret)
7325 return ret;
7327 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7328 rpc_printer_migrate_drivers_internals, argc,
7329 argv);
7330 if (ret)
7331 return ret;
7333 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7334 rpc_printer_migrate_forms_internals, argc, argv);
7335 if (ret)
7336 return ret;
7338 ret = run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7339 rpc_printer_migrate_settings_internals, argc,
7340 argv);
7341 if (ret)
7342 return ret;
7344 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7345 rpc_printer_migrate_security_internals, argc,
7346 argv);
7351 * Migrate print drivers from a print server.
7353 * @param c A net_context structure.
7354 * @param argc Standard main() style argc.
7355 * @param argv Standard main() style argv. Initial components are already
7356 * stripped.
7358 * @return A shell status integer (0 for success).
7360 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
7361 const char **argv)
7363 if (c->display_usage) {
7364 d_printf( "%s\n"
7365 "net rpc printer migrate drivers\n"
7366 " %s\n",
7367 _("Usage:"),
7368 _("Migrate print-drivers from a print-server"));
7369 return 0;
7372 if (!c->opt_host) {
7373 d_printf(_("no server to migrate\n"));
7374 return -1;
7377 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7378 rpc_printer_migrate_drivers_internals,
7379 argc, argv);
7383 * Migrate print-forms from a print-server.
7385 * @param c A net_context structure.
7386 * @param argc Standard main() style argc.
7387 * @param argv Standard main() style argv. Initial components are already
7388 * stripped.
7390 * @return A shell status integer (0 for success).
7392 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
7393 const char **argv)
7395 if (c->display_usage) {
7396 d_printf( "%s\n"
7397 "net rpc printer migrate forms\n"
7398 " %s\n",
7399 _("Usage:"),
7400 _("Migrate print-forms from a print-server"));
7401 return 0;
7404 if (!c->opt_host) {
7405 d_printf(_("no server to migrate\n"));
7406 return -1;
7409 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7410 rpc_printer_migrate_forms_internals,
7411 argc, argv);
7415 * Migrate printers from a print-server.
7417 * @param c A net_context structure.
7418 * @param argc Standard main() style argc.
7419 * @param argv Standard main() style argv. Initial components are already
7420 * stripped.
7422 * @return A shell status integer (0 for success).
7424 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
7425 const char **argv)
7427 if (c->display_usage) {
7428 d_printf( "%s\n"
7429 "net rpc printer migrate printers\n"
7430 " %s\n",
7431 _("Usage:"),
7432 _("Migrate printers from a print-server"));
7433 return 0;
7436 if (!c->opt_host) {
7437 d_printf(_("no server to migrate\n"));
7438 return -1;
7441 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7442 rpc_printer_migrate_printers_internals,
7443 argc, argv);
7447 * Migrate printer-ACLs from a print-server
7449 * @param c A net_context structure.
7450 * @param argc Standard main() style argc.
7451 * @param argv Standard main() style argv. Initial components are already
7452 * stripped.
7454 * @return A shell status integer (0 for success).
7456 static int rpc_printer_migrate_security(struct net_context *c, int argc,
7457 const char **argv)
7459 if (c->display_usage) {
7460 d_printf( "%s\n"
7461 "net rpc printer migrate security\n"
7462 " %s\n",
7463 _("Usage:"),
7464 _("Migrate printer-ACLs from a print-server"));
7465 return 0;
7468 if (!c->opt_host) {
7469 d_printf(_("no server to migrate\n"));
7470 return -1;
7473 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7474 rpc_printer_migrate_security_internals,
7475 argc, argv);
7479 * Migrate printer-settings from a print-server.
7481 * @param c A net_context structure.
7482 * @param argc Standard main() style argc.
7483 * @param argv Standard main() style argv. Initial components are already
7484 * stripped.
7486 * @return A shell status integer (0 for success).
7488 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
7489 const char **argv)
7491 if (c->display_usage) {
7492 d_printf( "%s\n"
7493 "net rpc printer migrate settings\n"
7494 " %s\n",
7495 _("Usage:"),
7496 _("Migrate printer-settings from a "
7497 "print-server"));
7498 return 0;
7501 if (!c->opt_host) {
7502 d_printf(_("no server to migrate\n"));
7503 return -1;
7506 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7507 rpc_printer_migrate_settings_internals,
7508 argc, argv);
7512 * 'net rpc printer' entrypoint.
7514 * @param c A net_context structure.
7515 * @param argc Standard main() style argc.
7516 * @param argv Standard main() style argv. Initial components are already
7517 * stripped.
7520 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
7523 /* ouch: when addriver and setdriver are called from within
7524 rpc_printer_migrate_drivers_internals, the printer-queue already
7525 *has* to exist */
7527 struct functable func[] = {
7529 "all",
7530 rpc_printer_migrate_all,
7531 NET_TRANSPORT_RPC,
7532 N_("Migrate all from remote to local print server"),
7533 N_("net rpc printer migrate all\n"
7534 " Migrate all from remote to local print server")
7537 "drivers",
7538 rpc_printer_migrate_drivers,
7539 NET_TRANSPORT_RPC,
7540 N_("Migrate drivers to local server"),
7541 N_("net rpc printer migrate drivers\n"
7542 " Migrate drivers to local server")
7545 "forms",
7546 rpc_printer_migrate_forms,
7547 NET_TRANSPORT_RPC,
7548 N_("Migrate froms to local server"),
7549 N_("net rpc printer migrate forms\n"
7550 " Migrate froms to local server")
7553 "printers",
7554 rpc_printer_migrate_printers,
7555 NET_TRANSPORT_RPC,
7556 N_("Migrate printers to local server"),
7557 N_("net rpc printer migrate printers\n"
7558 " Migrate printers to local server")
7561 "security",
7562 rpc_printer_migrate_security,
7563 NET_TRANSPORT_RPC,
7564 N_("Mirgate printer ACLs to local server"),
7565 N_("net rpc printer migrate security\n"
7566 " Mirgate printer ACLs to local server")
7569 "settings",
7570 rpc_printer_migrate_settings,
7571 NET_TRANSPORT_RPC,
7572 N_("Migrate printer settings to local server"),
7573 N_("net rpc printer migrate settings\n"
7574 " Migrate printer settings to local server")
7576 {NULL, NULL, 0, NULL, NULL}
7579 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7584 * List printers on a remote RPC server.
7586 * @param c A net_context structure.
7587 * @param argc Standard main() style argc.
7588 * @param argv Standard main() style argv. Initial components are already
7589 * stripped.
7591 * @return A shell status integer (0 for success).
7593 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7595 if (c->display_usage) {
7596 d_printf( "%s\n"
7597 "net rpc printer list\n"
7598 " %s\n",
7599 _("Usage:"),
7600 _("List printers on a remote RPC server"));
7601 return 0;
7604 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7605 rpc_printer_list_internals,
7606 argc, argv);
7610 * List printer-drivers on a remote RPC server.
7612 * @param c A net_context structure.
7613 * @param argc Standard main() style argc.
7614 * @param argv Standard main() style argv. Initial components are already
7615 * stripped.
7617 * @return A shell status integer (0 for success).
7619 static int rpc_printer_driver_list(struct net_context *c, int argc,
7620 const char **argv)
7622 if (c->display_usage) {
7623 d_printf( "%s\n"
7624 "net rpc printer driver\n"
7625 " %s\n",
7626 _("Usage:"),
7627 _("List printer-drivers on a remote RPC server"));
7628 return 0;
7631 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7632 rpc_printer_driver_list_internals,
7633 argc, argv);
7637 * Publish printer in ADS via MSRPC.
7639 * @param c A net_context structure.
7640 * @param argc Standard main() style argc.
7641 * @param argv Standard main() style argv. Initial components are already
7642 * stripped.
7644 * @return A shell status integer (0 for success).
7646 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7647 const char **argv)
7649 if (c->display_usage) {
7650 d_printf( "%s\n"
7651 "net rpc printer publish publish\n"
7652 " %s\n",
7653 _("Usage:"),
7654 _("Publish printer in ADS via MSRPC"));
7655 return 0;
7658 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7659 rpc_printer_publish_publish_internals,
7660 argc, argv);
7664 * Update printer in ADS via MSRPC.
7666 * @param c A net_context structure.
7667 * @param argc Standard main() style argc.
7668 * @param argv Standard main() style argv. Initial components are already
7669 * stripped.
7671 * @return A shell status integer (0 for success).
7673 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7675 if (c->display_usage) {
7676 d_printf( "%s\n"
7677 "net rpc printer publish update\n"
7678 " %s\n",
7679 _("Usage:"),
7680 _("Update printer in ADS via MSRPC"));
7681 return 0;
7684 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7685 rpc_printer_publish_update_internals,
7686 argc, argv);
7690 * UnPublish printer in ADS via MSRPC.
7692 * @param c A net_context structure.
7693 * @param argc Standard main() style argc.
7694 * @param argv Standard main() style argv. Initial components are already
7695 * stripped.
7697 * @return A shell status integer (0 for success).
7699 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7700 const char **argv)
7702 if (c->display_usage) {
7703 d_printf( "%s\n"
7704 "net rpc printer publish unpublish\n"
7705 " %s\n",
7706 _("Usage:\n"),
7707 _("UnPublish printer in ADS via MSRPC"));
7708 return 0;
7711 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7712 rpc_printer_publish_unpublish_internals,
7713 argc, argv);
7717 * List published printers via MSRPC.
7719 * @param c A net_context structure.
7720 * @param argc Standard main() style argc.
7721 * @param argv Standard main() style argv. Initial components are already
7722 * stripped.
7724 * @return A shell status integer (0 for success).
7726 static int rpc_printer_publish_list(struct net_context *c, int argc,
7727 const char **argv)
7729 if (c->display_usage) {
7730 d_printf( "%s\n"
7731 "net rpc printer publish list\n"
7732 " %s\n",
7733 _("Usage:"),
7734 _("List published printers via MSRPC"));
7735 return 0;
7738 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7739 rpc_printer_publish_list_internals,
7740 argc, argv);
7745 * Publish printer in ADS.
7747 * @param c A net_context structure.
7748 * @param argc Standard main() style argc.
7749 * @param argv Standard main() style argv. Initial components are already
7750 * stripped.
7752 * @return A shell status integer (0 for success).
7754 static int rpc_printer_publish(struct net_context *c, int argc,
7755 const char **argv)
7758 struct functable func[] = {
7760 "publish",
7761 rpc_printer_publish_publish,
7762 NET_TRANSPORT_RPC,
7763 N_("Publish printer in AD"),
7764 N_("net rpc printer publish publish\n"
7765 " Publish printer in AD")
7768 "update",
7769 rpc_printer_publish_update,
7770 NET_TRANSPORT_RPC,
7771 N_("Update printer in AD"),
7772 N_("net rpc printer publish update\n"
7773 " Update printer in AD")
7776 "unpublish",
7777 rpc_printer_publish_unpublish,
7778 NET_TRANSPORT_RPC,
7779 N_("Unpublish printer"),
7780 N_("net rpc printer publish unpublish\n"
7781 " Unpublish printer")
7784 "list",
7785 rpc_printer_publish_list,
7786 NET_TRANSPORT_RPC,
7787 N_("List published printers"),
7788 N_("net rpc printer publish list\n"
7789 " List published printers")
7791 {NULL, NULL, 0, NULL, NULL}
7794 if (argc == 0) {
7795 if (c->display_usage) {
7796 d_printf(_("Usage:\n"));
7797 d_printf(_("net rpc printer publish\n"
7798 " List published printers\n"
7799 " Alias of net rpc printer publish "
7800 "list\n"));
7801 net_display_usage_from_functable(func);
7802 return 0;
7804 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7805 rpc_printer_publish_list_internals,
7806 argc, argv);
7809 return net_run_function(c, argc, argv, "net rpc printer publish",func);
7815 * Display rpc printer help page.
7817 * @param c A net_context structure.
7818 * @param argc Standard main() style argc.
7819 * @param argv Standard main() style argv. Initial components are already
7820 * stripped.
7822 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
7824 d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
7825 "\tlists all printers on print-server\n\n"));
7826 d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
7827 "\tlists all printer-drivers on print-server\n\n"));
7828 d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
7829 "\tpublishes printer settings in Active Directory\n"
7830 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
7831 d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
7832 "\n\tmigrates printers from remote to local server\n\n"));
7833 d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
7834 "\n\tmigrates printer-settings from remote to local server\n\n"));
7835 d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
7836 "\n\tmigrates printer-drivers from remote to local server\n\n"));
7837 d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
7838 "\n\tmigrates printer-forms from remote to local server\n\n"));
7839 d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
7840 "\n\tmigrates printer-ACLs from remote to local server\n\n"));
7841 d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
7842 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
7843 "\tremote to local print-server\n\n"));
7844 net_common_methods_usage(c, argc, argv);
7845 net_common_flags_usage(c, argc, argv);
7846 d_printf(_(
7847 "\t-v or --verbose\t\t\tgive verbose output\n"
7848 "\t --destination\t\tmigration target server (default: localhost)\n"));
7850 return -1;
7854 * 'net rpc printer' entrypoint.
7856 * @param c A net_context structure.
7857 * @param argc Standard main() style argc.
7858 * @param argv Standard main() style argv. Initial components are already
7859 * stripped.
7861 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7863 struct functable func[] = {
7865 "list",
7866 rpc_printer_list,
7867 NET_TRANSPORT_RPC,
7868 N_("List all printers on print server"),
7869 N_("net rpc printer list\n"
7870 " List all printers on print server")
7873 "migrate",
7874 rpc_printer_migrate,
7875 NET_TRANSPORT_RPC,
7876 N_("Migrate printer to local server"),
7877 N_("net rpc printer migrate\n"
7878 " Migrate printer to local server")
7881 "driver",
7882 rpc_printer_driver_list,
7883 NET_TRANSPORT_RPC,
7884 N_("List printer drivers"),
7885 N_("net rpc printer driver\n"
7886 " List printer drivers")
7889 "publish",
7890 rpc_printer_publish,
7891 NET_TRANSPORT_RPC,
7892 N_("Publish printer in AD"),
7893 N_("net rpc printer publish\n"
7894 " Publish printer in AD")
7896 {NULL, NULL, 0, NULL, NULL}
7899 if (argc == 0) {
7900 if (c->display_usage) {
7901 d_printf(_("Usage:\n"));
7902 d_printf(_("net rpc printer\n"
7903 " List printers\n"));
7904 net_display_usage_from_functable(func);
7905 return 0;
7907 return run_rpc_command(c, NULL, &ndr_table_spoolss, 0,
7908 rpc_printer_list_internals,
7909 argc, argv);
7912 return net_run_function(c, argc, argv, "net rpc printer", func);
7916 * 'net rpc' entrypoint.
7918 * @param c A net_context structure.
7919 * @param argc Standard main() style argc.
7920 * @param argv Standard main() style argv. Initial components are already
7921 * stripped.
7924 int net_rpc(struct net_context *c, int argc, const char **argv)
7926 NET_API_STATUS status;
7928 struct functable func[] = {
7930 "audit",
7931 net_rpc_audit,
7932 NET_TRANSPORT_RPC,
7933 N_("Modify global audit settings"),
7934 N_("net rpc audit\n"
7935 " Modify global audit settings")
7938 "info",
7939 net_rpc_info,
7940 NET_TRANSPORT_RPC,
7941 N_("Show basic info about a domain"),
7942 N_("net rpc info\n"
7943 " Show basic info about a domain")
7946 "join",
7947 net_rpc_join,
7948 NET_TRANSPORT_RPC,
7949 N_("Join a domain"),
7950 N_("net rpc join\n"
7951 " Join a domain")
7954 "oldjoin",
7955 net_rpc_oldjoin,
7956 NET_TRANSPORT_RPC,
7957 N_("Join a domain created in server manager"),
7958 N_("net rpc oldjoin\n"
7959 " Join a domain created in server manager")
7962 "testjoin",
7963 net_rpc_testjoin,
7964 NET_TRANSPORT_RPC,
7965 N_("Test that a join is valid"),
7966 N_("net rpc testjoin\n"
7967 " Test that a join is valid")
7970 "user",
7971 net_rpc_user,
7972 NET_TRANSPORT_RPC,
7973 N_("List/modify users"),
7974 N_("net rpc user\n"
7975 " List/modify users")
7978 "password",
7979 rpc_user_password,
7980 NET_TRANSPORT_RPC,
7981 N_("Change a user password"),
7982 N_("net rpc password\n"
7983 " Change a user password\n"
7984 " Alias for net rpc user password")
7987 "group",
7988 net_rpc_group,
7989 NET_TRANSPORT_RPC,
7990 N_("List/modify groups"),
7991 N_("net rpc group\n"
7992 " List/modify groups")
7995 "share",
7996 net_rpc_share,
7997 NET_TRANSPORT_RPC,
7998 N_("List/modify shares"),
7999 N_("net rpc share\n"
8000 " List/modify shares")
8003 "file",
8004 net_rpc_file,
8005 NET_TRANSPORT_RPC,
8006 N_("List open files"),
8007 N_("net rpc file\n"
8008 " List open files")
8011 "printer",
8012 net_rpc_printer,
8013 NET_TRANSPORT_RPC,
8014 N_("List/modify printers"),
8015 N_("net rpc printer\n"
8016 " List/modify printers")
8019 "changetrustpw",
8020 net_rpc_changetrustpw,
8021 NET_TRANSPORT_RPC,
8022 N_("Change trust account password"),
8023 N_("net rpc changetrustpw\n"
8024 " Change trust account password")
8027 "trustdom",
8028 rpc_trustdom,
8029 NET_TRANSPORT_RPC,
8030 N_("Modify domain trusts"),
8031 N_("net rpc trustdom\n"
8032 " Modify domain trusts")
8035 "abortshutdown",
8036 rpc_shutdown_abort,
8037 NET_TRANSPORT_RPC,
8038 N_("Abort a remote shutdown"),
8039 N_("net rpc abortshutdown\n"
8040 " Abort a remote shutdown")
8043 "shutdown",
8044 rpc_shutdown,
8045 NET_TRANSPORT_RPC,
8046 N_("Shutdown a remote server"),
8047 N_("net rpc shutdown\n"
8048 " Shutdown a remote server")
8051 "samdump",
8052 rpc_samdump,
8053 NET_TRANSPORT_RPC,
8054 N_("Dump SAM data of remote NT PDC"),
8055 N_("net rpc samdump\n"
8056 " Dump SAM data of remote NT PDC")
8059 "vampire",
8060 rpc_vampire,
8061 NET_TRANSPORT_RPC,
8062 N_("Sync a remote NT PDC's data into local passdb"),
8063 N_("net rpc vampire\n"
8064 " Sync a remote NT PDC's data into local passdb")
8067 "getsid",
8068 net_rpc_getsid,
8069 NET_TRANSPORT_RPC,
8070 N_("Fetch the domain sid into local secrets.tdb"),
8071 N_("net rpc getsid\n"
8072 " Fetch the domain sid into local secrets.tdb")
8075 "rights",
8076 net_rpc_rights,
8077 NET_TRANSPORT_RPC,
8078 N_("Manage privileges assigned to SID"),
8079 N_("net rpc rights\n"
8080 " Manage privileges assigned to SID")
8083 "service",
8084 net_rpc_service,
8085 NET_TRANSPORT_RPC,
8086 N_("Start/stop/query remote services"),
8087 N_("net rpc service\n"
8088 " Start/stop/query remote services")
8091 "registry",
8092 net_rpc_registry,
8093 NET_TRANSPORT_RPC,
8094 N_("Manage registry hives"),
8095 N_("net rpc registry\n"
8096 " Manage registry hives")
8099 "shell",
8100 net_rpc_shell,
8101 NET_TRANSPORT_RPC,
8102 N_("Open interactive shell on remote server"),
8103 N_("net rpc shell\n"
8104 " Open interactive shell on remote server")
8107 "trust",
8108 net_rpc_trust,
8109 NET_TRANSPORT_RPC,
8110 N_("Manage trusts"),
8111 N_("net rpc trust\n"
8112 " Manage trusts")
8115 "conf",
8116 net_rpc_conf,
8117 NET_TRANSPORT_RPC,
8118 N_("Configure a remote samba server"),
8119 N_("net rpc conf\n"
8120 " Configure a remote samba server")
8122 {NULL, NULL, 0, NULL, NULL}
8125 status = libnetapi_net_init(&c->netapi_ctx);
8126 if (status != 0) {
8127 return -1;
8129 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
8130 libnetapi_set_password(c->netapi_ctx, c->opt_password);
8131 if (c->opt_kerberos) {
8132 libnetapi_set_use_kerberos(c->netapi_ctx);
8134 if (c->opt_ccache) {
8135 libnetapi_set_use_ccache(c->netapi_ctx);
8138 return net_run_function(c, argc, argv, "net rpc", func);