talloc: Fixed a doxygen problem with PRINTF_ATTRIBUTE.
[Samba/ekacnet.git] / source3 / utils / net_rpc.c
blob0fd693e582aa16ce7a19995d9b88d736e2131d46
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 "../libcli/auth/libcli_auth.h"
26 #include "../librpc/gen_ndr/cli_samr.h"
27 #include "../librpc/gen_ndr/cli_lsa.h"
28 #include "../librpc/gen_ndr/cli_netlogon.h"
29 #include "../librpc/gen_ndr/cli_srvsvc.h"
30 #include "../librpc/gen_ndr/cli_spoolss.h"
31 #include "../librpc/gen_ndr/cli_initshutdown.h"
32 #include "../librpc/gen_ndr/cli_winreg.h"
34 static int net_mode_share;
35 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask);
37 /**
38 * @file net_rpc.c
40 * @brief RPC based subcommands for the 'net' utility.
42 * This file should contain much of the functionality that used to
43 * be found in rpcclient, execpt that the commands should change
44 * less often, and the fucntionality should be sane (the user is not
45 * expected to know a rid/sid before they conduct an operation etc.)
47 * @todo Perhaps eventually these should be split out into a number
48 * of files, as this could get quite big.
49 **/
52 /**
53 * Many of the RPC functions need the domain sid. This function gets
54 * it at the start of every run
56 * @param cli A cli_state already connected to the remote machine
58 * @return The Domain SID of the remote machine.
59 **/
61 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
62 DOM_SID **domain_sid,
63 const char **domain_name)
65 struct rpc_pipe_client *lsa_pipe = NULL;
66 struct policy_handle pol;
67 NTSTATUS result = NT_STATUS_OK;
68 union lsa_PolicyInformation *info = NULL;
70 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
71 &lsa_pipe);
72 if (!NT_STATUS_IS_OK(result)) {
73 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
74 return result;
77 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
78 SEC_FLAG_MAXIMUM_ALLOWED,
79 &pol);
80 if (!NT_STATUS_IS_OK(result)) {
81 d_fprintf(stderr, "open_policy %s: %s\n",
82 _("failed"),
83 nt_errstr(result));
84 return result;
87 result = rpccli_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx,
88 &pol,
89 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
90 &info);
91 if (!NT_STATUS_IS_OK(result)) {
92 d_fprintf(stderr, "lsaquery %s: %s\n",
93 _("failed"),
94 nt_errstr(result));
95 return result;
98 *domain_name = info->account_domain.name.string;
99 *domain_sid = info->account_domain.sid;
101 rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
102 TALLOC_FREE(lsa_pipe);
104 return NT_STATUS_OK;
108 * Run a single RPC command, from start to finish.
110 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
111 * @param conn_flag a NET_FLAG_ combination. Passed to
112 * net_make_ipc_connection.
113 * @param argc Standard main() style argc.
114 * @param argv Standard main() style argv. Initial components are already
115 * stripped.
116 * @return A shell status integer (0 for success).
119 int run_rpc_command(struct net_context *c,
120 struct cli_state *cli_arg,
121 const struct ndr_syntax_id *interface,
122 int conn_flags,
123 rpc_command_fn fn,
124 int argc,
125 const char **argv)
127 struct cli_state *cli = NULL;
128 struct rpc_pipe_client *pipe_hnd = NULL;
129 TALLOC_CTX *mem_ctx;
130 NTSTATUS nt_status;
131 DOM_SID *domain_sid;
132 const char *domain_name;
133 int ret = -1;
135 /* make use of cli_state handed over as an argument, if possible */
136 if (!cli_arg) {
137 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
138 if (!NT_STATUS_IS_OK(nt_status)) {
139 DEBUG(1, ("failed to make ipc connection: %s\n",
140 nt_errstr(nt_status)));
141 return -1;
143 } else {
144 cli = cli_arg;
147 if (!cli) {
148 return -1;
151 /* Create mem_ctx */
153 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
154 DEBUG(0, ("talloc_init() failed\n"));
155 goto fail;
158 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
159 &domain_name);
160 if (!NT_STATUS_IS_OK(nt_status)) {
161 goto fail;
164 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
165 if (lp_client_schannel()
166 && (ndr_syntax_id_equal(interface,
167 &ndr_table_netlogon.syntax_id))) {
168 /* Always try and create an schannel netlogon pipe. */
169 nt_status = cli_rpc_pipe_open_schannel(
170 cli, interface, NCACN_NP,
171 DCERPC_AUTH_LEVEL_PRIVACY, domain_name,
172 &pipe_hnd);
173 if (!NT_STATUS_IS_OK(nt_status)) {
174 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
175 nt_errstr(nt_status) ));
176 goto fail;
178 } else {
179 if (conn_flags & NET_FLAGS_SEAL) {
180 nt_status = cli_rpc_pipe_open_ntlmssp(
181 cli, interface,
182 (conn_flags & NET_FLAGS_TCP) ?
183 NCACN_IP_TCP : NCACN_NP,
184 DCERPC_AUTH_LEVEL_PRIVACY,
185 lp_workgroup(), c->opt_user_name,
186 c->opt_password, &pipe_hnd);
187 } else {
188 nt_status = cli_rpc_pipe_open_noauth(
189 cli, interface,
190 &pipe_hnd);
192 if (!NT_STATUS_IS_OK(nt_status)) {
193 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
194 get_pipe_name_from_syntax(
195 talloc_tos(), interface),
196 nt_errstr(nt_status) ));
197 goto fail;
202 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
204 if (!NT_STATUS_IS_OK(nt_status)) {
205 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
206 } else {
207 ret = 0;
208 DEBUG(5, ("rpc command function succedded\n"));
211 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
212 if (pipe_hnd) {
213 TALLOC_FREE(pipe_hnd);
217 fail:
218 /* close the connection only if it was opened here */
219 if (!cli_arg) {
220 cli_shutdown(cli);
223 talloc_destroy(mem_ctx);
224 return ret;
228 * Force a change of the trust acccount password.
230 * All parameters are provided by the run_rpc_command function, except for
231 * argc, argv which are passed through.
233 * @param domain_sid The domain sid acquired from the remote server.
234 * @param cli A cli_state connected to the server.
235 * @param mem_ctx Talloc context, destroyed on completion of the function.
236 * @param argc Standard main() style argc.
237 * @param argv Standard main() style argv. Initial components are already
238 * stripped.
240 * @return Normal NTSTATUS return.
243 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
244 const DOM_SID *domain_sid,
245 const char *domain_name,
246 struct cli_state *cli,
247 struct rpc_pipe_client *pipe_hnd,
248 TALLOC_CTX *mem_ctx,
249 int argc,
250 const char **argv)
252 NTSTATUS status;
254 status = trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
255 if (!NT_STATUS_IS_OK(status)) {
256 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
257 nt_errstr(status));
258 return status;
261 return NT_STATUS_OK;
265 * Force a change of the trust acccount password.
267 * @param argc Standard main() style argc.
268 * @param argv Standard main() style argv. Initial components are already
269 * stripped.
271 * @return A shell status integer (0 for success).
274 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
276 if (c->display_usage) {
277 d_printf( "%s\n"
278 "net rpc changetrustpw\n"
279 " %s\n",
280 _("Usage:"),
281 _("Change the machine trust password"));
282 return 0;
285 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
286 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
287 rpc_changetrustpw_internals,
288 argc, argv);
292 * Join a domain, the old way.
294 * This uses 'machinename' as the inital password, and changes it.
296 * The password should be created with 'server manager' or equiv first.
298 * All parameters are provided by the run_rpc_command function, except for
299 * argc, argv which are passed through.
301 * @param domain_sid The domain sid acquired from the remote server.
302 * @param cli A cli_state connected to the server.
303 * @param mem_ctx Talloc context, destroyed on completion of the function.
304 * @param argc Standard main() style argc.
305 * @param argv Standard main() style argv. Initial components are already
306 * stripped.
308 * @return Normal NTSTATUS return.
311 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
312 const DOM_SID *domain_sid,
313 const char *domain_name,
314 struct cli_state *cli,
315 struct rpc_pipe_client *pipe_hnd,
316 TALLOC_CTX *mem_ctx,
317 int argc,
318 const char **argv)
321 fstring trust_passwd;
322 unsigned char orig_trust_passwd_hash[16];
323 NTSTATUS result;
324 enum netr_SchannelType sec_channel_type;
326 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
327 &pipe_hnd);
328 if (!NT_STATUS_IS_OK(result)) {
329 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
330 "error was %s\n",
331 cli->desthost,
332 nt_errstr(result) ));
333 return result;
337 check what type of join - if the user want's to join as
338 a BDC, the server must agree that we are a BDC.
340 if (argc >= 0) {
341 sec_channel_type = get_sec_channel_type(argv[0]);
342 } else {
343 sec_channel_type = get_sec_channel_type(NULL);
346 fstrcpy(trust_passwd, global_myname());
347 strlower_m(trust_passwd);
350 * Machine names can be 15 characters, but the max length on
351 * a password is 14. --jerry
354 trust_passwd[14] = '\0';
356 E_md4hash(trust_passwd, orig_trust_passwd_hash);
358 result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
359 global_myname(),
360 orig_trust_passwd_hash,
361 sec_channel_type);
363 if (NT_STATUS_IS_OK(result))
364 printf(_("Joined domain %s.\n"), c->opt_target_workgroup);
367 if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
368 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
369 result = NT_STATUS_UNSUCCESSFUL;
372 return result;
376 * Join a domain, the old way.
378 * @param argc Standard main() style argc.
379 * @param argv Standard main() style argv. Initial components are already
380 * stripped.
382 * @return A shell status integer (0 for success).
385 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
387 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
388 NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
389 rpc_oldjoin_internals,
390 argc, argv);
394 * Join a domain, the old way. This function exists to allow
395 * the message to be displayed when oldjoin was explicitly
396 * requested, but not when it was implied by "net rpc join".
398 * @param argc Standard main() style argc.
399 * @param argv Standard main() style argv. Initial components are already
400 * stripped.
402 * @return A shell status integer (0 for success).
405 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
407 int rc = -1;
409 if (c->display_usage) {
410 d_printf( "%s\n"
411 "net rpc oldjoin\n"
412 " %s\n",
413 _("Usage:"),
414 _("Join a domain the old way"));
415 return 0;
418 rc = net_rpc_perform_oldjoin(c, argc, argv);
420 if (rc) {
421 d_fprintf(stderr, _("Failed to join domain\n"));
424 return rc;
428 * 'net rpc join' entrypoint.
429 * @param argc Standard main() style argc.
430 * @param argv Standard main() style argv. Initial components are already
431 * stripped
433 * Main 'net_rpc_join()' (where the admin username/password is used) is
434 * in net_rpc_join.c.
435 * Try to just change the password, but if that doesn't work, use/prompt
436 * for a username/password.
439 int net_rpc_join(struct net_context *c, int argc, const char **argv)
441 if (c->display_usage) {
442 d_printf("%s\n%s",
443 _("Usage:"),
444 _("net rpc join -U <username>[%%password] <type>\n"
445 " Join a domain\n"
446 " username\tName of the admin user"
447 " password\tPassword of the admin user, will "
448 "prompt if not specified\n"
449 " type\tCan be one of the following:\n"
450 "\t\tMEMBER\tJoin as member server (default)\n"
451 "\t\tBDC\tJoin as BDC\n"
452 "\t\tPDC\tJoin as PDC\n"));
453 return 0;
456 if (lp_server_role() == ROLE_STANDALONE) {
457 d_printf(_("cannot join as standalone machine\n"));
458 return -1;
461 if (strlen(global_myname()) > 15) {
462 d_printf(_("Our netbios name can be at most 15 chars long, "
463 "\"%s\" is %u chars long\n"),
464 global_myname(), (unsigned int)strlen(global_myname()));
465 return -1;
468 if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
469 return 0;
471 return net_rpc_join_newstyle(c, argc, argv);
475 * display info about a rpc domain
477 * All parameters are provided by the run_rpc_command function, except for
478 * argc, argv which are passed through.
480 * @param domain_sid The domain sid acquired from the remote server
481 * @param cli A cli_state connected to the server.
482 * @param mem_ctx Talloc context, destroyed on completion of the function.
483 * @param argc Standard main() style argc.
484 * @param argv Standard main() style argv. Initial components are already
485 * stripped.
487 * @return Normal NTSTATUS return.
490 NTSTATUS rpc_info_internals(struct net_context *c,
491 const DOM_SID *domain_sid,
492 const char *domain_name,
493 struct cli_state *cli,
494 struct rpc_pipe_client *pipe_hnd,
495 TALLOC_CTX *mem_ctx,
496 int argc,
497 const char **argv)
499 struct policy_handle connect_pol, domain_pol;
500 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
501 union samr_DomainInfo *info = NULL;
502 fstring sid_str;
504 sid_to_fstring(sid_str, domain_sid);
506 /* Get sam policy handle */
507 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
508 pipe_hnd->desthost,
509 MAXIMUM_ALLOWED_ACCESS,
510 &connect_pol);
511 if (!NT_STATUS_IS_OK(result)) {
512 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
513 nt_errstr(result));
514 goto done;
517 /* Get domain policy handle */
518 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
519 &connect_pol,
520 MAXIMUM_ALLOWED_ACCESS,
521 CONST_DISCARD(struct dom_sid2 *, domain_sid),
522 &domain_pol);
523 if (!NT_STATUS_IS_OK(result)) {
524 d_fprintf(stderr, _("Could not open domain: %s\n"),
525 nt_errstr(result));
526 goto done;
529 result = rpccli_samr_QueryDomainInfo(pipe_hnd, mem_ctx,
530 &domain_pol,
532 &info);
533 if (NT_STATUS_IS_OK(result)) {
534 d_printf(_("Domain Name: %s\n"),
535 info->general.domain_name.string);
536 d_printf(_("Domain SID: %s\n"), sid_str);
537 d_printf(_("Sequence number: %llu\n"),
538 (unsigned long long)info->general.sequence_num);
539 d_printf(_("Num users: %u\n"), info->general.num_users);
540 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
541 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
544 done:
545 return result;
549 * 'net rpc info' entrypoint.
550 * @param argc Standard main() style argc.
551 * @param argv Standard main() style argv. Initial components are already
552 * stripped.
555 int net_rpc_info(struct net_context *c, int argc, const char **argv)
557 if (c->display_usage) {
558 d_printf( "%s\n"
559 "net rpc info\n"
560 " %s\n",
561 _("Usage:"),
562 _("Display information about the domain"));
563 return 0;
566 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
567 NET_FLAGS_PDC, rpc_info_internals,
568 argc, argv);
572 * Fetch domain SID into the local secrets.tdb.
574 * All parameters are provided by the run_rpc_command function, except for
575 * argc, argv which are passed through.
577 * @param domain_sid The domain sid acquired from the remote server.
578 * @param cli A cli_state connected to the server.
579 * @param mem_ctx Talloc context, destroyed on completion of the function.
580 * @param argc Standard main() style argc.
581 * @param argv Standard main() style argv. Initial components are already
582 * stripped.
584 * @return Normal NTSTATUS return.
587 static NTSTATUS rpc_getsid_internals(struct net_context *c,
588 const DOM_SID *domain_sid,
589 const char *domain_name,
590 struct cli_state *cli,
591 struct rpc_pipe_client *pipe_hnd,
592 TALLOC_CTX *mem_ctx,
593 int argc,
594 const char **argv)
596 fstring sid_str;
598 sid_to_fstring(sid_str, domain_sid);
599 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
600 sid_str, domain_name);
602 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
603 DEBUG(0,("Can't store domain SID\n"));
604 return NT_STATUS_UNSUCCESSFUL;
607 return NT_STATUS_OK;
611 * 'net rpc getsid' entrypoint.
612 * @param argc Standard main() style argc.
613 * @param argv Standard main() style argv. Initial components are already
614 * stripped.
617 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
619 int conn_flags = NET_FLAGS_PDC;
621 if (!c->opt_user_specified) {
622 conn_flags |= NET_FLAGS_ANONYMOUS;
625 if (c->display_usage) {
626 d_printf( "%s\n"
627 "net rpc getsid\n"
628 " %s\n",
629 _("Usage:"),
630 _("Fetch domain SID into local secrets.tdb"));
631 return 0;
634 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
635 conn_flags,
636 rpc_getsid_internals,
637 argc, argv);
640 /****************************************************************************/
643 * Basic usage function for 'net rpc user'.
644 * @param argc Standard main() style argc.
645 * @param argv Standard main() style argv. Initial components are already
646 * stripped.
649 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
651 return net_user_usage(c, argc, argv);
655 * Add a new user to a remote RPC server.
657 * @param argc Standard main() style argc.
658 * @param argv Standard main() style argv. Initial components are already
659 * stripped.
661 * @return A shell status integer (0 for success).
664 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
666 NET_API_STATUS status;
667 struct USER_INFO_1 info1;
668 uint32_t parm_error = 0;
670 if (argc < 1 || c->display_usage) {
671 rpc_user_usage(c, argc, argv);
672 return 0;
675 ZERO_STRUCT(info1);
677 info1.usri1_name = argv[0];
678 if (argc == 2) {
679 info1.usri1_password = argv[1];
682 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
684 if (status != 0) {
685 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
686 argv[0], libnetapi_get_error_string(c->netapi_ctx,
687 status));
688 return -1;
689 } else {
690 d_printf(_("Added user '%s'.\n"), argv[0]);
693 return 0;
697 * Rename a user on a remote RPC server.
699 * @param argc Standard main() style argc.
700 * @param argv Standard main() style argv. Initial components are already
701 * stripped.
703 * @return A shell status integer (0 for success).
706 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
708 NET_API_STATUS status;
709 struct USER_INFO_0 u0;
710 uint32_t parm_err = 0;
712 if (argc != 2 || c->display_usage) {
713 rpc_user_usage(c, argc, argv);
714 return 0;
717 u0.usri0_name = argv[1];
719 status = NetUserSetInfo(c->opt_host, argv[0],
720 0, (uint8_t *)&u0, &parm_err);
721 if (status) {
722 d_fprintf(stderr,
723 _("Failed to rename user from %s to %s - %s\n"),
724 argv[0], argv[1],
725 libnetapi_get_error_string(c->netapi_ctx, status));
726 } else {
727 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
730 return status;
734 * Set a user's primary group
736 * @param argc Standard main() style argc.
737 * @param argv Standard main() style argv. Initial components are already
738 * stripped.
740 * @return A shell status integer (0 for success).
743 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
744 const char **argv)
746 NET_API_STATUS status;
747 uint8_t *buffer;
748 struct GROUP_INFO_2 *g2;
749 struct USER_INFO_1051 u1051;
750 uint32_t parm_err = 0;
752 if (argc != 2 || c->display_usage) {
753 rpc_user_usage(c, argc, argv);
754 return 0;
757 status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
758 if (status) {
759 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
760 argv[1],
761 libnetapi_get_error_string(c->netapi_ctx, status));
762 return status;
764 g2 = (struct GROUP_INFO_2 *)buffer;
766 u1051.usri1051_primary_group_id = g2->grpi2_group_id;
768 NetApiBufferFree(buffer);
770 status = NetUserSetInfo(c->opt_host, argv[0], 1051,
771 (uint8_t *)&u1051, &parm_err);
772 if (status) {
773 d_fprintf(stderr,
774 _("Failed to set user's primary group %s to %s - "
775 "%s\n"), argv[0], argv[1],
776 libnetapi_get_error_string(c->netapi_ctx, status));
777 } else {
778 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
779 argv[1]);
781 return status;
785 * Delete a user from a remote RPC server.
787 * @param argc Standard main() style argc.
788 * @param argv Standard main() style argv. Initial components are already
789 * stripped.
791 * @return A shell status integer (0 for success).
794 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
796 NET_API_STATUS status;
798 if (argc < 1 || c->display_usage) {
799 rpc_user_usage(c, argc, argv);
800 return 0;
803 status = NetUserDel(c->opt_host, argv[0]);
805 if (status != 0) {
806 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
807 argv[0],
808 libnetapi_get_error_string(c->netapi_ctx, status));
809 return -1;
810 } else {
811 d_printf(_("Deleted user '%s'.\n"), argv[0]);
814 return 0;
818 * Set a user's password on a remote RPC server.
820 * @param argc Standard main() style argc.
821 * @param argv Standard main() style argv. Initial components are already
822 * stripped.
824 * @return A shell status integer (0 for success).
827 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
829 NET_API_STATUS status;
830 char *prompt = NULL;
831 struct USER_INFO_1003 u1003;
832 uint32_t parm_err = 0;
833 int ret;
835 if (argc < 1 || c->display_usage) {
836 rpc_user_usage(c, argc, argv);
837 return 0;
840 if (argv[1]) {
841 u1003.usri1003_password = argv[1];
842 } else {
843 ret = asprintf(&prompt, _("Enter new password for %s:"),
844 argv[0]);
845 if (ret == -1) {
846 return -1;
848 u1003.usri1003_password = getpass(prompt);
849 SAFE_FREE(prompt);
852 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
854 /* Display results */
855 if (status != 0) {
856 d_fprintf(stderr,
857 _("Failed to set password for '%s' with error: %s.\n"),
858 argv[0], libnetapi_get_error_string(c->netapi_ctx,
859 status));
860 return -1;
863 return 0;
867 * List a user's groups from a remote RPC server.
869 * @param argc Standard main() style argc.
870 * @param argv Standard main() style argv. Initial components are already
871 * stripped.
873 * @return A shell status integer (0 for success)
876 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
879 NET_API_STATUS status;
880 struct GROUP_USERS_INFO_0 *u0 = NULL;
881 uint32_t entries_read = 0;
882 uint32_t total_entries = 0;
883 int i;
886 if (argc < 1 || c->display_usage) {
887 rpc_user_usage(c, argc, argv);
888 return 0;
891 status = NetUserGetGroups(c->opt_host,
892 argv[0],
894 (uint8_t **)(void *)&u0,
895 (uint32_t)-1,
896 &entries_read,
897 &total_entries);
898 if (status != 0) {
899 d_fprintf(stderr,
900 _("Failed to get groups for '%s' with error: %s.\n"),
901 argv[0], libnetapi_get_error_string(c->netapi_ctx,
902 status));
903 return -1;
906 for (i=0; i < entries_read; i++) {
907 printf("%s\n", u0->grui0_name);
908 u0++;
911 return 0;
915 * List users on a remote RPC server.
917 * All parameters are provided by the run_rpc_command function, except for
918 * argc, argv which are passed through.
920 * @param domain_sid The domain sid acquired from the remote server.
921 * @param cli A cli_state connected to the server.
922 * @param mem_ctx Talloc context, destroyed on completion of the function.
923 * @param argc Standard main() style argc.
924 * @param argv Standard main() style argv. Initial components are already
925 * stripped.
927 * @return Normal NTSTATUS return.
930 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
932 NET_API_STATUS status;
933 uint32_t start_idx=0, num_entries, i, loop_count = 0;
934 struct NET_DISPLAY_USER *info = NULL;
935 void *buffer = NULL;
937 /* Query domain users */
938 if (c->opt_long_list_entries)
939 d_printf(_("\nUser name Comment"
940 "\n-----------------------------\n"));
941 do {
942 uint32_t max_entries, max_size;
944 get_query_dispinfo_params(
945 loop_count, &max_entries, &max_size);
947 status = NetQueryDisplayInformation(c->opt_host,
949 start_idx,
950 max_entries,
951 max_size,
952 &num_entries,
953 &buffer);
954 if (status != 0 && status != ERROR_MORE_DATA) {
955 return status;
958 info = (struct NET_DISPLAY_USER *)buffer;
960 for (i = 0; i < num_entries; i++) {
962 if (c->opt_long_list_entries)
963 printf("%-21.21s %s\n", info->usri1_name,
964 info->usri1_comment);
965 else
966 printf("%s\n", info->usri1_name);
967 info++;
970 NetApiBufferFree(buffer);
972 loop_count++;
973 start_idx += num_entries;
975 } while (status == ERROR_MORE_DATA);
977 return status;
981 * 'net rpc user' entrypoint.
982 * @param argc Standard main() style argc.
983 * @param argv Standard main() style argv. Initial components are already
984 * stripped.
987 int net_rpc_user(struct net_context *c, int argc, const char **argv)
989 NET_API_STATUS status;
991 struct functable func[] = {
993 "add",
994 rpc_user_add,
995 NET_TRANSPORT_RPC,
996 N_("Add specified user"),
997 N_("net rpc user add\n"
998 " Add specified user")
1001 "info",
1002 rpc_user_info,
1003 NET_TRANSPORT_RPC,
1004 N_("List domain groups of user"),
1005 N_("net rpc user info\n"
1006 " Lis domain groups of user")
1009 "delete",
1010 rpc_user_delete,
1011 NET_TRANSPORT_RPC,
1012 N_("Remove specified user"),
1013 N_("net rpc user delete\n"
1014 " Remove specified user")
1017 "password",
1018 rpc_user_password,
1019 NET_TRANSPORT_RPC,
1020 N_("Change user password"),
1021 N_("net rpc user password\n"
1022 " Change user password")
1025 "rename",
1026 rpc_user_rename,
1027 NET_TRANSPORT_RPC,
1028 N_("Rename specified user"),
1029 N_("net rpc user rename\n"
1030 " Rename specified user")
1033 "setprimarygroup",
1034 rpc_user_setprimarygroup,
1035 NET_TRANSPORT_RPC,
1036 "Set a user's primary group",
1037 "net rpc user setprimarygroup\n"
1038 " Set a user's primary group"
1040 {NULL, NULL, 0, NULL, NULL}
1043 status = libnetapi_init(&c->netapi_ctx);
1044 if (status != 0) {
1045 return -1;
1047 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1048 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1049 if (c->opt_kerberos) {
1050 libnetapi_set_use_kerberos(c->netapi_ctx);
1053 if (argc == 0) {
1054 if (c->display_usage) {
1055 d_printf( "%s\n"
1056 "net rpc user\n"
1057 " %s\n",
1058 _("Usage:"),
1059 _("List all users"));
1060 net_display_usage_from_functable(func);
1061 return 0;
1064 return rpc_user_list(c, argc, argv);
1067 return net_run_function(c, argc, argv, "net rpc user", func);
1070 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1071 TALLOC_CTX *mem_ctx,
1072 struct rpc_sh_ctx *ctx,
1073 struct rpc_pipe_client *pipe_hnd,
1074 int argc, const char **argv)
1076 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1079 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1080 TALLOC_CTX *mem_ctx,
1081 struct rpc_sh_ctx *ctx,
1082 struct rpc_pipe_client *pipe_hnd,
1083 int argc, const char **argv)
1085 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1088 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1089 TALLOC_CTX *mem_ctx,
1090 struct rpc_sh_ctx *ctx,
1091 struct rpc_pipe_client *pipe_hnd,
1092 int argc, const char **argv,
1093 NTSTATUS (*fn)(
1094 struct net_context *c,
1095 TALLOC_CTX *mem_ctx,
1096 struct rpc_sh_ctx *ctx,
1097 struct rpc_pipe_client *pipe_hnd,
1098 struct policy_handle *user_hnd,
1099 int argc, const char **argv))
1101 struct policy_handle connect_pol, domain_pol, user_pol;
1102 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1103 DOM_SID sid;
1104 uint32 rid;
1105 enum lsa_SidType type;
1107 if (argc == 0) {
1108 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1109 ctx->whoami);
1110 return NT_STATUS_INVALID_PARAMETER;
1113 ZERO_STRUCT(connect_pol);
1114 ZERO_STRUCT(domain_pol);
1115 ZERO_STRUCT(user_pol);
1117 result = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1118 argv[0], NULL, NULL, &sid, &type);
1119 if (!NT_STATUS_IS_OK(result)) {
1120 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1121 nt_errstr(result));
1122 goto done;
1125 if (type != SID_NAME_USER) {
1126 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1127 sid_type_lookup(type));
1128 result = NT_STATUS_NO_SUCH_USER;
1129 goto done;
1132 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1133 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1134 result = NT_STATUS_NO_SUCH_USER;
1135 goto done;
1138 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1139 pipe_hnd->desthost,
1140 MAXIMUM_ALLOWED_ACCESS,
1141 &connect_pol);
1142 if (!NT_STATUS_IS_OK(result)) {
1143 goto done;
1146 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1147 &connect_pol,
1148 MAXIMUM_ALLOWED_ACCESS,
1149 ctx->domain_sid,
1150 &domain_pol);
1151 if (!NT_STATUS_IS_OK(result)) {
1152 goto done;
1155 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1156 &domain_pol,
1157 MAXIMUM_ALLOWED_ACCESS,
1158 rid,
1159 &user_pol);
1160 if (!NT_STATUS_IS_OK(result)) {
1161 goto done;
1164 result = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1166 done:
1167 if (is_valid_policy_hnd(&user_pol)) {
1168 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1170 if (is_valid_policy_hnd(&domain_pol)) {
1171 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
1173 if (is_valid_policy_hnd(&connect_pol)) {
1174 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1176 return result;
1179 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1180 TALLOC_CTX *mem_ctx,
1181 struct rpc_sh_ctx *ctx,
1182 struct rpc_pipe_client *pipe_hnd,
1183 struct policy_handle *user_hnd,
1184 int argc, const char **argv)
1186 NTSTATUS result;
1187 union samr_UserInfo *info = NULL;
1189 if (argc != 0) {
1190 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1191 ctx->whoami);
1192 return NT_STATUS_INVALID_PARAMETER;
1195 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1196 user_hnd,
1198 &info);
1199 if (!NT_STATUS_IS_OK(result)) {
1200 return result;
1203 d_printf(_("user rid: %d, group rid: %d\n"),
1204 info->info21.rid,
1205 info->info21.primary_gid);
1207 return result;
1210 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1211 TALLOC_CTX *mem_ctx,
1212 struct rpc_sh_ctx *ctx,
1213 struct rpc_pipe_client *pipe_hnd,
1214 int argc, const char **argv)
1216 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1217 rpc_sh_user_show_internals);
1220 #define FETCHSTR(name, rec) \
1221 do { if (strequal(ctx->thiscmd, name)) { \
1222 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1223 } while (0);
1225 #define SETSTR(name, rec, flag) \
1226 do { if (strequal(ctx->thiscmd, name)) { \
1227 init_lsa_String(&(info->info21.rec), argv[0]); \
1228 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1229 } while (0);
1231 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1232 TALLOC_CTX *mem_ctx,
1233 struct rpc_sh_ctx *ctx,
1234 struct rpc_pipe_client *pipe_hnd,
1235 struct policy_handle *user_hnd,
1236 int argc, const char **argv)
1238 NTSTATUS result;
1239 const char *username;
1240 const char *oldval = "";
1241 union samr_UserInfo *info = NULL;
1243 if (argc > 1) {
1244 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1245 _("Usage:"), ctx->whoami);
1246 return NT_STATUS_INVALID_PARAMETER;
1249 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1250 user_hnd,
1252 &info);
1253 if (!NT_STATUS_IS_OK(result)) {
1254 return result;
1257 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1259 FETCHSTR("fullname", full_name);
1260 FETCHSTR("homedir", home_directory);
1261 FETCHSTR("homedrive", home_drive);
1262 FETCHSTR("logonscript", logon_script);
1263 FETCHSTR("profilepath", profile_path);
1264 FETCHSTR("description", description);
1266 if (argc == 0) {
1267 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1268 goto done;
1271 if (strcmp(argv[0], "NULL") == 0) {
1272 argv[0] = "";
1275 ZERO_STRUCT(info->info21);
1277 SETSTR("fullname", full_name, FULL_NAME);
1278 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1279 SETSTR("homedrive", home_drive, HOME_DRIVE);
1280 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1281 SETSTR("profilepath", profile_path, PROFILE_PATH);
1282 SETSTR("description", description, DESCRIPTION);
1284 result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1285 user_hnd,
1287 info);
1289 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1290 ctx->thiscmd, oldval, argv[0]);
1292 done:
1294 return result;
1297 #define HANDLEFLG(name, rec) \
1298 do { if (strequal(ctx->thiscmd, name)) { \
1299 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1300 if (newval) { \
1301 newflags = oldflags | ACB_##rec; \
1302 } else { \
1303 newflags = oldflags & ~ACB_##rec; \
1304 } } } while (0);
1306 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1307 TALLOC_CTX *mem_ctx,
1308 struct rpc_sh_ctx *ctx,
1309 struct rpc_pipe_client *pipe_hnd,
1310 int argc, const char **argv)
1312 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1313 rpc_sh_user_str_edit_internals);
1316 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1317 TALLOC_CTX *mem_ctx,
1318 struct rpc_sh_ctx *ctx,
1319 struct rpc_pipe_client *pipe_hnd,
1320 struct policy_handle *user_hnd,
1321 int argc, const char **argv)
1323 NTSTATUS result;
1324 const char *username;
1325 const char *oldval = "unknown";
1326 uint32 oldflags, newflags;
1327 bool newval;
1328 union samr_UserInfo *info = NULL;
1330 if ((argc > 1) ||
1331 ((argc == 1) && !strequal(argv[0], "yes") &&
1332 !strequal(argv[0], "no"))) {
1333 /* TRANSATORS: The yes|no here are program keywords. Please do
1334 not translate. */
1335 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1336 ctx->whoami);
1337 return NT_STATUS_INVALID_PARAMETER;
1340 newval = strequal(argv[0], "yes");
1342 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1343 user_hnd,
1345 &info);
1346 if (!NT_STATUS_IS_OK(result)) {
1347 return result;
1350 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1351 oldflags = info->info21.acct_flags;
1352 newflags = info->info21.acct_flags;
1354 HANDLEFLG("disabled", DISABLED);
1355 HANDLEFLG("pwnotreq", PWNOTREQ);
1356 HANDLEFLG("autolock", AUTOLOCK);
1357 HANDLEFLG("pwnoexp", PWNOEXP);
1359 if (argc == 0) {
1360 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1361 oldval);
1362 goto done;
1365 ZERO_STRUCT(info->info21);
1367 info->info21.acct_flags = newflags;
1368 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1370 result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1371 user_hnd,
1373 info);
1375 if (NT_STATUS_IS_OK(result)) {
1376 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1377 ctx->thiscmd, oldval, argv[0]);
1380 done:
1382 return result;
1385 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1386 TALLOC_CTX *mem_ctx,
1387 struct rpc_sh_ctx *ctx,
1388 struct rpc_pipe_client *pipe_hnd,
1389 int argc, const char **argv)
1391 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1392 rpc_sh_user_flag_edit_internals);
1395 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1396 TALLOC_CTX *mem_ctx,
1397 struct rpc_sh_ctx *ctx)
1399 static struct rpc_sh_cmd cmds[] = {
1401 { "fullname", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1402 N_("Show/Set a user's full name") },
1404 { "homedir", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1405 N_("Show/Set a user's home directory") },
1407 { "homedrive", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1408 N_("Show/Set a user's home drive") },
1410 { "logonscript", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1411 N_("Show/Set a user's logon script") },
1413 { "profilepath", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1414 N_("Show/Set a user's profile path") },
1416 { "description", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1417 N_("Show/Set a user's description") },
1419 { "disabled", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1420 N_("Show/Set whether a user is disabled") },
1422 { "autolock", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1423 N_("Show/Set whether a user locked out") },
1425 { "pwnotreq", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1426 N_("Show/Set whether a user does not need a password") },
1428 { "pwnoexp", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1429 N_("Show/Set whether a user's password does not expire") },
1431 { NULL, NULL, 0, NULL, NULL }
1434 return cmds;
1437 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1438 TALLOC_CTX *mem_ctx,
1439 struct rpc_sh_ctx *ctx)
1441 static struct rpc_sh_cmd cmds[] = {
1443 { "list", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_list,
1444 N_("List available users") },
1446 { "info", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_info,
1447 N_("List the domain groups a user is member of") },
1449 { "show", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_show,
1450 N_("Show info about a user") },
1452 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1453 N_("Show/Modify a user's fields") },
1455 { NULL, NULL, 0, NULL, NULL }
1458 return cmds;
1461 /****************************************************************************/
1464 * Basic usage function for 'net rpc group'.
1465 * @param argc Standard main() style argc.
1466 * @param argv Standard main() style argv. Initial components are already
1467 * stripped.
1470 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1472 return net_group_usage(c, argc, argv);
1476 * Delete group on a remote RPC server.
1478 * All parameters are provided by the run_rpc_command function, except for
1479 * argc, argv which are passed through.
1481 * @param domain_sid The domain sid acquired from the remote server.
1482 * @param cli A cli_state connected to the server.
1483 * @param mem_ctx Talloc context, destroyed on completion of the function.
1484 * @param argc Standard main() style argc.
1485 * @param argv Standard main() style argv. Initial components are already
1486 * stripped.
1488 * @return Normal NTSTATUS return.
1491 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1492 const DOM_SID *domain_sid,
1493 const char *domain_name,
1494 struct cli_state *cli,
1495 struct rpc_pipe_client *pipe_hnd,
1496 TALLOC_CTX *mem_ctx,
1497 int argc,
1498 const char **argv)
1500 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1501 bool group_is_primary = false;
1502 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1503 uint32_t group_rid;
1504 struct samr_RidTypeArray *rids = NULL;
1505 /* char **names; */
1506 int i;
1507 /* struct samr_RidWithAttribute *user_gids; */
1509 struct samr_Ids group_rids, name_types;
1510 struct lsa_String lsa_acct_name;
1511 union samr_UserInfo *info = NULL;
1513 if (argc < 1 || c->display_usage) {
1514 rpc_group_usage(c, argc,argv);
1515 return NT_STATUS_OK; /* ok? */
1518 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1519 pipe_hnd->desthost,
1520 MAXIMUM_ALLOWED_ACCESS,
1521 &connect_pol);
1523 if (!NT_STATUS_IS_OK(result)) {
1524 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1525 goto done;
1528 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1529 &connect_pol,
1530 MAXIMUM_ALLOWED_ACCESS,
1531 CONST_DISCARD(struct dom_sid2 *, domain_sid),
1532 &domain_pol);
1534 if (!NT_STATUS_IS_OK(result)) {
1535 d_fprintf(stderr, _("Request open_domain failed\n"));
1536 goto done;
1539 init_lsa_String(&lsa_acct_name, argv[0]);
1541 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1542 &domain_pol,
1544 &lsa_acct_name,
1545 &group_rids,
1546 &name_types);
1547 if (!NT_STATUS_IS_OK(result)) {
1548 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1549 goto done;
1552 switch (name_types.ids[0])
1554 case SID_NAME_DOM_GRP:
1555 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1556 &domain_pol,
1557 MAXIMUM_ALLOWED_ACCESS,
1558 group_rids.ids[0],
1559 &group_pol);
1560 if (!NT_STATUS_IS_OK(result)) {
1561 d_fprintf(stderr, _("Request open_group failed"));
1562 goto done;
1565 group_rid = group_rids.ids[0];
1567 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
1568 &group_pol,
1569 &rids);
1571 if (!NT_STATUS_IS_OK(result)) {
1572 d_fprintf(stderr,
1573 _("Unable to query group members of %s"),
1574 argv[0]);
1575 goto done;
1578 if (c->opt_verbose) {
1579 d_printf(
1580 _("Domain Group %s (rid: %d) has %d members\n"),
1581 argv[0],group_rid, rids->count);
1584 /* Check if group is anyone's primary group */
1585 for (i = 0; i < rids->count; i++)
1587 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1588 &domain_pol,
1589 MAXIMUM_ALLOWED_ACCESS,
1590 rids->rids[i],
1591 &user_pol);
1593 if (!NT_STATUS_IS_OK(result)) {
1594 d_fprintf(stderr,
1595 _("Unable to open group member %d\n"),
1596 rids->rids[i]);
1597 goto done;
1600 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1601 &user_pol,
1603 &info);
1605 if (!NT_STATUS_IS_OK(result)) {
1606 d_fprintf(stderr,
1607 _("Unable to lookup userinfo for group "
1608 "member %d\n"),
1609 rids->rids[i]);
1610 goto done;
1613 if (info->info21.primary_gid == group_rid) {
1614 if (c->opt_verbose) {
1615 d_printf(_("Group is primary group "
1616 "of %s\n"),
1617 info->info21.account_name.string);
1619 group_is_primary = true;
1622 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1625 if (group_is_primary) {
1626 d_fprintf(stderr, _("Unable to delete group because "
1627 "some of it's members have it as primary "
1628 "group\n"));
1629 result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1630 goto done;
1633 /* remove all group members */
1634 for (i = 0; i < rids->count; i++)
1636 if (c->opt_verbose)
1637 d_printf(_("Remove group member %d..."),
1638 rids->rids[i]);
1639 result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
1640 &group_pol,
1641 rids->rids[i]);
1643 if (NT_STATUS_IS_OK(result)) {
1644 if (c->opt_verbose)
1645 d_printf(_("ok\n"));
1646 } else {
1647 if (c->opt_verbose)
1648 d_printf("%s\n", _("failed"));
1649 goto done;
1653 result = rpccli_samr_DeleteDomainGroup(pipe_hnd, mem_ctx,
1654 &group_pol);
1656 break;
1657 /* removing a local group is easier... */
1658 case SID_NAME_ALIAS:
1659 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1660 &domain_pol,
1661 MAXIMUM_ALLOWED_ACCESS,
1662 group_rids.ids[0],
1663 &group_pol);
1665 if (!NT_STATUS_IS_OK(result)) {
1666 d_fprintf(stderr, _("Request open_alias failed\n"));
1667 goto done;
1670 result = rpccli_samr_DeleteDomAlias(pipe_hnd, mem_ctx,
1671 &group_pol);
1672 break;
1673 default:
1674 d_fprintf(stderr, _("%s is of type %s. This command is only "
1675 "for deleting local or global groups\n"),
1676 argv[0],sid_type_lookup(name_types.ids[0]));
1677 result = NT_STATUS_UNSUCCESSFUL;
1678 goto done;
1681 if (NT_STATUS_IS_OK(result)) {
1682 if (c->opt_verbose)
1683 d_printf(_("Deleted %s '%s'\n"),
1684 sid_type_lookup(name_types.ids[0]), argv[0]);
1685 } else {
1686 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
1687 get_friendly_nt_error_msg(result));
1690 done:
1691 return result;
1695 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1697 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1698 rpc_group_delete_internals, argc,argv);
1701 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1703 NET_API_STATUS status;
1704 struct GROUP_INFO_1 info1;
1705 uint32_t parm_error = 0;
1707 if (argc != 1 || c->display_usage) {
1708 rpc_group_usage(c, argc, argv);
1709 return 0;
1712 ZERO_STRUCT(info1);
1714 info1.grpi1_name = argv[0];
1715 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1716 info1.grpi1_comment = c->opt_comment;
1719 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1721 if (status != 0) {
1722 d_fprintf(stderr,
1723 _("Failed to add group '%s' with error: %s.\n"),
1724 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1725 status));
1726 return -1;
1727 } else {
1728 d_printf(_("Added group '%s'.\n"), argv[0]);
1731 return 0;
1734 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
1736 NET_API_STATUS status;
1737 struct LOCALGROUP_INFO_1 info1;
1738 uint32_t parm_error = 0;
1740 if (argc != 1 || c->display_usage) {
1741 rpc_group_usage(c, argc, argv);
1742 return 0;
1745 ZERO_STRUCT(info1);
1747 info1.lgrpi1_name = argv[0];
1748 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1749 info1.lgrpi1_comment = c->opt_comment;
1752 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1754 if (status != 0) {
1755 d_fprintf(stderr,
1756 _("Failed to add alias '%s' with error: %s.\n"),
1757 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1758 status));
1759 return -1;
1760 } else {
1761 d_printf(_("Added alias '%s'.\n"), argv[0]);
1764 return 0;
1767 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1769 if (c->opt_localgroup)
1770 return rpc_alias_add_internals(c, argc, argv);
1772 return rpc_group_add_internals(c, argc, argv);
1775 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1776 TALLOC_CTX *mem_ctx,
1777 const char *name,
1778 DOM_SID *sid,
1779 enum lsa_SidType *type)
1781 DOM_SID *sids = NULL;
1782 enum lsa_SidType *types = NULL;
1783 struct rpc_pipe_client *pipe_hnd = NULL;
1784 struct policy_handle lsa_pol;
1785 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1787 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1788 &pipe_hnd);
1789 if (!NT_STATUS_IS_OK(result)) {
1790 goto done;
1793 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1794 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1796 if (!NT_STATUS_IS_OK(result)) {
1797 goto done;
1800 result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1801 &name, NULL, 1, &sids, &types);
1803 if (NT_STATUS_IS_OK(result)) {
1804 sid_copy(sid, &sids[0]);
1805 *type = types[0];
1808 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
1810 done:
1811 if (pipe_hnd) {
1812 TALLOC_FREE(pipe_hnd);
1815 if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
1817 /* Try as S-1-5-whatever */
1819 DOM_SID tmp_sid;
1821 if (string_to_sid(&tmp_sid, name)) {
1822 sid_copy(sid, &tmp_sid);
1823 *type = SID_NAME_UNKNOWN;
1824 result = NT_STATUS_OK;
1828 return result;
1831 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
1832 TALLOC_CTX *mem_ctx,
1833 const DOM_SID *group_sid,
1834 const char *member)
1836 struct policy_handle connect_pol, domain_pol;
1837 NTSTATUS result;
1838 uint32 group_rid;
1839 struct policy_handle group_pol;
1841 struct samr_Ids rids, rid_types;
1842 struct lsa_String lsa_acct_name;
1844 DOM_SID sid;
1846 sid_copy(&sid, group_sid);
1848 if (!sid_split_rid(&sid, &group_rid)) {
1849 return NT_STATUS_UNSUCCESSFUL;
1852 /* Get sam policy handle */
1853 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1854 pipe_hnd->desthost,
1855 MAXIMUM_ALLOWED_ACCESS,
1856 &connect_pol);
1857 if (!NT_STATUS_IS_OK(result)) {
1858 return result;
1861 /* Get domain policy handle */
1862 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1863 &connect_pol,
1864 MAXIMUM_ALLOWED_ACCESS,
1865 &sid,
1866 &domain_pol);
1867 if (!NT_STATUS_IS_OK(result)) {
1868 return result;
1871 init_lsa_String(&lsa_acct_name, member);
1873 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1874 &domain_pol,
1876 &lsa_acct_name,
1877 &rids,
1878 &rid_types);
1880 if (!NT_STATUS_IS_OK(result)) {
1881 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
1882 member);
1883 goto done;
1886 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1887 &domain_pol,
1888 MAXIMUM_ALLOWED_ACCESS,
1889 group_rid,
1890 &group_pol);
1892 if (!NT_STATUS_IS_OK(result)) {
1893 goto done;
1896 result = rpccli_samr_AddGroupMember(pipe_hnd, mem_ctx,
1897 &group_pol,
1898 rids.ids[0],
1899 0x0005); /* unknown flags */
1901 done:
1902 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1903 return result;
1906 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
1907 TALLOC_CTX *mem_ctx,
1908 const DOM_SID *alias_sid,
1909 const char *member)
1911 struct policy_handle connect_pol, domain_pol;
1912 NTSTATUS result;
1913 uint32 alias_rid;
1914 struct policy_handle alias_pol;
1916 DOM_SID member_sid;
1917 enum lsa_SidType member_type;
1919 DOM_SID sid;
1921 sid_copy(&sid, alias_sid);
1923 if (!sid_split_rid(&sid, &alias_rid)) {
1924 return NT_STATUS_UNSUCCESSFUL;
1927 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
1928 member, &member_sid, &member_type);
1930 if (!NT_STATUS_IS_OK(result)) {
1931 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
1932 member);
1933 return result;
1936 /* Get sam policy handle */
1937 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1938 pipe_hnd->desthost,
1939 MAXIMUM_ALLOWED_ACCESS,
1940 &connect_pol);
1941 if (!NT_STATUS_IS_OK(result)) {
1942 goto done;
1945 /* Get domain policy handle */
1946 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1947 &connect_pol,
1948 MAXIMUM_ALLOWED_ACCESS,
1949 &sid,
1950 &domain_pol);
1951 if (!NT_STATUS_IS_OK(result)) {
1952 goto done;
1955 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1956 &domain_pol,
1957 MAXIMUM_ALLOWED_ACCESS,
1958 alias_rid,
1959 &alias_pol);
1961 if (!NT_STATUS_IS_OK(result)) {
1962 return result;
1965 result = rpccli_samr_AddAliasMember(pipe_hnd, mem_ctx,
1966 &alias_pol,
1967 &member_sid);
1969 if (!NT_STATUS_IS_OK(result)) {
1970 return result;
1973 done:
1974 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1975 return result;
1978 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
1979 const DOM_SID *domain_sid,
1980 const char *domain_name,
1981 struct cli_state *cli,
1982 struct rpc_pipe_client *pipe_hnd,
1983 TALLOC_CTX *mem_ctx,
1984 int argc,
1985 const char **argv)
1987 DOM_SID group_sid;
1988 enum lsa_SidType group_type;
1990 if (argc != 2 || c->display_usage) {
1991 d_printf("%s\n%s",
1992 _("Usage:"),
1993 _("net rpc group addmem <group> <member>\n"
1994 " Add a member to a group\n"
1995 " group\tGroup to add member to\n"
1996 " member\tMember to add to group\n"));
1997 return NT_STATUS_UNSUCCESSFUL;
2000 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2001 &group_sid, &group_type))) {
2002 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2003 argv[0]);
2004 return NT_STATUS_UNSUCCESSFUL;
2007 if (group_type == SID_NAME_DOM_GRP) {
2008 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2009 &group_sid, argv[1]);
2011 if (!NT_STATUS_IS_OK(result)) {
2012 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2013 argv[1], argv[0], nt_errstr(result));
2015 return result;
2018 if (group_type == SID_NAME_ALIAS) {
2019 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2020 &group_sid, argv[1]);
2022 if (!NT_STATUS_IS_OK(result)) {
2023 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2024 argv[1], argv[0], nt_errstr(result));
2026 return result;
2029 d_fprintf(stderr, _("Can only add members to global or local groups "
2030 "which %s is not\n"), argv[0]);
2032 return NT_STATUS_UNSUCCESSFUL;
2035 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2037 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2038 rpc_group_addmem_internals,
2039 argc, argv);
2042 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2043 struct rpc_pipe_client *pipe_hnd,
2044 TALLOC_CTX *mem_ctx,
2045 const DOM_SID *group_sid,
2046 const char *member)
2048 struct policy_handle connect_pol, domain_pol;
2049 NTSTATUS result;
2050 uint32 group_rid;
2051 struct policy_handle group_pol;
2053 struct samr_Ids rids, rid_types;
2054 struct lsa_String lsa_acct_name;
2056 DOM_SID sid;
2058 sid_copy(&sid, group_sid);
2060 if (!sid_split_rid(&sid, &group_rid))
2061 return NT_STATUS_UNSUCCESSFUL;
2063 /* Get sam policy handle */
2064 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2065 pipe_hnd->desthost,
2066 MAXIMUM_ALLOWED_ACCESS,
2067 &connect_pol);
2068 if (!NT_STATUS_IS_OK(result))
2069 return result;
2071 /* Get domain policy handle */
2072 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2073 &connect_pol,
2074 MAXIMUM_ALLOWED_ACCESS,
2075 &sid,
2076 &domain_pol);
2077 if (!NT_STATUS_IS_OK(result))
2078 return result;
2080 init_lsa_String(&lsa_acct_name, member);
2082 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2083 &domain_pol,
2085 &lsa_acct_name,
2086 &rids,
2087 &rid_types);
2088 if (!NT_STATUS_IS_OK(result)) {
2089 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2090 member);
2091 goto done;
2094 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2095 &domain_pol,
2096 MAXIMUM_ALLOWED_ACCESS,
2097 group_rid,
2098 &group_pol);
2100 if (!NT_STATUS_IS_OK(result))
2101 goto done;
2103 result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
2104 &group_pol,
2105 rids.ids[0]);
2107 done:
2108 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2109 return result;
2112 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2113 TALLOC_CTX *mem_ctx,
2114 const DOM_SID *alias_sid,
2115 const char *member)
2117 struct policy_handle connect_pol, domain_pol;
2118 NTSTATUS result;
2119 uint32 alias_rid;
2120 struct policy_handle alias_pol;
2122 DOM_SID member_sid;
2123 enum lsa_SidType member_type;
2125 DOM_SID sid;
2127 sid_copy(&sid, alias_sid);
2129 if (!sid_split_rid(&sid, &alias_rid))
2130 return NT_STATUS_UNSUCCESSFUL;
2132 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2133 member, &member_sid, &member_type);
2135 if (!NT_STATUS_IS_OK(result)) {
2136 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2137 member);
2138 return result;
2141 /* Get sam policy handle */
2142 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2143 pipe_hnd->desthost,
2144 MAXIMUM_ALLOWED_ACCESS,
2145 &connect_pol);
2146 if (!NT_STATUS_IS_OK(result)) {
2147 goto done;
2150 /* Get domain policy handle */
2151 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2152 &connect_pol,
2153 MAXIMUM_ALLOWED_ACCESS,
2154 &sid,
2155 &domain_pol);
2156 if (!NT_STATUS_IS_OK(result)) {
2157 goto done;
2160 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2161 &domain_pol,
2162 MAXIMUM_ALLOWED_ACCESS,
2163 alias_rid,
2164 &alias_pol);
2166 if (!NT_STATUS_IS_OK(result))
2167 return result;
2169 result = rpccli_samr_DeleteAliasMember(pipe_hnd, mem_ctx,
2170 &alias_pol,
2171 &member_sid);
2173 if (!NT_STATUS_IS_OK(result))
2174 return result;
2176 done:
2177 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2178 return result;
2181 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2182 const DOM_SID *domain_sid,
2183 const char *domain_name,
2184 struct cli_state *cli,
2185 struct rpc_pipe_client *pipe_hnd,
2186 TALLOC_CTX *mem_ctx,
2187 int argc,
2188 const char **argv)
2190 DOM_SID group_sid;
2191 enum lsa_SidType group_type;
2193 if (argc != 2 || c->display_usage) {
2194 d_printf("%s\n%s",
2195 _("Usage:"),
2196 _("net rpc group delmem <group> <member>\n"
2197 " Delete a member from a group\n"
2198 " group\tGroup to delete member from\n"
2199 " member\tMember to delete from group\n"));
2200 return NT_STATUS_UNSUCCESSFUL;
2203 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2204 &group_sid, &group_type))) {
2205 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2206 argv[0]);
2207 return NT_STATUS_UNSUCCESSFUL;
2210 if (group_type == SID_NAME_DOM_GRP) {
2211 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2212 &group_sid, argv[1]);
2214 if (!NT_STATUS_IS_OK(result)) {
2215 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2216 argv[1], argv[0], nt_errstr(result));
2218 return result;
2221 if (group_type == SID_NAME_ALIAS) {
2222 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2223 &group_sid, argv[1]);
2225 if (!NT_STATUS_IS_OK(result)) {
2226 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2227 argv[1], argv[0], nt_errstr(result));
2229 return result;
2232 d_fprintf(stderr, _("Can only delete members from global or local "
2233 "groups which %s is not\n"), argv[0]);
2235 return NT_STATUS_UNSUCCESSFUL;
2238 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2240 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2241 rpc_group_delmem_internals,
2242 argc, argv);
2246 * List groups on a remote RPC server.
2248 * All parameters are provided by the run_rpc_command function, except for
2249 * argc, argv which are passes through.
2251 * @param domain_sid The domain sid acquired from the remote server.
2252 * @param cli A cli_state connected to the server.
2253 * @param mem_ctx Talloc context, destroyed on completion of the function.
2254 * @param argc Standard main() style argc.
2255 * @param argv Standard main() style argv. Initial components are already
2256 * stripped.
2258 * @return Normal NTSTATUS return.
2261 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2262 const DOM_SID *domain_sid,
2263 const char *domain_name,
2264 struct cli_state *cli,
2265 struct rpc_pipe_client *pipe_hnd,
2266 TALLOC_CTX *mem_ctx,
2267 int argc,
2268 const char **argv)
2270 struct policy_handle connect_pol, domain_pol;
2271 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2272 uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2273 struct samr_SamArray *groups = NULL;
2274 bool global = false;
2275 bool local = false;
2276 bool builtin = false;
2278 if (c->display_usage) {
2279 d_printf("%s\n%s",
2280 _("Usage:"),
2281 _("net rpc group list [global] [local] [builtin]\n"
2282 " List groups on RPC server\n"
2283 " global\tList global groups\n"
2284 " local\tList local groups\n"
2285 " builtin\tList builtin groups\n"
2286 " If none of global, local or builtin is "
2287 "specified, all three options are considered "
2288 "set\n"));
2289 return NT_STATUS_OK;
2292 if (argc == 0) {
2293 global = true;
2294 local = true;
2295 builtin = true;
2298 for (i=0; i<argc; i++) {
2299 if (strequal(argv[i], "global"))
2300 global = true;
2302 if (strequal(argv[i], "local"))
2303 local = true;
2305 if (strequal(argv[i], "builtin"))
2306 builtin = true;
2309 /* Get sam policy handle */
2311 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2312 pipe_hnd->desthost,
2313 MAXIMUM_ALLOWED_ACCESS,
2314 &connect_pol);
2315 if (!NT_STATUS_IS_OK(result)) {
2316 goto done;
2319 /* Get domain policy handle */
2321 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2322 &connect_pol,
2323 MAXIMUM_ALLOWED_ACCESS,
2324 CONST_DISCARD(struct dom_sid2 *, domain_sid),
2325 &domain_pol);
2326 if (!NT_STATUS_IS_OK(result)) {
2327 goto done;
2330 /* Query domain groups */
2331 if (c->opt_long_list_entries)
2332 d_printf(_("\nGroup name Comment"
2333 "\n-----------------------------\n"));
2334 do {
2335 uint32_t max_size, total_size, returned_size;
2336 union samr_DispInfo info;
2338 if (!global) break;
2340 get_query_dispinfo_params(
2341 loop_count, &max_entries, &max_size);
2343 result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
2344 &domain_pol,
2346 start_idx,
2347 max_entries,
2348 max_size,
2349 &total_size,
2350 &returned_size,
2351 &info);
2352 num_entries = info.info3.count;
2353 start_idx += info.info3.count;
2355 if (!NT_STATUS_IS_OK(result) &&
2356 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2357 break;
2359 for (i = 0; i < num_entries; i++) {
2361 const char *group = NULL;
2362 const char *desc = NULL;
2364 group = info.info3.entries[i].account_name.string;
2365 desc = info.info3.entries[i].description.string;
2367 if (c->opt_long_list_entries)
2368 printf("%-21.21s %-50.50s\n",
2369 group, desc);
2370 else
2371 printf("%s\n", group);
2373 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2374 /* query domain aliases */
2375 start_idx = 0;
2376 do {
2377 if (!local) break;
2379 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2380 &domain_pol,
2381 &start_idx,
2382 &groups,
2383 0xffff,
2384 &num_entries);
2385 if (!NT_STATUS_IS_OK(result) &&
2386 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2387 break;
2389 for (i = 0; i < num_entries; i++) {
2391 const char *description = NULL;
2393 if (c->opt_long_list_entries) {
2395 struct policy_handle alias_pol;
2396 union samr_AliasInfo *info = NULL;
2398 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2399 &domain_pol,
2400 0x8,
2401 groups->entries[i].idx,
2402 &alias_pol))) &&
2403 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2404 &alias_pol,
2406 &info))) &&
2407 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2408 &alias_pol)))) {
2409 description = info->description.string;
2413 if (description != NULL) {
2414 printf("%-21.21s %-50.50s\n",
2415 groups->entries[i].name.string,
2416 description);
2417 } else {
2418 printf("%s\n", groups->entries[i].name.string);
2421 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2422 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2423 /* Get builtin policy handle */
2425 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2426 &connect_pol,
2427 MAXIMUM_ALLOWED_ACCESS,
2428 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2429 &domain_pol);
2430 if (!NT_STATUS_IS_OK(result)) {
2431 goto done;
2433 /* query builtin aliases */
2434 start_idx = 0;
2435 do {
2436 if (!builtin) break;
2438 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2439 &domain_pol,
2440 &start_idx,
2441 &groups,
2442 max_entries,
2443 &num_entries);
2444 if (!NT_STATUS_IS_OK(result) &&
2445 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2446 break;
2448 for (i = 0; i < num_entries; i++) {
2450 const char *description = NULL;
2452 if (c->opt_long_list_entries) {
2454 struct policy_handle alias_pol;
2455 union samr_AliasInfo *info = NULL;
2457 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2458 &domain_pol,
2459 0x8,
2460 groups->entries[i].idx,
2461 &alias_pol))) &&
2462 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2463 &alias_pol,
2465 &info))) &&
2466 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2467 &alias_pol)))) {
2468 description = info->description.string;
2472 if (description != NULL) {
2473 printf("%-21.21s %-50.50s\n",
2474 groups->entries[i].name.string,
2475 description);
2476 } else {
2477 printf("%s\n", groups->entries[i].name.string);
2480 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2482 done:
2483 return result;
2486 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2488 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2489 rpc_group_list_internals,
2490 argc, argv);
2493 static NTSTATUS rpc_list_group_members(struct net_context *c,
2494 struct rpc_pipe_client *pipe_hnd,
2495 TALLOC_CTX *mem_ctx,
2496 const char *domain_name,
2497 const DOM_SID *domain_sid,
2498 struct policy_handle *domain_pol,
2499 uint32 rid)
2501 NTSTATUS result;
2502 struct policy_handle group_pol;
2503 uint32 num_members, *group_rids;
2504 int i;
2505 struct samr_RidTypeArray *rids = NULL;
2506 struct lsa_Strings names;
2507 struct samr_Ids types;
2509 fstring sid_str;
2510 sid_to_fstring(sid_str, domain_sid);
2512 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2513 domain_pol,
2514 MAXIMUM_ALLOWED_ACCESS,
2515 rid,
2516 &group_pol);
2518 if (!NT_STATUS_IS_OK(result))
2519 return result;
2521 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
2522 &group_pol,
2523 &rids);
2525 if (!NT_STATUS_IS_OK(result))
2526 return result;
2528 num_members = rids->count;
2529 group_rids = rids->rids;
2531 while (num_members > 0) {
2532 int this_time = 512;
2534 if (num_members < this_time)
2535 this_time = num_members;
2537 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
2538 domain_pol,
2539 this_time,
2540 group_rids,
2541 &names,
2542 &types);
2544 if (!NT_STATUS_IS_OK(result))
2545 return result;
2547 /* We only have users as members, but make the output
2548 the same as the output of alias members */
2550 for (i = 0; i < this_time; i++) {
2552 if (c->opt_long_list_entries) {
2553 printf("%s-%d %s\\%s %d\n", sid_str,
2554 group_rids[i], domain_name,
2555 names.names[i].string,
2556 SID_NAME_USER);
2557 } else {
2558 printf("%s\\%s\n", domain_name,
2559 names.names[i].string);
2563 num_members -= this_time;
2564 group_rids += 512;
2567 return NT_STATUS_OK;
2570 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2571 struct rpc_pipe_client *pipe_hnd,
2572 TALLOC_CTX *mem_ctx,
2573 struct policy_handle *domain_pol,
2574 uint32 rid)
2576 NTSTATUS result;
2577 struct rpc_pipe_client *lsa_pipe;
2578 struct policy_handle alias_pol, lsa_pol;
2579 uint32 num_members;
2580 DOM_SID *alias_sids;
2581 char **domains;
2582 char **names;
2583 enum lsa_SidType *types;
2584 int i;
2585 struct lsa_SidArray sid_array;
2587 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2588 domain_pol,
2589 MAXIMUM_ALLOWED_ACCESS,
2590 rid,
2591 &alias_pol);
2593 if (!NT_STATUS_IS_OK(result))
2594 return result;
2596 result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
2597 &alias_pol,
2598 &sid_array);
2600 if (!NT_STATUS_IS_OK(result)) {
2601 d_fprintf(stderr, _("Couldn't list alias members\n"));
2602 return result;
2605 num_members = sid_array.num_sids;
2607 if (num_members == 0) {
2608 return NT_STATUS_OK;
2611 result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2612 &ndr_table_lsarpc.syntax_id,
2613 &lsa_pipe);
2614 if (!NT_STATUS_IS_OK(result)) {
2615 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
2616 nt_errstr(result) );
2617 return result;
2620 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2621 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2623 if (!NT_STATUS_IS_OK(result)) {
2624 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
2625 TALLOC_FREE(lsa_pipe);
2626 return result;
2629 alias_sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_members);
2630 if (!alias_sids) {
2631 d_fprintf(stderr, _("Out of memory\n"));
2632 TALLOC_FREE(lsa_pipe);
2633 return NT_STATUS_NO_MEMORY;
2636 for (i=0; i<num_members; i++) {
2637 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2640 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
2641 num_members, alias_sids,
2642 &domains, &names, &types);
2644 if (!NT_STATUS_IS_OK(result) &&
2645 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2646 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
2647 TALLOC_FREE(lsa_pipe);
2648 return result;
2651 for (i = 0; i < num_members; i++) {
2652 fstring sid_str;
2653 sid_to_fstring(sid_str, &alias_sids[i]);
2655 if (c->opt_long_list_entries) {
2656 printf("%s %s\\%s %d\n", sid_str,
2657 domains[i] ? domains[i] : _("*unknown*"),
2658 names[i] ? names[i] : _("*unknown*"), types[i]);
2659 } else {
2660 if (domains[i])
2661 printf("%s\\%s\n", domains[i], names[i]);
2662 else
2663 printf("%s\n", sid_str);
2667 TALLOC_FREE(lsa_pipe);
2668 return NT_STATUS_OK;
2671 static NTSTATUS rpc_group_members_internals(struct net_context *c,
2672 const DOM_SID *domain_sid,
2673 const char *domain_name,
2674 struct cli_state *cli,
2675 struct rpc_pipe_client *pipe_hnd,
2676 TALLOC_CTX *mem_ctx,
2677 int argc,
2678 const char **argv)
2680 NTSTATUS result;
2681 struct policy_handle connect_pol, domain_pol;
2682 struct samr_Ids rids, rid_types;
2683 struct lsa_String lsa_acct_name;
2685 /* Get sam policy handle */
2687 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2688 pipe_hnd->desthost,
2689 MAXIMUM_ALLOWED_ACCESS,
2690 &connect_pol);
2692 if (!NT_STATUS_IS_OK(result))
2693 return result;
2695 /* Get domain policy handle */
2697 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2698 &connect_pol,
2699 MAXIMUM_ALLOWED_ACCESS,
2700 CONST_DISCARD(struct dom_sid2 *, domain_sid),
2701 &domain_pol);
2703 if (!NT_STATUS_IS_OK(result))
2704 return result;
2706 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
2708 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2709 &domain_pol,
2711 &lsa_acct_name,
2712 &rids,
2713 &rid_types);
2715 if (!NT_STATUS_IS_OK(result)) {
2717 /* Ok, did not find it in the global sam, try with builtin */
2719 DOM_SID sid_Builtin;
2721 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2723 sid_copy(&sid_Builtin, &global_sid_Builtin);
2725 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2726 &connect_pol,
2727 MAXIMUM_ALLOWED_ACCESS,
2728 &sid_Builtin,
2729 &domain_pol);
2731 if (!NT_STATUS_IS_OK(result)) {
2732 d_fprintf(stderr, _("Couldn't find group %s\n"),
2733 argv[0]);
2734 return result;
2737 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2738 &domain_pol,
2740 &lsa_acct_name,
2741 &rids,
2742 &rid_types);
2744 if (!NT_STATUS_IS_OK(result)) {
2745 d_fprintf(stderr, _("Couldn't find group %s\n"),
2746 argv[0]);
2747 return result;
2751 if (rids.count != 1) {
2752 d_fprintf(stderr, _("Couldn't find group %s\n"),
2753 argv[0]);
2754 return result;
2757 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
2758 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
2759 domain_sid, &domain_pol,
2760 rids.ids[0]);
2763 if (rid_types.ids[0] == SID_NAME_ALIAS) {
2764 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
2765 rids.ids[0]);
2768 return NT_STATUS_NO_SUCH_GROUP;
2771 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
2773 if (argc != 1 || c->display_usage) {
2774 return rpc_group_usage(c, argc, argv);
2777 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2778 rpc_group_members_internals,
2779 argc, argv);
2782 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
2784 NET_API_STATUS status;
2785 struct GROUP_INFO_0 g0;
2786 uint32_t parm_err;
2788 if (argc != 2) {
2789 d_printf(_("Usage:\n"));
2790 d_printf("net rpc group rename group newname\n");
2791 return -1;
2794 g0.grpi0_name = argv[1];
2796 status = NetGroupSetInfo(c->opt_host,
2797 argv[0],
2799 (uint8_t *)&g0,
2800 &parm_err);
2802 if (status != 0) {
2803 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
2804 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2805 status));
2806 return -1;
2809 return 0;
2812 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
2814 if (argc != 2 || c->display_usage) {
2815 return rpc_group_usage(c, argc, argv);
2818 return rpc_group_rename_internals(c, argc, argv);
2822 * 'net rpc group' entrypoint.
2823 * @param argc Standard main() style argc.
2824 * @param argv Standard main() style argv. Initial components are already
2825 * stripped.
2828 int net_rpc_group(struct net_context *c, int argc, const char **argv)
2830 NET_API_STATUS status;
2832 struct functable func[] = {
2834 "add",
2835 rpc_group_add,
2836 NET_TRANSPORT_RPC,
2837 N_("Create specified group"),
2838 N_("net rpc group add\n"
2839 " Create specified group")
2842 "delete",
2843 rpc_group_delete,
2844 NET_TRANSPORT_RPC,
2845 N_("Delete specified group"),
2846 N_("net rpc group delete\n"
2847 " Delete specified group")
2850 "addmem",
2851 rpc_group_addmem,
2852 NET_TRANSPORT_RPC,
2853 N_("Add member to group"),
2854 N_("net rpc group addmem\n"
2855 " Add member to group")
2858 "delmem",
2859 rpc_group_delmem,
2860 NET_TRANSPORT_RPC,
2861 N_("Remove member from group"),
2862 N_("net rpc group delmem\n"
2863 " Remove member from group")
2866 "list",
2867 rpc_group_list,
2868 NET_TRANSPORT_RPC,
2869 N_("List groups"),
2870 N_("net rpc group list\n"
2871 " List groups")
2874 "members",
2875 rpc_group_members,
2876 NET_TRANSPORT_RPC,
2877 N_("List group members"),
2878 N_("net rpc group members\n"
2879 " List group members")
2882 "rename",
2883 rpc_group_rename,
2884 NET_TRANSPORT_RPC,
2885 N_("Rename group"),
2886 N_("net rpc group rename\n"
2887 " Rename group")
2889 {NULL, NULL, 0, NULL, NULL}
2892 status = libnetapi_init(&c->netapi_ctx);
2893 if (status != 0) {
2894 return -1;
2896 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
2897 libnetapi_set_password(c->netapi_ctx, c->opt_password);
2898 if (c->opt_kerberos) {
2899 libnetapi_set_use_kerberos(c->netapi_ctx);
2902 if (argc == 0) {
2903 if (c->display_usage) {
2904 d_printf(_("Usage:\n"));
2905 d_printf(_("net rpc group\n"
2906 " Alias for net rpc group list global "
2907 "local builtin\n"));
2908 net_display_usage_from_functable(func);
2909 return 0;
2912 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2913 rpc_group_list_internals,
2914 argc, argv);
2917 return net_run_function(c, argc, argv, "net rpc group", func);
2920 /****************************************************************************/
2922 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
2924 return net_share_usage(c, argc, argv);
2928 * Add a share on a remote RPC server.
2930 * @param argc Standard main() style argc.
2931 * @param argv Standard main() style argv. Initial components are already
2932 * stripped.
2934 * @return A shell status integer (0 for success).
2937 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
2939 NET_API_STATUS status;
2940 char *sharename;
2941 char *path;
2942 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
2943 uint32 num_users=0, perms=0;
2944 char *password=NULL; /* don't allow a share password */
2945 struct SHARE_INFO_2 i2;
2946 uint32_t parm_error = 0;
2948 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
2949 return rpc_share_usage(c, argc, argv);
2952 if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
2953 return -1;
2956 path = strchr(sharename, '=');
2957 if (!path) {
2958 return -1;
2961 *path++ = '\0';
2963 i2.shi2_netname = sharename;
2964 i2.shi2_type = type;
2965 i2.shi2_remark = c->opt_comment;
2966 i2.shi2_permissions = perms;
2967 i2.shi2_max_uses = c->opt_maxusers;
2968 i2.shi2_current_uses = num_users;
2969 i2.shi2_path = path;
2970 i2.shi2_passwd = password;
2972 status = NetShareAdd(c->opt_host,
2974 (uint8_t *)&i2,
2975 &parm_error);
2976 if (status != 0) {
2977 printf(_("NetShareAdd failed with: %s\n"),
2978 libnetapi_get_error_string(c->netapi_ctx, status));
2981 return status;
2985 * Delete a share on a remote RPC server.
2987 * @param domain_sid The domain sid acquired from the remote server.
2988 * @param argc Standard main() style argc.
2989 * @param argv Standard main() style argv. Initial components are already
2990 * stripped.
2992 * @return A shell status integer (0 for success).
2994 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
2996 if (argc < 1 || c->display_usage) {
2997 return rpc_share_usage(c, argc, argv);
3000 return NetShareDel(c->opt_host, argv[0], 0);
3004 * Formatted print of share info
3006 * @param r pointer to SHARE_INFO_1 to format
3009 static void display_share_info_1(struct net_context *c,
3010 struct SHARE_INFO_1 *r)
3012 if (c->opt_long_list_entries) {
3013 d_printf("%-12s %-8.8s %-50s\n",
3014 r->shi1_netname,
3015 net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3016 r->shi1_remark);
3017 } else {
3018 d_printf("%s\n", r->shi1_netname);
3022 static WERROR get_share_info(struct net_context *c,
3023 struct rpc_pipe_client *pipe_hnd,
3024 TALLOC_CTX *mem_ctx,
3025 uint32 level,
3026 int argc,
3027 const char **argv,
3028 struct srvsvc_NetShareInfoCtr *info_ctr)
3030 WERROR result;
3031 NTSTATUS status;
3032 union srvsvc_NetShareInfo info;
3034 /* no specific share requested, enumerate all */
3035 if (argc == 0) {
3037 uint32_t preferred_len = 0xffffffff;
3038 uint32_t total_entries = 0;
3039 uint32_t resume_handle = 0;
3041 info_ctr->level = level;
3043 status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, mem_ctx,
3044 pipe_hnd->desthost,
3045 info_ctr,
3046 preferred_len,
3047 &total_entries,
3048 &resume_handle,
3049 &result);
3050 return result;
3053 /* request just one share */
3054 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
3055 pipe_hnd->desthost,
3056 argv[0],
3057 level,
3058 &info,
3059 &result);
3061 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
3062 goto done;
3065 /* construct ctr */
3066 ZERO_STRUCTP(info_ctr);
3068 info_ctr->level = level;
3070 switch (level) {
3071 case 1:
3073 struct srvsvc_NetShareCtr1 *ctr1;
3075 ctr1 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr1);
3076 W_ERROR_HAVE_NO_MEMORY(ctr1);
3078 ctr1->count = 1;
3079 ctr1->array = info.info1;
3081 info_ctr->ctr.ctr1 = ctr1;
3083 case 2:
3085 struct srvsvc_NetShareCtr2 *ctr2;
3087 ctr2 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr2);
3088 W_ERROR_HAVE_NO_MEMORY(ctr2);
3090 ctr2->count = 1;
3091 ctr2->array = info.info2;
3093 info_ctr->ctr.ctr2 = ctr2;
3095 case 502:
3097 struct srvsvc_NetShareCtr502 *ctr502;
3099 ctr502 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr502);
3100 W_ERROR_HAVE_NO_MEMORY(ctr502);
3102 ctr502->count = 1;
3103 ctr502->array = info.info502;
3105 info_ctr->ctr.ctr502 = ctr502;
3107 } /* switch */
3108 done:
3109 return result;
3112 /***
3113 * 'net rpc share list' entrypoint.
3114 * @param argc Standard main() style argc.
3115 * @param argv Standard main() style argv. Initial components are already
3116 * stripped.
3118 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3120 NET_API_STATUS status;
3121 struct SHARE_INFO_1 *i1 = NULL;
3122 uint32_t entries_read = 0;
3123 uint32_t total_entries = 0;
3124 uint32_t resume_handle = 0;
3125 uint32_t i, level = 1;
3127 if (c->display_usage) {
3128 d_printf( "%s\n"
3129 "net rpc share list\n"
3130 " %s\n",
3131 _("Usage:"),
3132 _("List shares on remote server"));
3133 return 0;
3136 status = NetShareEnum(c->opt_host,
3137 level,
3138 (uint8_t **)(void *)&i1,
3139 (uint32_t)-1,
3140 &entries_read,
3141 &total_entries,
3142 &resume_handle);
3143 if (status != 0) {
3144 goto done;
3147 /* Display results */
3149 if (c->opt_long_list_entries) {
3150 d_printf(_(
3151 "\nEnumerating shared resources (exports) on remote server:\n\n"
3152 "\nShare name Type Description\n"
3153 "---------- ---- -----------\n"));
3155 for (i = 0; i < entries_read; i++)
3156 display_share_info_1(c, &i1[i]);
3157 done:
3158 return status;
3161 static bool check_share_availability(struct cli_state *cli, const char *netname)
3163 NTSTATUS status;
3165 status = cli_tcon_andx(cli, netname, "A:", "", 0);
3166 if (!NT_STATUS_IS_OK(status)) {
3167 d_printf(_("skipping [%s]: not a file share.\n"), netname);
3168 return false;
3171 status = cli_tdis(cli);
3172 if (!NT_STATUS_IS_OK(status)) {
3173 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3174 return false;
3177 return true;
3180 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3181 const char *netname, uint32 type)
3183 /* only support disk shares */
3184 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3185 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3186 type);
3187 return false;
3190 /* skip builtin shares */
3191 /* FIXME: should print$ be added too ? */
3192 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3193 strequal(netname,"global"))
3194 return false;
3196 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3197 printf(_("excluding [%s]\n"), netname);
3198 return false;
3201 return check_share_availability(cli, netname);
3205 * Migrate shares from a remote RPC server to the local RPC server.
3207 * All parameters are provided by the run_rpc_command function, except for
3208 * argc, argv which are passed through.
3210 * @param domain_sid The domain sid acquired from the remote server.
3211 * @param cli A cli_state connected to the server.
3212 * @param mem_ctx Talloc context, destroyed on completion of the function.
3213 * @param argc Standard main() style argc.
3214 * @param argv Standard main() style argv. Initial components are already
3215 * stripped.
3217 * @return Normal NTSTATUS return.
3220 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3221 const DOM_SID *domain_sid,
3222 const char *domain_name,
3223 struct cli_state *cli,
3224 struct rpc_pipe_client *pipe_hnd,
3225 TALLOC_CTX *mem_ctx,
3226 int argc,
3227 const char **argv)
3229 WERROR result;
3230 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3231 struct srvsvc_NetShareInfoCtr ctr_src;
3232 uint32 i;
3233 struct rpc_pipe_client *srvsvc_pipe = NULL;
3234 struct cli_state *cli_dst = NULL;
3235 uint32 level = 502; /* includes secdesc */
3236 uint32_t parm_error = 0;
3238 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3239 &ctr_src);
3240 if (!W_ERROR_IS_OK(result))
3241 goto done;
3243 /* connect destination PI_SRVSVC */
3244 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3245 &ndr_table_srvsvc.syntax_id);
3246 if (!NT_STATUS_IS_OK(nt_status))
3247 return nt_status;
3250 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3252 union srvsvc_NetShareInfo info;
3253 struct srvsvc_NetShareInfo502 info502 =
3254 ctr_src.ctr.ctr502->array[i];
3256 /* reset error-code */
3257 nt_status = NT_STATUS_UNSUCCESSFUL;
3259 if (!check_share_sanity(c, cli, info502.name, info502.type))
3260 continue;
3262 /* finally add the share on the dst server */
3264 printf(_("migrating: [%s], path: %s, comment: %s, without "
3265 "share-ACLs\n"),
3266 info502.name, info502.path, info502.comment);
3268 info.info502 = &info502;
3270 nt_status = rpccli_srvsvc_NetShareAdd(srvsvc_pipe, mem_ctx,
3271 srvsvc_pipe->desthost,
3272 502,
3273 &info,
3274 &parm_error,
3275 &result);
3277 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3278 printf(_(" [%s] does already exist\n"),
3279 info502.name);
3280 continue;
3283 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3284 printf(_("cannot add share: %s\n"), win_errstr(result));
3285 goto done;
3290 nt_status = NT_STATUS_OK;
3292 done:
3293 if (cli_dst) {
3294 cli_shutdown(cli_dst);
3297 return nt_status;
3302 * Migrate shares from a RPC server to another.
3304 * @param argc Standard main() style argc.
3305 * @param argv Standard main() style argv. Initial components are already
3306 * stripped.
3308 * @return A shell status integer (0 for success).
3310 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3311 const char **argv)
3313 if (c->display_usage) {
3314 d_printf( "%s\n"
3315 "net rpc share migrate shares\n"
3316 " %s\n",
3317 _("Usage:"),
3318 _("Migrate shares to local server"));
3319 return 0;
3322 if (!c->opt_host) {
3323 printf(_("no server to migrate\n"));
3324 return -1;
3327 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3328 rpc_share_migrate_shares_internals,
3329 argc, argv);
3333 * Copy a file/dir
3335 * @param f file_info
3336 * @param mask current search mask
3337 * @param state arg-pointer
3340 static void copy_fn(const char *mnt, file_info *f,
3341 const char *mask, void *state)
3343 static NTSTATUS nt_status;
3344 static struct copy_clistate *local_state;
3345 static fstring filename, new_mask;
3346 fstring dir;
3347 char *old_dir;
3348 struct net_context *c;
3350 local_state = (struct copy_clistate *)state;
3351 nt_status = NT_STATUS_UNSUCCESSFUL;
3353 c = local_state->c;
3355 if (strequal(f->name, ".") || strequal(f->name, ".."))
3356 return;
3358 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3360 /* DIRECTORY */
3361 if (f->mode & aDIR) {
3363 DEBUG(3,("got dir: %s\n", f->name));
3365 fstrcpy(dir, local_state->cwd);
3366 fstrcat(dir, "\\");
3367 fstrcat(dir, f->name);
3369 switch (net_mode_share)
3371 case NET_MODE_SHARE_MIGRATE:
3372 /* create that directory */
3373 nt_status = net_copy_file(c, local_state->mem_ctx,
3374 local_state->cli_share_src,
3375 local_state->cli_share_dst,
3376 dir, dir,
3377 c->opt_acls? true : false,
3378 c->opt_attrs? true : false,
3379 c->opt_timestamps? true:false,
3380 false);
3381 break;
3382 default:
3383 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3384 return;
3387 if (!NT_STATUS_IS_OK(nt_status))
3388 printf(_("could not handle dir %s: %s\n"),
3389 dir, nt_errstr(nt_status));
3391 /* search below that directory */
3392 fstrcpy(new_mask, dir);
3393 fstrcat(new_mask, "\\*");
3395 old_dir = local_state->cwd;
3396 local_state->cwd = dir;
3397 if (!sync_files(local_state, new_mask))
3398 printf(_("could not handle files\n"));
3399 local_state->cwd = old_dir;
3401 return;
3405 /* FILE */
3406 fstrcpy(filename, local_state->cwd);
3407 fstrcat(filename, "\\");
3408 fstrcat(filename, f->name);
3410 DEBUG(3,("got file: %s\n", filename));
3412 switch (net_mode_share)
3414 case NET_MODE_SHARE_MIGRATE:
3415 nt_status = net_copy_file(c, local_state->mem_ctx,
3416 local_state->cli_share_src,
3417 local_state->cli_share_dst,
3418 filename, filename,
3419 c->opt_acls? true : false,
3420 c->opt_attrs? true : false,
3421 c->opt_timestamps? true: false,
3422 true);
3423 break;
3424 default:
3425 d_fprintf(stderr, _("Unsupported file mode %d\n"),
3426 net_mode_share);
3427 return;
3430 if (!NT_STATUS_IS_OK(nt_status))
3431 printf(_("could not handle file %s: %s\n"),
3432 filename, nt_errstr(nt_status));
3437 * sync files, can be called recursivly to list files
3438 * and then call copy_fn for each file
3440 * @param cp_clistate pointer to the copy_clistate we work with
3441 * @param mask the current search mask
3443 * @return Boolean result
3445 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask)
3447 struct cli_state *targetcli;
3448 char *targetpath = NULL;
3450 DEBUG(3,("calling cli_list with mask: %s\n", mask));
3452 if ( !cli_resolve_path(talloc_tos(), "", NULL, cp_clistate->cli_share_src,
3453 mask, &targetcli, &targetpath ) ) {
3454 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
3455 "%s\n"),
3456 mask, cli_errstr(cp_clistate->cli_share_src));
3457 return false;
3460 if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3461 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
3462 mask, cli_errstr(targetcli));
3463 return false;
3466 return true;
3471 * Set the top level directory permissions before we do any further copies.
3472 * Should set up ACL inheritance.
3475 bool copy_top_level_perms(struct net_context *c,
3476 struct copy_clistate *cp_clistate,
3477 const char *sharename)
3479 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3481 switch (net_mode_share) {
3482 case NET_MODE_SHARE_MIGRATE:
3483 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3484 nt_status = net_copy_fileattr(c,
3485 cp_clistate->mem_ctx,
3486 cp_clistate->cli_share_src,
3487 cp_clistate->cli_share_dst,
3488 "\\", "\\",
3489 c->opt_acls? true : false,
3490 c->opt_attrs? true : false,
3491 c->opt_timestamps? true: false,
3492 false);
3493 break;
3494 default:
3495 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3496 break;
3499 if (!NT_STATUS_IS_OK(nt_status)) {
3500 printf(_("Could handle directory attributes for top level "
3501 "directory of share %s. Error %s\n"),
3502 sharename, nt_errstr(nt_status));
3503 return false;
3506 return true;
3510 * Sync all files inside a remote share to another share (over smb).
3512 * All parameters are provided by the run_rpc_command function, except for
3513 * argc, argv which are passed through.
3515 * @param domain_sid The domain sid acquired from the remote server.
3516 * @param cli A cli_state connected to the server.
3517 * @param mem_ctx Talloc context, destroyed on completion of the function.
3518 * @param argc Standard main() style argc.
3519 * @param argv Standard main() style argv. Initial components are already
3520 * stripped.
3522 * @return Normal NTSTATUS return.
3525 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
3526 const DOM_SID *domain_sid,
3527 const char *domain_name,
3528 struct cli_state *cli,
3529 struct rpc_pipe_client *pipe_hnd,
3530 TALLOC_CTX *mem_ctx,
3531 int argc,
3532 const char **argv)
3534 WERROR result;
3535 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3536 struct srvsvc_NetShareInfoCtr ctr_src;
3537 uint32 i;
3538 uint32 level = 502;
3539 struct copy_clistate cp_clistate;
3540 bool got_src_share = false;
3541 bool got_dst_share = false;
3542 const char *mask = "\\*";
3543 char *dst = NULL;
3545 dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3546 if (dst == NULL) {
3547 nt_status = NT_STATUS_NO_MEMORY;
3548 goto done;
3551 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3552 &ctr_src);
3554 if (!W_ERROR_IS_OK(result))
3555 goto done;
3557 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3559 struct srvsvc_NetShareInfo502 info502 =
3560 ctr_src.ctr.ctr502->array[i];
3562 if (!check_share_sanity(c, cli, info502.name, info502.type))
3563 continue;
3565 /* one might not want to mirror whole discs :) */
3566 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3567 d_printf(_("skipping [%s]: builtin/hidden share\n"),
3568 info502.name);
3569 continue;
3572 switch (net_mode_share)
3574 case NET_MODE_SHARE_MIGRATE:
3575 printf("syncing");
3576 break;
3577 default:
3578 d_fprintf(stderr, _("Unsupported mode %d\n"),
3579 net_mode_share);
3580 break;
3582 printf(_(" [%s] files and directories %s ACLs, %s DOS "
3583 "Attributes %s\n"),
3584 info502.name,
3585 c->opt_acls ? _("including") : _("without"),
3586 c->opt_attrs ? _("including") : _("without"),
3587 c->opt_timestamps ? _("(preserving timestamps)") : "");
3589 cp_clistate.mem_ctx = mem_ctx;
3590 cp_clistate.cli_share_src = NULL;
3591 cp_clistate.cli_share_dst = NULL;
3592 cp_clistate.cwd = NULL;
3593 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3594 cp_clistate.c = c;
3596 /* open share source */
3597 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
3598 &cli->dest_ss, cli->desthost,
3599 info502.name, "A:");
3600 if (!NT_STATUS_IS_OK(nt_status))
3601 goto done;
3603 got_src_share = true;
3605 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3606 /* open share destination */
3607 nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
3608 NULL, dst, info502.name, "A:");
3609 if (!NT_STATUS_IS_OK(nt_status))
3610 goto done;
3612 got_dst_share = true;
3615 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
3616 d_fprintf(stderr, _("Could not handle the top level "
3617 "directory permissions for the "
3618 "share: %s\n"), info502.name);
3619 nt_status = NT_STATUS_UNSUCCESSFUL;
3620 goto done;
3623 if (!sync_files(&cp_clistate, mask)) {
3624 d_fprintf(stderr, _("could not handle files for share: "
3625 "%s\n"), info502.name);
3626 nt_status = NT_STATUS_UNSUCCESSFUL;
3627 goto done;
3631 nt_status = NT_STATUS_OK;
3633 done:
3635 if (got_src_share)
3636 cli_shutdown(cp_clistate.cli_share_src);
3638 if (got_dst_share)
3639 cli_shutdown(cp_clistate.cli_share_dst);
3641 SAFE_FREE(dst);
3642 return nt_status;
3646 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
3648 if (c->display_usage) {
3649 d_printf( "%s\n"
3650 "net share migrate files\n"
3651 " %s\n",
3652 _("Usage:"),
3653 _("Migrate files to local server"));
3654 return 0;
3657 if (!c->opt_host) {
3658 d_printf(_("no server to migrate\n"));
3659 return -1;
3662 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3663 rpc_share_migrate_files_internals,
3664 argc, argv);
3668 * Migrate share-ACLs from a remote RPC server to the local RPC server.
3670 * All parameters are provided by the run_rpc_command function, except for
3671 * argc, argv which are passed through.
3673 * @param domain_sid The domain sid acquired from the remote server.
3674 * @param cli A cli_state connected to the server.
3675 * @param mem_ctx Talloc context, destroyed on completion of the function.
3676 * @param argc Standard main() style argc.
3677 * @param argv Standard main() style argv. Initial components are already
3678 * stripped.
3680 * @return Normal NTSTATUS return.
3683 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
3684 const DOM_SID *domain_sid,
3685 const char *domain_name,
3686 struct cli_state *cli,
3687 struct rpc_pipe_client *pipe_hnd,
3688 TALLOC_CTX *mem_ctx,
3689 int argc,
3690 const char **argv)
3692 WERROR result;
3693 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3694 struct srvsvc_NetShareInfoCtr ctr_src;
3695 union srvsvc_NetShareInfo info;
3696 uint32 i;
3697 struct rpc_pipe_client *srvsvc_pipe = NULL;
3698 struct cli_state *cli_dst = NULL;
3699 uint32 level = 502; /* includes secdesc */
3700 uint32_t parm_error = 0;
3702 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3703 &ctr_src);
3705 if (!W_ERROR_IS_OK(result))
3706 goto done;
3708 /* connect destination PI_SRVSVC */
3709 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3710 &ndr_table_srvsvc.syntax_id);
3711 if (!NT_STATUS_IS_OK(nt_status))
3712 return nt_status;
3715 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3717 struct srvsvc_NetShareInfo502 info502 =
3718 ctr_src.ctr.ctr502->array[i];
3720 /* reset error-code */
3721 nt_status = NT_STATUS_UNSUCCESSFUL;
3723 if (!check_share_sanity(c, cli, info502.name, info502.type))
3724 continue;
3726 printf(_("migrating: [%s], path: %s, comment: %s, including "
3727 "share-ACLs\n"),
3728 info502.name, info502.path, info502.comment);
3730 if (c->opt_verbose)
3731 display_sec_desc(info502.sd_buf.sd);
3733 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3734 info.info502 = &info502;
3736 /* finally modify the share on the dst server */
3737 nt_status = rpccli_srvsvc_NetShareSetInfo(srvsvc_pipe, mem_ctx,
3738 srvsvc_pipe->desthost,
3739 info502.name,
3740 level,
3741 &info,
3742 &parm_error,
3743 &result);
3744 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3745 printf(_("cannot set share-acl: %s\n"),
3746 win_errstr(result));
3747 goto done;
3752 nt_status = NT_STATUS_OK;
3754 done:
3755 if (cli_dst) {
3756 cli_shutdown(cli_dst);
3759 return nt_status;
3764 * Migrate share-acls from a RPC server to another.
3766 * @param argc Standard main() style argc.
3767 * @param argv Standard main() style argv. Initial components are already
3768 * stripped.
3770 * @return A shell status integer (0 for success).
3772 static int rpc_share_migrate_security(struct net_context *c, int argc,
3773 const char **argv)
3775 if (c->display_usage) {
3776 d_printf( "%s\n"
3777 "net rpc share migrate security\n"
3778 " %s\n",
3779 _("Usage:"),
3780 _("Migrate share-acls to local server"));
3781 return 0;
3784 if (!c->opt_host) {
3785 d_printf(_("no server to migrate\n"));
3786 return -1;
3789 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3790 rpc_share_migrate_security_internals,
3791 argc, argv);
3795 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3796 * from one server to another.
3798 * @param argc Standard main() style argc.
3799 * @param argv Standard main() style argv. Initial components are already
3800 * stripped.
3802 * @return A shell status integer (0 for success).
3805 static int rpc_share_migrate_all(struct net_context *c, int argc,
3806 const char **argv)
3808 int ret;
3810 if (c->display_usage) {
3811 d_printf( "%s\n"
3812 "net rpc share migrate all\n"
3813 " %s\n",
3814 _("Usage:"),
3815 _("Migrates shares including all share settings"));
3816 return 0;
3819 if (!c->opt_host) {
3820 d_printf(_("no server to migrate\n"));
3821 return -1;
3824 /* order is important. we don't want to be locked out by the share-acl
3825 * before copying files - gd */
3827 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3828 rpc_share_migrate_shares_internals, argc, argv);
3829 if (ret)
3830 return ret;
3832 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3833 rpc_share_migrate_files_internals, argc, argv);
3834 if (ret)
3835 return ret;
3837 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3838 rpc_share_migrate_security_internals, argc,
3839 argv);
3844 * 'net rpc share migrate' entrypoint.
3845 * @param argc Standard main() style argc.
3846 * @param argv Standard main() style argv. Initial components are already
3847 * stripped.
3849 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
3852 struct functable func[] = {
3854 "all",
3855 rpc_share_migrate_all,
3856 NET_TRANSPORT_RPC,
3857 N_("Migrate shares from remote to local server"),
3858 N_("net rpc share migrate all\n"
3859 " Migrate shares from remote to local server")
3862 "files",
3863 rpc_share_migrate_files,
3864 NET_TRANSPORT_RPC,
3865 N_("Migrate files from remote to local server"),
3866 N_("net rpc share migrate files\n"
3867 " Migrate files from remote to local server")
3870 "security",
3871 rpc_share_migrate_security,
3872 NET_TRANSPORT_RPC,
3873 N_("Migrate share-ACLs from remote to local server"),
3874 N_("net rpc share migrate security\n"
3875 " Migrate share-ACLs from remote to local server")
3878 "shares",
3879 rpc_share_migrate_shares,
3880 NET_TRANSPORT_RPC,
3881 N_("Migrate shares from remote to local server"),
3882 N_("net rpc share migrate shares\n"
3883 " Migrate shares from remote to local server")
3885 {NULL, NULL, 0, NULL, NULL}
3888 net_mode_share = NET_MODE_SHARE_MIGRATE;
3890 return net_run_function(c, argc, argv, "net rpc share migrate", func);
3893 struct full_alias {
3894 DOM_SID sid;
3895 uint32 num_members;
3896 DOM_SID *members;
3899 static int num_server_aliases;
3900 static struct full_alias *server_aliases;
3903 * Add an alias to the static list.
3905 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
3907 if (server_aliases == NULL)
3908 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
3910 server_aliases[num_server_aliases] = *alias;
3911 num_server_aliases += 1;
3915 * For a specific domain on the server, fetch all the aliases
3916 * and their members. Add all of them to the server_aliases.
3919 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
3920 TALLOC_CTX *mem_ctx,
3921 struct policy_handle *connect_pol,
3922 const DOM_SID *domain_sid)
3924 uint32 start_idx, max_entries, num_entries, i;
3925 struct samr_SamArray *groups = NULL;
3926 NTSTATUS result;
3927 struct policy_handle domain_pol;
3929 /* Get domain policy handle */
3931 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
3932 connect_pol,
3933 MAXIMUM_ALLOWED_ACCESS,
3934 CONST_DISCARD(struct dom_sid2 *, domain_sid),
3935 &domain_pol);
3936 if (!NT_STATUS_IS_OK(result))
3937 return result;
3939 start_idx = 0;
3940 max_entries = 250;
3942 do {
3943 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
3944 &domain_pol,
3945 &start_idx,
3946 &groups,
3947 max_entries,
3948 &num_entries);
3949 for (i = 0; i < num_entries; i++) {
3951 struct policy_handle alias_pol;
3952 struct full_alias alias;
3953 struct lsa_SidArray sid_array;
3954 int j;
3956 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
3957 &domain_pol,
3958 MAXIMUM_ALLOWED_ACCESS,
3959 groups->entries[i].idx,
3960 &alias_pol);
3961 if (!NT_STATUS_IS_OK(result))
3962 goto done;
3964 result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
3965 &alias_pol,
3966 &sid_array);
3967 if (!NT_STATUS_IS_OK(result))
3968 goto done;
3970 alias.num_members = sid_array.num_sids;
3972 result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
3973 if (!NT_STATUS_IS_OK(result))
3974 goto done;
3976 alias.members = NULL;
3978 if (alias.num_members > 0) {
3979 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
3981 for (j = 0; j < alias.num_members; j++)
3982 sid_copy(&alias.members[j],
3983 sid_array.sids[j].sid);
3986 sid_compose(&alias.sid, domain_sid,
3987 groups->entries[i].idx);
3989 push_alias(mem_ctx, &alias);
3991 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3993 result = NT_STATUS_OK;
3995 done:
3996 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
3998 return result;
4002 * Dump server_aliases as names for debugging purposes.
4005 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4006 const DOM_SID *domain_sid,
4007 const char *domain_name,
4008 struct cli_state *cli,
4009 struct rpc_pipe_client *pipe_hnd,
4010 TALLOC_CTX *mem_ctx,
4011 int argc,
4012 const char **argv)
4014 int i;
4015 NTSTATUS result;
4016 struct policy_handle lsa_pol;
4018 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4019 SEC_FLAG_MAXIMUM_ALLOWED,
4020 &lsa_pol);
4021 if (!NT_STATUS_IS_OK(result))
4022 return result;
4024 for (i=0; i<num_server_aliases; i++) {
4025 char **names;
4026 char **domains;
4027 enum lsa_SidType *types;
4028 int j;
4030 struct full_alias *alias = &server_aliases[i];
4032 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4033 &alias->sid,
4034 &domains, &names, &types);
4035 if (!NT_STATUS_IS_OK(result))
4036 continue;
4038 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4040 if (alias->num_members == 0) {
4041 DEBUG(1, ("\n"));
4042 continue;
4045 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4046 alias->num_members,
4047 alias->members,
4048 &domains, &names, &types);
4050 if (!NT_STATUS_IS_OK(result) &&
4051 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4052 continue;
4054 for (j=0; j<alias->num_members; j++)
4055 DEBUG(1, ("%s\\%s (%d); ",
4056 domains[j] ? domains[j] : "*unknown*",
4057 names[j] ? names[j] : "*unknown*",types[j]));
4058 DEBUG(1, ("\n"));
4061 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
4063 return NT_STATUS_OK;
4067 * Fetch a list of all server aliases and their members into
4068 * server_aliases.
4071 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4072 const DOM_SID *domain_sid,
4073 const char *domain_name,
4074 struct cli_state *cli,
4075 struct rpc_pipe_client *pipe_hnd,
4076 TALLOC_CTX *mem_ctx,
4077 int argc,
4078 const char **argv)
4080 NTSTATUS result;
4081 struct policy_handle connect_pol;
4083 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
4084 pipe_hnd->desthost,
4085 MAXIMUM_ALLOWED_ACCESS,
4086 &connect_pol);
4088 if (!NT_STATUS_IS_OK(result))
4089 goto done;
4091 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4092 &global_sid_Builtin);
4094 if (!NT_STATUS_IS_OK(result))
4095 goto done;
4097 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4098 domain_sid);
4100 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
4101 done:
4102 return result;
4105 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
4107 token->num_sids = 4;
4109 if (!(token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4))) {
4110 d_fprintf(stderr, "malloc %s\n",_("failed"));
4111 token->num_sids = 0;
4112 return;
4115 token->user_sids[0] = *user_sid;
4116 sid_copy(&token->user_sids[1], &global_sid_World);
4117 sid_copy(&token->user_sids[2], &global_sid_Network);
4118 sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
4121 static void free_user_token(NT_USER_TOKEN *token)
4123 SAFE_FREE(token->user_sids);
4126 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
4128 if (is_sid_in_token(token, sid))
4129 return;
4131 token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
4132 if (!token->user_sids) {
4133 return;
4136 sid_copy(&token->user_sids[token->num_sids], sid);
4138 token->num_sids += 1;
4141 struct user_token {
4142 fstring name;
4143 NT_USER_TOKEN token;
4146 static void dump_user_token(struct user_token *token)
4148 int i;
4150 d_printf("%s\n", token->name);
4152 for (i=0; i<token->token.num_sids; i++) {
4153 d_printf(" %s\n", sid_string_tos(&token->token.user_sids[i]));
4157 static bool is_alias_member(DOM_SID *sid, struct full_alias *alias)
4159 int i;
4161 for (i=0; i<alias->num_members; i++) {
4162 if (sid_compare(sid, &alias->members[i]) == 0)
4163 return true;
4166 return false;
4169 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
4171 int i;
4173 for (i=0; i<num_server_aliases; i++) {
4174 if (is_alias_member(&sid, &server_aliases[i]))
4175 add_sid_to_token(token, &server_aliases[i].sid);
4180 * We got a user token with all the SIDs we can know about without asking the
4181 * server directly. These are the user and domain group sids. All of these can
4182 * be members of aliases. So scan the list of aliases for each of the SIDs and
4183 * add them to the token.
4186 static void collect_alias_memberships(NT_USER_TOKEN *token)
4188 int num_global_sids = token->num_sids;
4189 int i;
4191 for (i=0; i<num_global_sids; i++) {
4192 collect_sid_memberships(token, token->user_sids[i]);
4196 static bool get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
4198 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4199 enum wbcSidType type;
4200 fstring full_name;
4201 struct wbcDomainSid wsid;
4202 char *sid_str = NULL;
4203 DOM_SID user_sid;
4204 uint32_t num_groups;
4205 gid_t *groups = NULL;
4206 uint32_t i;
4208 fstr_sprintf(full_name, "%s%c%s",
4209 domain, *lp_winbind_separator(), user);
4211 /* First let's find out the user sid */
4213 wbc_status = wbcLookupName(domain, user, &wsid, &type);
4215 if (!WBC_ERROR_IS_OK(wbc_status)) {
4216 DEBUG(1, ("winbind could not find %s: %s\n",
4217 full_name, wbcErrorString(wbc_status)));
4218 return false;
4221 wbc_status = wbcSidToString(&wsid, &sid_str);
4222 if (!WBC_ERROR_IS_OK(wbc_status)) {
4223 return false;
4226 if (type != SID_NAME_USER) {
4227 wbcFreeMemory(sid_str);
4228 DEBUG(1, ("%s is not a user\n", full_name));
4229 return false;
4232 if (!string_to_sid(&user_sid, sid_str)) {
4233 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4234 return false;
4237 wbcFreeMemory(sid_str);
4238 sid_str = NULL;
4240 init_user_token(token, &user_sid);
4242 /* And now the groups winbind knows about */
4244 wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4245 if (!WBC_ERROR_IS_OK(wbc_status)) {
4246 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4247 full_name, wbcErrorString(wbc_status)));
4248 return false;
4251 for (i = 0; i < num_groups; i++) {
4252 gid_t gid = groups[i];
4253 DOM_SID sid;
4255 wbc_status = wbcGidToSid(gid, &wsid);
4256 if (!WBC_ERROR_IS_OK(wbc_status)) {
4257 DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4258 (unsigned int)gid, wbcErrorString(wbc_status)));
4259 wbcFreeMemory(groups);
4260 return false;
4263 wbc_status = wbcSidToString(&wsid, &sid_str);
4264 if (!WBC_ERROR_IS_OK(wbc_status)) {
4265 wbcFreeMemory(groups);
4266 return false;
4269 DEBUG(3, (" %s\n", sid_str));
4271 string_to_sid(&sid, sid_str);
4272 wbcFreeMemory(sid_str);
4273 sid_str = NULL;
4275 add_sid_to_token(token, &sid);
4277 wbcFreeMemory(groups);
4279 return true;
4283 * Get a list of all user tokens we want to look at
4286 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4287 struct user_token **user_tokens)
4289 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4290 uint32_t i, num_users;
4291 const char **users;
4292 struct user_token *result;
4293 TALLOC_CTX *frame = NULL;
4295 if (lp_winbind_use_default_domain() &&
4296 (c->opt_target_workgroup == NULL)) {
4297 d_fprintf(stderr, _("winbind use default domain = yes set, "
4298 "please specify a workgroup\n"));
4299 return false;
4302 /* Send request to winbind daemon */
4304 wbc_status = wbcListUsers(NULL, &num_users, &users);
4305 if (!WBC_ERROR_IS_OK(wbc_status)) {
4306 DEBUG(1, (_("winbind could not list users: %s\n"),
4307 wbcErrorString(wbc_status)));
4308 return false;
4311 result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4313 if (result == NULL) {
4314 DEBUG(1, ("Could not malloc sid array\n"));
4315 wbcFreeMemory(users);
4316 return false;
4319 frame = talloc_stackframe();
4320 for (i=0; i < num_users; i++) {
4321 fstring domain, user;
4322 char *p;
4324 fstrcpy(result[i].name, users[i]);
4326 p = strchr(users[i], *lp_winbind_separator());
4328 DEBUG(3, ("%s\n", users[i]));
4330 if (p == NULL) {
4331 fstrcpy(domain, c->opt_target_workgroup);
4332 fstrcpy(user, users[i]);
4333 } else {
4334 *p++ = '\0';
4335 fstrcpy(domain, users[i]);
4336 strupper_m(domain);
4337 fstrcpy(user, p);
4340 get_user_sids(domain, user, &(result[i].token));
4341 i+=1;
4343 TALLOC_FREE(frame);
4344 wbcFreeMemory(users);
4346 *num_tokens = num_users;
4347 *user_tokens = result;
4349 return true;
4352 static bool get_user_tokens_from_file(FILE *f,
4353 int *num_tokens,
4354 struct user_token **tokens)
4356 struct user_token *token = NULL;
4358 while (!feof(f)) {
4359 fstring line;
4361 if (fgets(line, sizeof(line)-1, f) == NULL) {
4362 return true;
4365 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
4366 line[strlen(line)-1] = '\0';
4369 if (line[0] == ' ') {
4370 /* We have a SID */
4372 DOM_SID sid;
4373 if(!string_to_sid(&sid, &line[1])) {
4374 DEBUG(1,("get_user_tokens_from_file: Could "
4375 "not convert sid %s \n",&line[1]));
4376 return false;
4379 if (token == NULL) {
4380 DEBUG(0, ("File does not begin with username"));
4381 return false;
4384 add_sid_to_token(&token->token, &sid);
4385 continue;
4388 /* And a new user... */
4390 *num_tokens += 1;
4391 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4392 if (*tokens == NULL) {
4393 DEBUG(0, ("Could not realloc tokens\n"));
4394 return false;
4397 token = &((*tokens)[*num_tokens-1]);
4399 fstrcpy(token->name, line);
4400 token->token.num_sids = 0;
4401 token->token.user_sids = NULL;
4402 continue;
4405 return false;
4410 * Show the list of all users that have access to a share
4413 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4414 TALLOC_CTX *mem_ctx,
4415 const char *netname,
4416 int num_tokens,
4417 struct user_token *tokens)
4419 uint16_t fnum;
4420 SEC_DESC *share_sd = NULL;
4421 SEC_DESC *root_sd = NULL;
4422 struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4423 int i;
4424 union srvsvc_NetShareInfo info;
4425 WERROR result;
4426 NTSTATUS status;
4427 uint16 cnum;
4429 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4430 pipe_hnd->desthost,
4431 netname,
4432 502,
4433 &info,
4434 &result);
4436 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4437 DEBUG(1, ("Coult not query secdesc for share %s\n",
4438 netname));
4439 return;
4442 share_sd = info.info502->sd_buf.sd;
4443 if (share_sd == NULL) {
4444 DEBUG(1, ("Got no secdesc for share %s\n",
4445 netname));
4448 cnum = cli->cnum;
4450 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
4451 return;
4454 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
4455 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
4456 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4459 for (i=0; i<num_tokens; i++) {
4460 uint32 acc_granted;
4462 if (share_sd != NULL) {
4463 status = se_access_check(share_sd, &tokens[i].token,
4464 1, &acc_granted);
4466 if (!NT_STATUS_IS_OK(status)) {
4467 DEBUG(1, ("Could not check share_sd for "
4468 "user %s\n",
4469 tokens[i].name));
4470 continue;
4474 if (root_sd == NULL) {
4475 d_printf(" %s\n", tokens[i].name);
4476 continue;
4479 status = se_access_check(root_sd, &tokens[i].token,
4480 1, &acc_granted);
4481 if (!NT_STATUS_IS_OK(status)) {
4482 DEBUG(1, ("Could not check root_sd for user %s\n",
4483 tokens[i].name));
4484 continue;
4486 d_printf(" %s\n", tokens[i].name);
4489 if (fnum != (uint16_t)-1)
4490 cli_close(cli, fnum);
4491 cli_tdis(cli);
4492 cli->cnum = cnum;
4494 return;
4497 struct share_list {
4498 int num_shares;
4499 char **shares;
4502 static void collect_share(const char *name, uint32 m,
4503 const char *comment, void *state)
4505 struct share_list *share_list = (struct share_list *)state;
4507 if (m != STYPE_DISKTREE)
4508 return;
4510 share_list->num_shares += 1;
4511 share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4512 if (!share_list->shares) {
4513 share_list->num_shares = 0;
4514 return;
4516 share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4520 * List shares on a remote RPC server, including the security descriptors.
4522 * All parameters are provided by the run_rpc_command function, except for
4523 * argc, argv which are passed through.
4525 * @param domain_sid The domain sid acquired from the remote server.
4526 * @param cli A cli_state connected to the server.
4527 * @param mem_ctx Talloc context, destroyed on completion of the function.
4528 * @param argc Standard main() style argc.
4529 * @param argv Standard main() style argv. Initial components are already
4530 * stripped.
4532 * @return Normal NTSTATUS return.
4535 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
4536 const DOM_SID *domain_sid,
4537 const char *domain_name,
4538 struct cli_state *cli,
4539 struct rpc_pipe_client *pipe_hnd,
4540 TALLOC_CTX *mem_ctx,
4541 int argc,
4542 const char **argv)
4544 int ret;
4545 bool r;
4546 uint32 i;
4547 FILE *f;
4549 struct user_token *tokens = NULL;
4550 int num_tokens = 0;
4552 struct share_list share_list;
4554 if (argc == 0) {
4555 f = stdin;
4556 } else {
4557 f = fopen(argv[0], "r");
4560 if (f == NULL) {
4561 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4562 return NT_STATUS_UNSUCCESSFUL;
4565 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4567 if (f != stdin)
4568 fclose(f);
4570 if (!r) {
4571 DEBUG(0, ("Could not read users from file\n"));
4572 return NT_STATUS_UNSUCCESSFUL;
4575 for (i=0; i<num_tokens; i++)
4576 collect_alias_memberships(&tokens[i].token);
4578 share_list.num_shares = 0;
4579 share_list.shares = NULL;
4581 ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4583 if (ret == -1) {
4584 DEBUG(0, ("Error returning browse list: %s\n",
4585 cli_errstr(cli)));
4586 goto done;
4589 for (i = 0; i < share_list.num_shares; i++) {
4590 char *netname = share_list.shares[i];
4592 if (netname[strlen(netname)-1] == '$')
4593 continue;
4595 d_printf("%s\n", netname);
4597 show_userlist(pipe_hnd, mem_ctx, netname,
4598 num_tokens, tokens);
4600 done:
4601 for (i=0; i<num_tokens; i++) {
4602 free_user_token(&tokens[i].token);
4604 SAFE_FREE(tokens);
4605 SAFE_FREE(share_list.shares);
4607 return NT_STATUS_OK;
4610 static int rpc_share_allowedusers(struct net_context *c, int argc,
4611 const char **argv)
4613 int result;
4615 if (c->display_usage) {
4616 d_printf( "%s\n"
4617 "net rpc share allowedusers\n"
4618 " %s\n",
4619 _("Usage:"),
4620 _("List allowed users"));
4621 return 0;
4624 result = run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
4625 rpc_aliaslist_internals,
4626 argc, argv);
4627 if (result != 0)
4628 return result;
4630 result = run_rpc_command(c, NULL, &ndr_table_lsarpc.syntax_id, 0,
4631 rpc_aliaslist_dump,
4632 argc, argv);
4633 if (result != 0)
4634 return result;
4636 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4637 rpc_share_allowedusers_internals,
4638 argc, argv);
4641 int net_usersidlist(struct net_context *c, int argc, const char **argv)
4643 int num_tokens = 0;
4644 struct user_token *tokens = NULL;
4645 int i;
4647 if (argc != 0) {
4648 net_usersidlist_usage(c, argc, argv);
4649 return 0;
4652 if (!get_user_tokens(c, &num_tokens, &tokens)) {
4653 DEBUG(0, ("Could not get the user/sid list\n"));
4654 return 0;
4657 for (i=0; i<num_tokens; i++) {
4658 dump_user_token(&tokens[i]);
4659 free_user_token(&tokens[i].token);
4662 SAFE_FREE(tokens);
4663 return 1;
4666 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
4668 d_printf(_("net usersidlist\n"
4669 "\tprints out a list of all users the running winbind knows\n"
4670 "\tabout, together with all their SIDs. This is used as\n"
4671 "\tinput to the 'net rpc share allowedusers' command.\n\n"));
4673 net_common_flags_usage(c, argc, argv);
4674 return -1;
4678 * 'net rpc share' entrypoint.
4679 * @param argc Standard main() style argc.
4680 * @param argv Standard main() style argv. Initial components are already
4681 * stripped.
4684 int net_rpc_share(struct net_context *c, int argc, const char **argv)
4686 NET_API_STATUS status;
4688 struct functable func[] = {
4690 "add",
4691 rpc_share_add,
4692 NET_TRANSPORT_RPC,
4693 N_("Add share"),
4694 N_("net rpc share add\n"
4695 " Add share")
4698 "delete",
4699 rpc_share_delete,
4700 NET_TRANSPORT_RPC,
4701 N_("Remove share"),
4702 N_("net rpc share delete\n"
4703 " Remove share")
4706 "allowedusers",
4707 rpc_share_allowedusers,
4708 NET_TRANSPORT_RPC,
4709 N_("Modify allowed users"),
4710 N_("net rpc share allowedusers\n"
4711 " Modify allowed users")
4714 "migrate",
4715 rpc_share_migrate,
4716 NET_TRANSPORT_RPC,
4717 N_("Migrate share to local server"),
4718 N_("net rpc share migrate\n"
4719 " Migrate share to local server")
4722 "list",
4723 rpc_share_list,
4724 NET_TRANSPORT_RPC,
4725 N_("List shares"),
4726 N_("net rpc share list\n"
4727 " List shares")
4729 {NULL, NULL, 0, NULL, NULL}
4732 status = libnetapi_init(&c->netapi_ctx);
4733 if (status != 0) {
4734 return -1;
4736 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
4737 libnetapi_set_password(c->netapi_ctx, c->opt_password);
4738 if (c->opt_kerberos) {
4739 libnetapi_set_use_kerberos(c->netapi_ctx);
4742 if (argc == 0) {
4743 if (c->display_usage) {
4744 d_printf("%s\n%s",
4745 _("Usage:"),
4746 _("net rpc share\n"
4747 " List shares\n"
4748 " Alias for net rpc share list\n"));
4749 net_display_usage_from_functable(func);
4750 return 0;
4753 return rpc_share_list(c, argc, argv);
4756 return net_run_function(c, argc, argv, "net rpc share", func);
4759 static NTSTATUS rpc_sh_share_list(struct net_context *c,
4760 TALLOC_CTX *mem_ctx,
4761 struct rpc_sh_ctx *ctx,
4762 struct rpc_pipe_client *pipe_hnd,
4763 int argc, const char **argv)
4766 return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
4769 static NTSTATUS rpc_sh_share_add(struct net_context *c,
4770 TALLOC_CTX *mem_ctx,
4771 struct rpc_sh_ctx *ctx,
4772 struct rpc_pipe_client *pipe_hnd,
4773 int argc, const char **argv)
4775 NET_API_STATUS status;
4776 uint32_t parm_err = 0;
4777 struct SHARE_INFO_2 i2;
4779 if ((argc < 2) || (argc > 3)) {
4780 d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
4781 ctx->whoami);
4782 return NT_STATUS_INVALID_PARAMETER;
4785 i2.shi2_netname = argv[0];
4786 i2.shi2_type = STYPE_DISKTREE;
4787 i2.shi2_remark = (argc == 3) ? argv[2] : "";
4788 i2.shi2_permissions = 0;
4789 i2.shi2_max_uses = 0;
4790 i2.shi2_current_uses = 0;
4791 i2.shi2_path = argv[1];
4792 i2.shi2_passwd = NULL;
4794 status = NetShareAdd(pipe_hnd->desthost,
4796 (uint8_t *)&i2,
4797 &parm_err);
4799 return werror_to_ntstatus(W_ERROR(status));
4802 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
4803 TALLOC_CTX *mem_ctx,
4804 struct rpc_sh_ctx *ctx,
4805 struct rpc_pipe_client *pipe_hnd,
4806 int argc, const char **argv)
4808 if (argc != 1) {
4809 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
4810 return NT_STATUS_INVALID_PARAMETER;
4813 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
4816 static NTSTATUS rpc_sh_share_info(struct net_context *c,
4817 TALLOC_CTX *mem_ctx,
4818 struct rpc_sh_ctx *ctx,
4819 struct rpc_pipe_client *pipe_hnd,
4820 int argc, const char **argv)
4822 union srvsvc_NetShareInfo info;
4823 WERROR result;
4824 NTSTATUS status;
4826 if (argc != 1) {
4827 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
4828 return NT_STATUS_INVALID_PARAMETER;
4831 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4832 pipe_hnd->desthost,
4833 argv[0],
4835 &info,
4836 &result);
4837 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4838 goto done;
4841 d_printf(_("Name: %s\n"), info.info2->name);
4842 d_printf(_("Comment: %s\n"), info.info2->comment);
4843 d_printf(_("Path: %s\n"), info.info2->path);
4844 d_printf(_("Password: %s\n"), info.info2->password);
4846 done:
4847 return werror_to_ntstatus(result);
4850 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
4851 struct rpc_sh_ctx *ctx)
4853 static struct rpc_sh_cmd cmds[] = {
4855 { "list", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_list,
4856 N_("List available shares") },
4858 { "add", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_add,
4859 N_("Add a share") },
4861 { "delete", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_delete,
4862 N_("Delete a share") },
4864 { "info", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_info,
4865 N_("Get information about a share") },
4867 { NULL, NULL, 0, NULL, NULL }
4870 return cmds;
4873 /****************************************************************************/
4875 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
4877 return net_file_usage(c, argc, argv);
4881 * Close a file on a remote RPC server.
4883 * @param argc Standard main() style argc.
4884 * @param argv Standard main() style argv. Initial components are already
4885 * stripped.
4887 * @return A shell status integer (0 for success).
4889 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
4891 if (argc < 1 || c->display_usage) {
4892 return rpc_file_usage(c, argc, argv);
4895 return NetFileClose(c->opt_host, atoi(argv[0]));
4899 * Formatted print of open file info
4901 * @param r struct FILE_INFO_3 contents
4904 static void display_file_info_3(struct FILE_INFO_3 *r)
4906 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
4907 r->fi3_id, r->fi3_username, r->fi3_permissions,
4908 r->fi3_num_locks, r->fi3_pathname);
4912 * List files for a user on a remote RPC server.
4914 * @param argc Standard main() style argc.
4915 * @param argv Standard main() style argv. Initial components are already
4916 * stripped.
4918 * @return A shell status integer (0 for success)..
4921 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
4923 NET_API_STATUS status;
4924 uint32 preferred_len = 0xffffffff, i;
4925 const char *username=NULL;
4926 uint32_t total_entries = 0;
4927 uint32_t entries_read = 0;
4928 uint32_t resume_handle = 0;
4929 struct FILE_INFO_3 *i3 = NULL;
4931 if (c->display_usage) {
4932 return rpc_file_usage(c, argc, argv);
4935 /* if argc > 0, must be user command */
4936 if (argc > 0) {
4937 username = smb_xstrdup(argv[0]);
4940 status = NetFileEnum(c->opt_host,
4941 NULL,
4942 username,
4944 (uint8_t **)(void *)&i3,
4945 preferred_len,
4946 &entries_read,
4947 &total_entries,
4948 &resume_handle);
4950 if (status != 0) {
4951 goto done;
4954 /* Display results */
4956 d_printf(_(
4957 "\nEnumerating open files on remote server:\n\n"
4958 "\nFileId Opened by Perms Locks Path"
4959 "\n------ --------- ----- ----- ---- \n"));
4960 for (i = 0; i < entries_read; i++) {
4961 display_file_info_3(&i3[i]);
4963 done:
4964 return status;
4968 * 'net rpc file' entrypoint.
4969 * @param argc Standard main() style argc.
4970 * @param argv Standard main() style argv. Initial components are already
4971 * stripped.
4974 int net_rpc_file(struct net_context *c, int argc, const char **argv)
4976 NET_API_STATUS status;
4978 struct functable func[] = {
4980 "close",
4981 rpc_file_close,
4982 NET_TRANSPORT_RPC,
4983 N_("Close opened file"),
4984 N_("net rpc file close\n"
4985 " Close opened file")
4988 "user",
4989 rpc_file_user,
4990 NET_TRANSPORT_RPC,
4991 N_("List files opened by user"),
4992 N_("net rpc file user\n"
4993 " List files opened by user")
4995 #if 0
4997 "info",
4998 rpc_file_info,
4999 NET_TRANSPORT_RPC,
5000 N_("Display information about opened file"),
5001 N_("net rpc file info\n"
5002 " Display information about opened file")
5004 #endif
5005 {NULL, NULL, 0, NULL, NULL}
5008 status = libnetapi_init(&c->netapi_ctx);
5009 if (status != 0) {
5010 return -1;
5012 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5013 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5014 if (c->opt_kerberos) {
5015 libnetapi_set_use_kerberos(c->netapi_ctx);
5018 if (argc == 0) {
5019 if (c->display_usage) {
5020 d_printf(_("Usage:\n"));
5021 d_printf(_("net rpc file\n"
5022 " List opened files\n"));
5023 net_display_usage_from_functable(func);
5024 return 0;
5027 return rpc_file_user(c, argc, argv);
5030 return net_run_function(c, argc, argv, "net rpc file", func);
5034 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5036 * All parameters are provided by the run_rpc_command function, except for
5037 * argc, argv which are passed through.
5039 * @param c A net_context structure.
5040 * @param domain_sid The domain sid acquired from the remote server.
5041 * @param cli A cli_state connected to the server.
5042 * @param mem_ctx Talloc context, destroyed on completion of the function.
5043 * @param argc Standard main() style argc.
5044 * @param argv Standard main() style argv. Initial components are already
5045 * stripped.
5047 * @return Normal NTSTATUS return.
5050 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5051 const DOM_SID *domain_sid,
5052 const char *domain_name,
5053 struct cli_state *cli,
5054 struct rpc_pipe_client *pipe_hnd,
5055 TALLOC_CTX *mem_ctx,
5056 int argc,
5057 const char **argv)
5059 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5061 result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
5063 if (NT_STATUS_IS_OK(result)) {
5064 d_printf(_("\nShutdown successfully aborted\n"));
5065 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5066 } else
5067 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5069 return result;
5073 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5075 * All parameters are provided by the run_rpc_command function, except for
5076 * argc, argv which are passed through.
5078 * @param c A net_context structure.
5079 * @param domain_sid The domain sid acquired from the remote server.
5080 * @param cli A cli_state connected to the server.
5081 * @param mem_ctx Talloc context, destroyed on completion of the function.
5082 * @param argc Standard main() style argc.
5083 * @param argv Standard main() style argv. Initial components are already
5084 * stripped.
5086 * @return Normal NTSTATUS return.
5089 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5090 const DOM_SID *domain_sid,
5091 const char *domain_name,
5092 struct cli_state *cli,
5093 struct rpc_pipe_client *pipe_hnd,
5094 TALLOC_CTX *mem_ctx,
5095 int argc,
5096 const char **argv)
5098 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5100 result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
5102 if (NT_STATUS_IS_OK(result)) {
5103 d_printf(_("\nShutdown successfully aborted\n"));
5104 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5105 } else
5106 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5108 return result;
5112 * ABORT the shutdown of a remote RPC server.
5114 * @param argc Standard main() style argc.
5115 * @param argv Standard main() style argv. Initial components are already
5116 * stripped.
5118 * @return A shell status integer (0 for success).
5121 static int rpc_shutdown_abort(struct net_context *c, int argc,
5122 const char **argv)
5124 int rc = -1;
5126 if (c->display_usage) {
5127 d_printf( "%s\n"
5128 "net rpc abortshutdown\n"
5129 " %s\n",
5130 _("Usage:"),
5131 _("Abort a scheduled shutdown"));
5132 return 0;
5135 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5136 rpc_shutdown_abort_internals, argc, argv);
5138 if (rc == 0)
5139 return rc;
5141 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5143 return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5144 rpc_reg_shutdown_abort_internals,
5145 argc, argv);
5149 * Shut down a remote RPC Server via initshutdown pipe.
5151 * All parameters are provided by the run_rpc_command function, except for
5152 * argc, argv which are passed through.
5154 * @param c A net_context structure.
5155 * @param domain_sid The domain sid acquired from the remote server.
5156 * @param cli A cli_state connected to the server.
5157 * @param mem_ctx Talloc context, destroyed on completion of the function.
5158 * @param argc Standard main() style argc.
5159 * @param argv Standard main() style argv. Initial components are already
5160 * stripped.
5162 * @return Normal NTSTATUS return.
5165 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5166 const DOM_SID *domain_sid,
5167 const char *domain_name,
5168 struct cli_state *cli,
5169 struct rpc_pipe_client *pipe_hnd,
5170 TALLOC_CTX *mem_ctx,
5171 int argc,
5172 const char **argv)
5174 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5175 const char *msg = N_("This machine will be shutdown shortly");
5176 uint32 timeout = 20;
5177 struct lsa_StringLarge msg_string;
5179 if (c->opt_comment) {
5180 msg = c->opt_comment;
5182 if (c->opt_timeout) {
5183 timeout = c->opt_timeout;
5186 msg_string.string = msg;
5188 /* create an entry */
5189 result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5190 &msg_string, timeout, c->opt_force, c->opt_reboot,
5191 NULL);
5193 if (NT_STATUS_IS_OK(result)) {
5194 d_printf(_("\nShutdown of remote machine succeeded\n"));
5195 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5196 } else {
5197 DEBUG(1,("Shutdown of remote machine failed!\n"));
5199 return result;
5203 * Shut down a remote RPC Server via winreg pipe.
5205 * All parameters are provided by the run_rpc_command function, except for
5206 * argc, argv which are passed through.
5208 * @param c A net_context structure.
5209 * @param domain_sid The domain sid acquired from the remote server.
5210 * @param cli A cli_state connected to the server.
5211 * @param mem_ctx Talloc context, destroyed on completion of the function.
5212 * @param argc Standard main() style argc.
5213 * @param argv Standard main() style argv. Initial components are already
5214 * stripped.
5216 * @return Normal NTSTATUS return.
5219 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5220 const DOM_SID *domain_sid,
5221 const char *domain_name,
5222 struct cli_state *cli,
5223 struct rpc_pipe_client *pipe_hnd,
5224 TALLOC_CTX *mem_ctx,
5225 int argc,
5226 const char **argv)
5228 const char *msg = N_("This machine will be shutdown shortly");
5229 uint32 timeout = 20;
5230 struct lsa_StringLarge msg_string;
5231 NTSTATUS result;
5232 WERROR werr;
5234 if (c->opt_comment) {
5235 msg = c->opt_comment;
5237 msg_string.string = msg;
5239 if (c->opt_timeout) {
5240 timeout = c->opt_timeout;
5243 /* create an entry */
5244 result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5245 &msg_string, timeout, c->opt_force, c->opt_reboot,
5246 &werr);
5248 if (NT_STATUS_IS_OK(result)) {
5249 d_printf(_("\nShutdown of remote machine succeeded\n"));
5250 } else {
5251 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5252 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5253 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5254 else
5255 d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5258 return result;
5262 * Shut down a remote RPC server.
5264 * @param argc Standard main() style argc.
5265 * @param argv Standard main() style argv. Initial components are already
5266 * stripped.
5268 * @return A shell status integer (0 for success).
5271 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5273 int rc = -1;
5275 if (c->display_usage) {
5276 d_printf( "%s\n"
5277 "net rpc shutdown\n"
5278 " %s\n",
5279 _("Usage:"),
5280 _("Shut down a remote RPC server"));
5281 return 0;
5284 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5285 rpc_init_shutdown_internals, argc, argv);
5287 if (rc) {
5288 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5289 rc = run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5290 rpc_reg_shutdown_internals, argc, argv);
5293 return rc;
5296 /***************************************************************************
5297 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5298 ***************************************************************************/
5301 * Add interdomain trust account to the RPC server.
5302 * All parameters (except for argc and argv) are passed by run_rpc_command
5303 * function.
5305 * @param c A net_context structure.
5306 * @param domain_sid The domain sid acquired from the server.
5307 * @param cli A cli_state connected to the server.
5308 * @param mem_ctx Talloc context, destroyed on completion of the function.
5309 * @param argc Standard main() style argc.
5310 * @param argv Standard main() style argv. Initial components are already
5311 * stripped.
5313 * @return normal NTSTATUS return code.
5316 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
5317 const DOM_SID *domain_sid,
5318 const char *domain_name,
5319 struct cli_state *cli,
5320 struct rpc_pipe_client *pipe_hnd,
5321 TALLOC_CTX *mem_ctx,
5322 int argc,
5323 const char **argv)
5325 struct policy_handle connect_pol, domain_pol, user_pol;
5326 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5327 char *acct_name;
5328 struct lsa_String lsa_acct_name;
5329 uint32 acb_info;
5330 uint32 acct_flags=0;
5331 uint32 user_rid;
5332 uint32_t access_granted = 0;
5333 union samr_UserInfo info;
5334 unsigned int orig_timeout;
5336 if (argc != 2) {
5337 d_printf("%s\n%s",
5338 _("Usage:"),
5339 _(" net rpc trustdom add <domain_name> "
5340 "<trust password>\n"));
5341 return NT_STATUS_INVALID_PARAMETER;
5345 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5348 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5349 return NT_STATUS_NO_MEMORY;
5352 strupper_m(acct_name);
5354 init_lsa_String(&lsa_acct_name, acct_name);
5356 /* Get samr policy handle */
5357 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5358 pipe_hnd->desthost,
5359 MAXIMUM_ALLOWED_ACCESS,
5360 &connect_pol);
5361 if (!NT_STATUS_IS_OK(result)) {
5362 goto done;
5365 /* Get domain policy handle */
5366 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5367 &connect_pol,
5368 MAXIMUM_ALLOWED_ACCESS,
5369 CONST_DISCARD(struct dom_sid2 *, domain_sid),
5370 &domain_pol);
5371 if (!NT_STATUS_IS_OK(result)) {
5372 goto done;
5375 /* This call can take a long time - allow the server to time out.
5376 * 35 seconds should do it. */
5378 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5380 /* Create trusting domain's account */
5381 acb_info = ACB_NORMAL;
5382 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5383 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5384 SAMR_USER_ACCESS_SET_PASSWORD |
5385 SAMR_USER_ACCESS_GET_ATTRIBUTES |
5386 SAMR_USER_ACCESS_SET_ATTRIBUTES;
5388 result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5389 &domain_pol,
5390 &lsa_acct_name,
5391 acb_info,
5392 acct_flags,
5393 &user_pol,
5394 &access_granted,
5395 &user_rid);
5397 /* And restore our original timeout. */
5398 rpccli_set_timeout(pipe_hnd, orig_timeout);
5400 if (!NT_STATUS_IS_OK(result)) {
5401 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
5402 acct_name, nt_errstr(result));
5403 goto done;
5407 struct samr_CryptPassword crypt_pwd;
5409 ZERO_STRUCT(info.info23);
5411 init_samr_CryptPassword(argv[1],
5412 &cli->user_session_key,
5413 &crypt_pwd);
5415 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
5416 SAMR_FIELD_NT_PASSWORD_PRESENT;
5417 info.info23.info.acct_flags = ACB_DOMTRUST;
5418 info.info23.password = crypt_pwd;
5420 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5421 &user_pol,
5423 &info);
5425 if (!NT_STATUS_IS_OK(result)) {
5426 DEBUG(0,("Could not set trust account password: %s\n",
5427 nt_errstr(result)));
5428 goto done;
5432 done:
5433 SAFE_FREE(acct_name);
5434 return result;
5438 * Create interdomain trust account for a remote domain.
5440 * @param argc Standard argc.
5441 * @param argv Standard argv without initial components.
5443 * @return Integer status (0 means success).
5446 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5448 if (argc > 0 && !c->display_usage) {
5449 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5450 rpc_trustdom_add_internals, argc, argv);
5451 } else {
5452 d_printf("%s\n%s",
5453 _("Usage:"),
5454 _("net rpc trustdom add <domain_name> <trust "
5455 "password>\n"));
5456 return -1;
5462 * Remove interdomain trust account from the RPC server.
5463 * All parameters (except for argc and argv) are passed by run_rpc_command
5464 * function.
5466 * @param c A net_context structure.
5467 * @param domain_sid The domain sid acquired from the server.
5468 * @param cli A cli_state connected to the server.
5469 * @param mem_ctx Talloc context, destroyed on completion of the function.
5470 * @param argc Standard main() style argc.
5471 * @param argv Standard main() style argv. Initial components are already
5472 * stripped.
5474 * @return normal NTSTATUS return code.
5477 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
5478 const DOM_SID *domain_sid,
5479 const char *domain_name,
5480 struct cli_state *cli,
5481 struct rpc_pipe_client *pipe_hnd,
5482 TALLOC_CTX *mem_ctx,
5483 int argc,
5484 const char **argv)
5486 struct policy_handle connect_pol, domain_pol, user_pol;
5487 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5488 char *acct_name;
5489 DOM_SID trust_acct_sid;
5490 struct samr_Ids user_rids, name_types;
5491 struct lsa_String lsa_acct_name;
5493 if (argc != 1) {
5494 d_printf("%s\n%s",
5495 _("Usage:"),
5496 _(" net rpc trustdom del <domain_name>\n"));
5497 return NT_STATUS_INVALID_PARAMETER;
5501 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5503 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5505 if (acct_name == NULL)
5506 return NT_STATUS_NO_MEMORY;
5508 strupper_m(acct_name);
5510 /* Get samr policy handle */
5511 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5512 pipe_hnd->desthost,
5513 MAXIMUM_ALLOWED_ACCESS,
5514 &connect_pol);
5515 if (!NT_STATUS_IS_OK(result)) {
5516 goto done;
5519 /* Get domain policy handle */
5520 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5521 &connect_pol,
5522 MAXIMUM_ALLOWED_ACCESS,
5523 CONST_DISCARD(struct dom_sid2 *, domain_sid),
5524 &domain_pol);
5525 if (!NT_STATUS_IS_OK(result)) {
5526 goto done;
5529 init_lsa_String(&lsa_acct_name, acct_name);
5531 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5532 &domain_pol,
5534 &lsa_acct_name,
5535 &user_rids,
5536 &name_types);
5538 if (!NT_STATUS_IS_OK(result)) {
5539 d_printf(_("net rpc trustdom del: LookupNames on user %s "
5540 "failed %s\n"),
5541 acct_name, nt_errstr(result) );
5542 goto done;
5545 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5546 &domain_pol,
5547 MAXIMUM_ALLOWED_ACCESS,
5548 user_rids.ids[0],
5549 &user_pol);
5551 if (!NT_STATUS_IS_OK(result)) {
5552 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
5553 "%s\n"),
5554 acct_name, nt_errstr(result) );
5555 goto done;
5558 /* append the rid to the domain sid */
5559 if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
5560 goto done;
5563 /* remove the sid */
5565 result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5566 &user_pol,
5567 &trust_acct_sid);
5568 if (!NT_STATUS_IS_OK(result)) {
5569 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
5570 " on user %s failed %s\n"),
5571 acct_name, nt_errstr(result) );
5572 goto done;
5575 /* Delete user */
5577 result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5578 &user_pol);
5580 if (!NT_STATUS_IS_OK(result)) {
5581 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
5582 "%s\n"),
5583 acct_name, nt_errstr(result) );
5584 goto done;
5587 if (!NT_STATUS_IS_OK(result)) {
5588 d_printf(_("Could not set trust account password: %s\n"),
5589 nt_errstr(result));
5590 goto done;
5593 done:
5594 return result;
5598 * Delete interdomain trust account for a remote domain.
5600 * @param argc Standard argc.
5601 * @param argv Standard argv without initial components.
5603 * @return Integer status (0 means success).
5606 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
5608 if (argc > 0 && !c->display_usage) {
5609 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5610 rpc_trustdom_del_internals, argc, argv);
5611 } else {
5612 d_printf("%s\n%s",
5613 _("Usage:"),
5614 _("net rpc trustdom del <domain>\n"));
5615 return -1;
5619 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
5620 struct cli_state *cli,
5621 TALLOC_CTX *mem_ctx,
5622 const char *domain_name)
5624 char *dc_name = NULL;
5625 const char *buffer = NULL;
5626 struct rpc_pipe_client *netr;
5627 NTSTATUS status;
5629 /* Use NetServerEnum2 */
5631 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
5632 SAFE_FREE(dc_name);
5633 return NT_STATUS_OK;
5636 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
5637 for domain %s\n", domain_name));
5639 /* Try netr_GetDcName */
5641 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
5642 &netr);
5643 if (!NT_STATUS_IS_OK(status)) {
5644 return status;
5647 status = rpccli_netr_GetDcName(netr, mem_ctx,
5648 cli->desthost,
5649 domain_name,
5650 &buffer,
5651 NULL);
5652 TALLOC_FREE(netr);
5654 if (NT_STATUS_IS_OK(status)) {
5655 return status;
5658 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
5659 for domain %s\n", domain_name));
5661 return status;
5665 * Establish trust relationship to a trusting domain.
5666 * Interdomain account must already be created on remote PDC.
5668 * @param c A net_context structure.
5669 * @param argc Standard argc.
5670 * @param argv Standard argv without initial components.
5672 * @return Integer status (0 means success).
5675 static int rpc_trustdom_establish(struct net_context *c, int argc,
5676 const char **argv)
5678 struct cli_state *cli = NULL;
5679 struct sockaddr_storage server_ss;
5680 struct rpc_pipe_client *pipe_hnd = NULL;
5681 struct policy_handle connect_hnd;
5682 TALLOC_CTX *mem_ctx;
5683 NTSTATUS nt_status;
5684 DOM_SID *domain_sid;
5686 char* domain_name;
5687 char* acct_name;
5688 fstring pdc_name;
5689 union lsa_PolicyInformation *info = NULL;
5692 * Connect to \\server\ipc$ as 'our domain' account with password
5695 if (argc != 1 || c->display_usage) {
5696 d_printf("%s\n%s",
5697 _("Usage:"),
5698 _("net rpc trustdom establish <domain_name>\n"));
5699 return -1;
5702 domain_name = smb_xstrdup(argv[0]);
5703 strupper_m(domain_name);
5705 /* account name used at first is our domain's name with '$' */
5706 if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
5707 return -1;
5709 strupper_m(acct_name);
5712 * opt_workgroup will be used by connection functions further,
5713 * hence it should be set to remote domain name instead of ours
5715 if (c->opt_workgroup) {
5716 c->opt_workgroup = smb_xstrdup(domain_name);
5719 c->opt_user_name = acct_name;
5721 /* find the domain controller */
5722 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5723 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5724 return -1;
5727 /* connect to ipc$ as username/password */
5728 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
5729 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5731 /* Is it trusting domain account for sure ? */
5732 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5733 nt_errstr(nt_status)));
5734 return -1;
5737 /* store who we connected to */
5739 saf_store( domain_name, pdc_name );
5742 * Connect to \\server\ipc$ again (this time anonymously)
5745 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
5746 (char*)pdc_name);
5748 if (NT_STATUS_IS_ERR(nt_status)) {
5749 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5750 domain_name, nt_errstr(nt_status)));
5751 return -1;
5754 if (!(mem_ctx = talloc_init("establishing trust relationship to "
5755 "domain %s", domain_name))) {
5756 DEBUG(0, ("talloc_init() failed\n"));
5757 cli_shutdown(cli);
5758 return -1;
5761 /* Make sure we're talking to a proper server */
5763 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
5764 if (!NT_STATUS_IS_OK(nt_status)) {
5765 cli_shutdown(cli);
5766 talloc_destroy(mem_ctx);
5767 return -1;
5771 * Call LsaOpenPolicy and LsaQueryInfo
5774 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5775 &pipe_hnd);
5776 if (!NT_STATUS_IS_OK(nt_status)) {
5777 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5778 cli_shutdown(cli);
5779 talloc_destroy(mem_ctx);
5780 return -1;
5783 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
5784 &connect_hnd);
5785 if (NT_STATUS_IS_ERR(nt_status)) {
5786 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5787 nt_errstr(nt_status)));
5788 cli_shutdown(cli);
5789 talloc_destroy(mem_ctx);
5790 return -1;
5793 /* Querying info level 5 */
5795 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5796 &connect_hnd,
5797 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5798 &info);
5799 if (NT_STATUS_IS_ERR(nt_status)) {
5800 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5801 nt_errstr(nt_status)));
5802 cli_shutdown(cli);
5803 talloc_destroy(mem_ctx);
5804 return -1;
5807 domain_sid = info->account_domain.sid;
5809 /* There should be actually query info level 3 (following nt serv behaviour),
5810 but I still don't know if it's _really_ necessary */
5813 * Store the password in secrets db
5816 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
5817 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5818 cli_shutdown(cli);
5819 talloc_destroy(mem_ctx);
5820 return -1;
5824 * Close the pipes and clean up
5827 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5828 if (NT_STATUS_IS_ERR(nt_status)) {
5829 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5830 nt_errstr(nt_status)));
5831 cli_shutdown(cli);
5832 talloc_destroy(mem_ctx);
5833 return -1;
5836 cli_shutdown(cli);
5838 talloc_destroy(mem_ctx);
5840 d_printf(_("Trust to domain %s established\n"), domain_name);
5841 return 0;
5845 * Revoke trust relationship to the remote domain.
5847 * @param c A net_context structure.
5848 * @param argc Standard argc.
5849 * @param argv Standard argv without initial components.
5851 * @return Integer status (0 means success).
5854 static int rpc_trustdom_revoke(struct net_context *c, int argc,
5855 const char **argv)
5857 char* domain_name;
5858 int rc = -1;
5860 if (argc < 1 || c->display_usage) {
5861 d_printf("%s\n%s",
5862 _("Usage:"),
5863 _("net rpc trustdom revoke <domain_name>\n"
5864 " Revoke trust relationship\n"
5865 " domain_name\tName of domain to revoke trust\n"));
5866 return -1;
5869 /* generate upper cased domain name */
5870 domain_name = smb_xstrdup(argv[0]);
5871 strupper_m(domain_name);
5873 /* delete password of the trust */
5874 if (!pdb_del_trusteddom_pw(domain_name)) {
5875 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
5876 domain_name));
5877 goto done;
5880 rc = 0;
5881 done:
5882 SAFE_FREE(domain_name);
5883 return rc;
5886 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
5887 const DOM_SID *domain_sid,
5888 const char *domain_name,
5889 struct cli_state *cli,
5890 struct rpc_pipe_client *pipe_hnd,
5891 TALLOC_CTX *mem_ctx,
5892 int argc,
5893 const char **argv)
5895 fstring str_sid;
5896 if (!sid_to_fstring(str_sid, domain_sid)) {
5897 return NT_STATUS_UNSUCCESSFUL;
5899 d_printf("%s\n", str_sid);
5900 return NT_STATUS_OK;
5903 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
5905 fstring ascii_sid;
5907 /* convert sid into ascii string */
5908 sid_to_fstring(ascii_sid, dom_sid);
5910 d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
5913 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
5914 TALLOC_CTX *mem_ctx,
5915 struct policy_handle *pol,
5916 DOM_SID dom_sid,
5917 const char *trusted_dom_name)
5919 NTSTATUS nt_status;
5920 union lsa_TrustedDomainInfo *info = NULL;
5921 char *cleartextpwd = NULL;
5922 uint8_t session_key[16];
5923 DATA_BLOB session_key_blob;
5924 DATA_BLOB data = data_blob_null;
5926 nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
5927 pol,
5928 &dom_sid,
5929 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
5930 &info);
5931 if (NT_STATUS_IS_ERR(nt_status)) {
5932 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5933 nt_errstr(nt_status)));
5934 goto done;
5937 data = data_blob(info->password.password->data,
5938 info->password.password->length);
5940 if (!rpccli_get_pwd_hash(pipe_hnd, session_key)) {
5941 DEBUG(0, ("Could not retrieve password hash\n"));
5942 goto done;
5945 session_key_blob = data_blob_const(session_key, sizeof(session_key));
5946 cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key_blob);
5948 if (cleartextpwd == NULL) {
5949 DEBUG(0,("retrieved NULL password\n"));
5950 nt_status = NT_STATUS_UNSUCCESSFUL;
5951 goto done;
5954 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
5955 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5956 nt_status = NT_STATUS_UNSUCCESSFUL;
5957 goto done;
5960 #ifdef DEBUG_PASSWORD
5961 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
5962 "password: [%s]\n", trusted_dom_name,
5963 sid_string_dbg(&dom_sid), cleartextpwd));
5964 #endif
5966 done:
5967 SAFE_FREE(cleartextpwd);
5968 data_blob_free(&data);
5970 return nt_status;
5973 static int rpc_trustdom_vampire(struct net_context *c, int argc,
5974 const char **argv)
5976 /* common variables */
5977 TALLOC_CTX* mem_ctx;
5978 struct cli_state *cli = NULL;
5979 struct rpc_pipe_client *pipe_hnd = NULL;
5980 NTSTATUS nt_status;
5981 const char *domain_name = NULL;
5982 DOM_SID *queried_dom_sid;
5983 struct policy_handle connect_hnd;
5984 union lsa_PolicyInformation *info = NULL;
5986 /* trusted domains listing variables */
5987 unsigned int enum_ctx = 0;
5988 int i;
5989 struct lsa_DomainList dom_list;
5990 fstring pdc_name;
5992 if (c->display_usage) {
5993 d_printf( "%s\n"
5994 "net rpc trustdom vampire\n"
5995 " %s\n",
5996 _("Usage:"),
5997 _("Vampire trust relationship from remote server"));
5998 return 0;
6002 * Listing trusted domains (stored in secrets.tdb, if local)
6005 mem_ctx = talloc_init("trust relationships vampire");
6008 * set domain and pdc name to local samba server (default)
6009 * or to remote one given in command line
6012 if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6013 domain_name = c->opt_workgroup;
6014 c->opt_target_workgroup = c->opt_workgroup;
6015 } else {
6016 fstrcpy(pdc_name, global_myname());
6017 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6018 c->opt_target_workgroup = domain_name;
6021 /* open \PIPE\lsarpc and open policy handle */
6022 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6023 if (!NT_STATUS_IS_OK(nt_status)) {
6024 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6025 nt_errstr(nt_status)));
6026 talloc_destroy(mem_ctx);
6027 return -1;
6030 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6031 &pipe_hnd);
6032 if (!NT_STATUS_IS_OK(nt_status)) {
6033 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6034 nt_errstr(nt_status) ));
6035 cli_shutdown(cli);
6036 talloc_destroy(mem_ctx);
6037 return -1;
6040 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6041 &connect_hnd);
6042 if (NT_STATUS_IS_ERR(nt_status)) {
6043 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6044 nt_errstr(nt_status)));
6045 cli_shutdown(cli);
6046 talloc_destroy(mem_ctx);
6047 return -1;
6050 /* query info level 5 to obtain sid of a domain being queried */
6051 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6052 &connect_hnd,
6053 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6054 &info);
6056 if (NT_STATUS_IS_ERR(nt_status)) {
6057 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6058 nt_errstr(nt_status)));
6059 cli_shutdown(cli);
6060 talloc_destroy(mem_ctx);
6061 return -1;
6064 queried_dom_sid = info->account_domain.sid;
6067 * Keep calling LsaEnumTrustdom over opened pipe until
6068 * the end of enumeration is reached
6071 d_printf(_("Vampire trusted domains:\n\n"));
6073 do {
6074 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6075 &connect_hnd,
6076 &enum_ctx,
6077 &dom_list,
6078 (uint32_t)-1);
6079 if (NT_STATUS_IS_ERR(nt_status)) {
6080 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6081 nt_errstr(nt_status)));
6082 cli_shutdown(cli);
6083 talloc_destroy(mem_ctx);
6084 return -1;
6087 for (i = 0; i < dom_list.count; i++) {
6089 print_trusted_domain(dom_list.domains[i].sid,
6090 dom_list.domains[i].name.string);
6092 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
6093 *dom_list.domains[i].sid,
6094 dom_list.domains[i].name.string);
6095 if (!NT_STATUS_IS_OK(nt_status)) {
6096 cli_shutdown(cli);
6097 talloc_destroy(mem_ctx);
6098 return -1;
6103 * in case of no trusted domains say something rather
6104 * than just display blank line
6106 if (!dom_list.count) d_printf(_("none\n"));
6108 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6110 /* close this connection before doing next one */
6111 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6112 if (NT_STATUS_IS_ERR(nt_status)) {
6113 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6114 nt_errstr(nt_status)));
6115 cli_shutdown(cli);
6116 talloc_destroy(mem_ctx);
6117 return -1;
6120 /* close lsarpc pipe and connection to IPC$ */
6121 cli_shutdown(cli);
6123 talloc_destroy(mem_ctx);
6124 return 0;
6127 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6129 /* common variables */
6130 TALLOC_CTX* mem_ctx;
6131 struct cli_state *cli = NULL, *remote_cli = NULL;
6132 struct rpc_pipe_client *pipe_hnd = NULL;
6133 NTSTATUS nt_status;
6134 const char *domain_name = NULL;
6135 DOM_SID *queried_dom_sid;
6136 int ascii_dom_name_len;
6137 struct policy_handle connect_hnd;
6138 union lsa_PolicyInformation *info = NULL;
6140 /* trusted domains listing variables */
6141 unsigned int num_domains, enum_ctx = 0;
6142 int i;
6143 struct lsa_DomainList dom_list;
6144 fstring pdc_name;
6145 bool found_domain;
6147 /* trusting domains listing variables */
6148 struct policy_handle domain_hnd;
6149 struct samr_SamArray *trusts = NULL;
6151 if (c->display_usage) {
6152 d_printf( "%s\n"
6153 "net rpc trustdom list\n"
6154 " %s\n",
6155 _("Usage:"),
6156 _("List incoming and outgoing trust relationships"));
6157 return 0;
6161 * Listing trusted domains (stored in secrets.tdb, if local)
6164 mem_ctx = talloc_init("trust relationships listing");
6167 * set domain and pdc name to local samba server (default)
6168 * or to remote one given in command line
6171 if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6172 domain_name = c->opt_workgroup;
6173 c->opt_target_workgroup = c->opt_workgroup;
6174 } else {
6175 fstrcpy(pdc_name, global_myname());
6176 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6177 c->opt_target_workgroup = domain_name;
6180 /* open \PIPE\lsarpc and open policy handle */
6181 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6182 if (!NT_STATUS_IS_OK(nt_status)) {
6183 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6184 nt_errstr(nt_status)));
6185 talloc_destroy(mem_ctx);
6186 return -1;
6189 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6190 &pipe_hnd);
6191 if (!NT_STATUS_IS_OK(nt_status)) {
6192 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6193 nt_errstr(nt_status) ));
6194 cli_shutdown(cli);
6195 talloc_destroy(mem_ctx);
6196 return -1;
6199 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6200 &connect_hnd);
6201 if (NT_STATUS_IS_ERR(nt_status)) {
6202 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6203 nt_errstr(nt_status)));
6204 cli_shutdown(cli);
6205 talloc_destroy(mem_ctx);
6206 return -1;
6209 /* query info level 5 to obtain sid of a domain being queried */
6210 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6211 &connect_hnd,
6212 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6213 &info);
6215 if (NT_STATUS_IS_ERR(nt_status)) {
6216 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6217 nt_errstr(nt_status)));
6218 cli_shutdown(cli);
6219 talloc_destroy(mem_ctx);
6220 return -1;
6223 queried_dom_sid = info->account_domain.sid;
6226 * Keep calling LsaEnumTrustdom over opened pipe until
6227 * the end of enumeration is reached
6230 d_printf(_("Trusted domains list:\n\n"));
6232 found_domain = false;
6234 do {
6235 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6236 &connect_hnd,
6237 &enum_ctx,
6238 &dom_list,
6239 (uint32_t)-1);
6240 if (NT_STATUS_IS_ERR(nt_status)) {
6241 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6242 nt_errstr(nt_status)));
6243 cli_shutdown(cli);
6244 talloc_destroy(mem_ctx);
6245 return -1;
6248 for (i = 0; i < dom_list.count; i++) {
6249 print_trusted_domain(dom_list.domains[i].sid,
6250 dom_list.domains[i].name.string);
6251 found_domain = true;
6255 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6258 * in case of no trusted domains say something rather
6259 * than just display blank line
6261 if (!found_domain) {
6262 d_printf(_("none\n"));
6265 /* close this connection before doing next one */
6266 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6267 if (NT_STATUS_IS_ERR(nt_status)) {
6268 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6269 nt_errstr(nt_status)));
6270 cli_shutdown(cli);
6271 talloc_destroy(mem_ctx);
6272 return -1;
6275 TALLOC_FREE(pipe_hnd);
6278 * Listing trusting domains (stored in passdb backend, if local)
6281 d_printf(_("\nTrusting domains list:\n\n"));
6284 * Open \PIPE\samr and get needed policy handles
6286 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6287 &pipe_hnd);
6288 if (!NT_STATUS_IS_OK(nt_status)) {
6289 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6290 cli_shutdown(cli);
6291 talloc_destroy(mem_ctx);
6292 return -1;
6295 /* SamrConnect2 */
6296 nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6297 pipe_hnd->desthost,
6298 SAMR_ACCESS_LOOKUP_DOMAIN,
6299 &connect_hnd);
6300 if (!NT_STATUS_IS_OK(nt_status)) {
6301 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6302 nt_errstr(nt_status)));
6303 cli_shutdown(cli);
6304 talloc_destroy(mem_ctx);
6305 return -1;
6308 /* SamrOpenDomain - we have to open domain policy handle in order to be
6309 able to enumerate accounts*/
6310 nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6311 &connect_hnd,
6312 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6313 queried_dom_sid,
6314 &domain_hnd);
6315 if (!NT_STATUS_IS_OK(nt_status)) {
6316 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6317 nt_errstr(nt_status)));
6318 cli_shutdown(cli);
6319 talloc_destroy(mem_ctx);
6320 return -1;
6324 * perform actual enumeration
6327 found_domain = false;
6329 enum_ctx = 0; /* reset enumeration context from last enumeration */
6330 do {
6332 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6333 &domain_hnd,
6334 &enum_ctx,
6335 ACB_DOMTRUST,
6336 &trusts,
6337 0xffff,
6338 &num_domains);
6339 if (NT_STATUS_IS_ERR(nt_status)) {
6340 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6341 nt_errstr(nt_status)));
6342 cli_shutdown(cli);
6343 talloc_destroy(mem_ctx);
6344 return -1;
6347 for (i = 0; i < num_domains; i++) {
6349 char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6351 found_domain = true;
6354 * get each single domain's sid (do we _really_ need this ?):
6355 * 1) connect to domain's pdc
6356 * 2) query the pdc for domain's sid
6359 /* get rid of '$' tail */
6360 ascii_dom_name_len = strlen(str);
6361 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6362 str[ascii_dom_name_len - 1] = '\0';
6364 /* set opt_* variables to remote domain */
6365 strupper_m(str);
6366 c->opt_workgroup = talloc_strdup(mem_ctx, str);
6367 c->opt_target_workgroup = c->opt_workgroup;
6369 d_printf("%-20s", str);
6371 /* connect to remote domain controller */
6372 nt_status = net_make_ipc_connection(c,
6373 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6374 &remote_cli);
6375 if (NT_STATUS_IS_OK(nt_status)) {
6376 /* query for domain's sid */
6377 if (run_rpc_command(
6378 c, remote_cli,
6379 &ndr_table_lsarpc.syntax_id, 0,
6380 rpc_query_domain_sid, argc,
6381 argv))
6382 d_printf(_("strange - couldn't get domain's sid\n"));
6384 cli_shutdown(remote_cli);
6386 } else {
6387 d_fprintf(stderr, _("domain controller is not "
6388 "responding: %s\n"),
6389 nt_errstr(nt_status));
6390 d_printf(_("couldn't get domain's sid\n"));
6394 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6396 if (!found_domain) {
6397 d_printf("none\n");
6400 /* close opened samr and domain policy handles */
6401 nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6402 if (!NT_STATUS_IS_OK(nt_status)) {
6403 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6406 nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6407 if (!NT_STATUS_IS_OK(nt_status)) {
6408 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6411 /* close samr pipe and connection to IPC$ */
6412 cli_shutdown(cli);
6414 talloc_destroy(mem_ctx);
6415 return 0;
6419 * Entrypoint for 'net rpc trustdom' code.
6421 * @param argc Standard argc.
6422 * @param argv Standard argv without initial components.
6424 * @return Integer status (0 means success).
6427 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
6429 struct functable func[] = {
6431 "add",
6432 rpc_trustdom_add,
6433 NET_TRANSPORT_RPC,
6434 N_("Add trusting domain's account"),
6435 N_("net rpc trustdom add\n"
6436 " Add trusting domain's account")
6439 "del",
6440 rpc_trustdom_del,
6441 NET_TRANSPORT_RPC,
6442 N_("Remove trusting domain's account"),
6443 N_("net rpc trustdom del\n"
6444 " Remove trusting domain's account")
6447 "establish",
6448 rpc_trustdom_establish,
6449 NET_TRANSPORT_RPC,
6450 N_("Establish outgoing trust relationship"),
6451 N_("net rpc trustdom establish\n"
6452 " Establish outgoing trust relationship")
6455 "revoke",
6456 rpc_trustdom_revoke,
6457 NET_TRANSPORT_RPC,
6458 N_("Revoke outgoing trust relationship"),
6459 N_("net rpc trustdom revoke\n"
6460 " Revoke outgoing trust relationship")
6463 "list",
6464 rpc_trustdom_list,
6465 NET_TRANSPORT_RPC,
6466 N_("List in- and outgoing domain trusts"),
6467 N_("net rpc trustdom list\n"
6468 " List in- and outgoing domain trusts")
6471 "vampire",
6472 rpc_trustdom_vampire,
6473 NET_TRANSPORT_RPC,
6474 N_("Vampire trusts from remote server"),
6475 N_("net rpc trustdom vampire\n"
6476 " Vampire trusts from remote server")
6478 {NULL, NULL, 0, NULL, NULL}
6481 return net_run_function(c, argc, argv, "net rpc trustdom", func);
6485 * Check if a server will take rpc commands
6486 * @param flags Type of server to connect to (PDC, DMB, localhost)
6487 * if the host is not explicitly specified
6488 * @return bool (true means rpc supported)
6490 bool net_rpc_check(struct net_context *c, unsigned flags)
6492 struct cli_state *cli;
6493 bool ret = false;
6494 struct sockaddr_storage server_ss;
6495 char *server_name = NULL;
6496 NTSTATUS status;
6498 /* flags (i.e. server type) may depend on command */
6499 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
6500 return false;
6502 if ((cli = cli_initialise()) == NULL) {
6503 return false;
6506 status = cli_connect(cli, server_name, &server_ss);
6507 if (!NT_STATUS_IS_OK(status))
6508 goto done;
6509 if (!attempt_netbios_session_request(&cli, global_myname(),
6510 server_name, &server_ss))
6511 goto done;
6512 status = cli_negprot(cli);
6513 if (!NT_STATUS_IS_OK(status))
6514 goto done;
6515 if (cli->protocol < PROTOCOL_NT1)
6516 goto done;
6518 ret = true;
6519 done:
6520 cli_shutdown(cli);
6521 return ret;
6524 /* dump sam database via samsync rpc calls */
6525 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
6526 if (c->display_usage) {
6527 d_printf( "%s\n"
6528 "net rpc samdump\n"
6529 " %s\n",
6530 _("Usage:"),
6531 _("Dump remote SAM database"));
6532 return 0;
6535 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6536 NET_FLAGS_ANONYMOUS,
6537 rpc_samdump_internals, argc, argv);
6540 /* syncronise sam database via samsync rpc calls */
6541 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
6543 struct functable func[] = {
6545 "ldif",
6546 rpc_vampire_ldif,
6547 NET_TRANSPORT_RPC,
6548 N_("Dump remote SAM database to ldif"),
6549 N_("net rpc vampire ldif\n"
6550 " Dump remote SAM database to LDIF file or "
6551 "stdout")
6554 "keytab",
6555 rpc_vampire_keytab,
6556 NET_TRANSPORT_RPC,
6557 N_("Dump remote SAM database to Kerberos Keytab"),
6558 N_("net rpc vampire keytab\n"
6559 " Dump remote SAM database to Kerberos keytab "
6560 "file")
6563 "passdb",
6564 rpc_vampire_passdb,
6565 NET_TRANSPORT_RPC,
6566 N_("Dump remote SAM database to passdb"),
6567 N_("net rpc vampire passdb\n"
6568 " Dump remote SAM database to passdb")
6571 {NULL, NULL, 0, NULL, NULL}
6574 if (argc == 0) {
6575 if (c->display_usage) {
6576 d_printf( "%s\n"
6577 "net rpc vampire\n"
6578 " %s\n",
6579 _("Usage:"),
6580 _("Vampire remote SAM database"));
6581 return 0;
6584 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6585 NET_FLAGS_ANONYMOUS,
6586 rpc_vampire_internals,
6587 argc, argv);
6590 return net_run_function(c, argc, argv, "net rpc vampire", func);
6594 * Migrate everything from a print server.
6596 * @param c A net_context structure.
6597 * @param argc Standard main() style argc.
6598 * @param argv Standard main() style argv. Initial components are already
6599 * stripped.
6601 * @return A shell status integer (0 for success).
6603 * The order is important !
6604 * To successfully add drivers the print queues have to exist !
6605 * Applying ACLs should be the last step, because you're easily locked out.
6608 static int rpc_printer_migrate_all(struct net_context *c, int argc,
6609 const char **argv)
6611 int ret;
6613 if (c->display_usage) {
6614 d_printf( "%s\n"
6615 "net rpc printer migrate all\n"
6616 " %s\n",
6617 _("Usage:"),
6618 _("Migrate everything from a print server"));
6619 return 0;
6622 if (!c->opt_host) {
6623 d_printf(_("no server to migrate\n"));
6624 return -1;
6627 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6628 rpc_printer_migrate_printers_internals, argc,
6629 argv);
6630 if (ret)
6631 return ret;
6633 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6634 rpc_printer_migrate_drivers_internals, argc,
6635 argv);
6636 if (ret)
6637 return ret;
6639 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6640 rpc_printer_migrate_forms_internals, argc, argv);
6641 if (ret)
6642 return ret;
6644 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6645 rpc_printer_migrate_settings_internals, argc,
6646 argv);
6647 if (ret)
6648 return ret;
6650 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6651 rpc_printer_migrate_security_internals, argc,
6652 argv);
6657 * Migrate print drivers from a print server.
6659 * @param c A net_context structure.
6660 * @param argc Standard main() style argc.
6661 * @param argv Standard main() style argv. Initial components are already
6662 * stripped.
6664 * @return A shell status integer (0 for success).
6666 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
6667 const char **argv)
6669 if (c->display_usage) {
6670 d_printf( "%s\n"
6671 "net rpc printer migrate drivers\n"
6672 " %s\n",
6673 _("Usage:"),
6674 _("Migrate print-drivers from a print-server"));
6675 return 0;
6678 if (!c->opt_host) {
6679 d_printf(_("no server to migrate\n"));
6680 return -1;
6683 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6684 rpc_printer_migrate_drivers_internals,
6685 argc, argv);
6689 * Migrate print-forms from a print-server.
6691 * @param c A net_context structure.
6692 * @param argc Standard main() style argc.
6693 * @param argv Standard main() style argv. Initial components are already
6694 * stripped.
6696 * @return A shell status integer (0 for success).
6698 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
6699 const char **argv)
6701 if (c->display_usage) {
6702 d_printf( "%s\n"
6703 "net rpc printer migrate forms\n"
6704 " %s\n",
6705 _("Usage:"),
6706 _("Migrate print-forms from a print-server"));
6707 return 0;
6710 if (!c->opt_host) {
6711 d_printf(_("no server to migrate\n"));
6712 return -1;
6715 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6716 rpc_printer_migrate_forms_internals,
6717 argc, argv);
6721 * Migrate printers from a print-server.
6723 * @param c A net_context structure.
6724 * @param argc Standard main() style argc.
6725 * @param argv Standard main() style argv. Initial components are already
6726 * stripped.
6728 * @return A shell status integer (0 for success).
6730 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
6731 const char **argv)
6733 if (c->display_usage) {
6734 d_printf( "%s\n"
6735 "net rpc printer migrate printers\n"
6736 " %s\n",
6737 _("Usage:"),
6738 _("Migrate printers from a print-server"));
6739 return 0;
6742 if (!c->opt_host) {
6743 d_printf(_("no server to migrate\n"));
6744 return -1;
6747 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6748 rpc_printer_migrate_printers_internals,
6749 argc, argv);
6753 * Migrate printer-ACLs from a print-server
6755 * @param c A net_context structure.
6756 * @param argc Standard main() style argc.
6757 * @param argv Standard main() style argv. Initial components are already
6758 * stripped.
6760 * @return A shell status integer (0 for success).
6762 static int rpc_printer_migrate_security(struct net_context *c, int argc,
6763 const char **argv)
6765 if (c->display_usage) {
6766 d_printf( "%s\n"
6767 "net rpc printer migrate security\n"
6768 " %s\n",
6769 _("Usage:"),
6770 _("Migrate printer-ACLs from a print-server"));
6771 return 0;
6774 if (!c->opt_host) {
6775 d_printf(_("no server to migrate\n"));
6776 return -1;
6779 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6780 rpc_printer_migrate_security_internals,
6781 argc, argv);
6785 * Migrate printer-settings from a print-server.
6787 * @param c A net_context structure.
6788 * @param argc Standard main() style argc.
6789 * @param argv Standard main() style argv. Initial components are already
6790 * stripped.
6792 * @return A shell status integer (0 for success).
6794 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
6795 const char **argv)
6797 if (c->display_usage) {
6798 d_printf( "%s\n"
6799 "net rpc printer migrate settings\n"
6800 " %s\n",
6801 _("Usage:"),
6802 _("Migrate printer-settings from a "
6803 "print-server"));
6804 return 0;
6807 if (!c->opt_host) {
6808 d_printf(_("no server to migrate\n"));
6809 return -1;
6812 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6813 rpc_printer_migrate_settings_internals,
6814 argc, argv);
6818 * 'net rpc printer' entrypoint.
6820 * @param c A net_context structure.
6821 * @param argc Standard main() style argc.
6822 * @param argv Standard main() style argv. Initial components are already
6823 * stripped.
6826 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
6829 /* ouch: when addriver and setdriver are called from within
6830 rpc_printer_migrate_drivers_internals, the printer-queue already
6831 *has* to exist */
6833 struct functable func[] = {
6835 "all",
6836 rpc_printer_migrate_all,
6837 NET_TRANSPORT_RPC,
6838 N_("Migrate all from remote to local print server"),
6839 N_("net rpc printer migrate all\n"
6840 " Migrate all from remote to local print server")
6843 "drivers",
6844 rpc_printer_migrate_drivers,
6845 NET_TRANSPORT_RPC,
6846 N_("Migrate drivers to local server"),
6847 N_("net rpc printer migrate drivers\n"
6848 " Migrate drivers to local server")
6851 "forms",
6852 rpc_printer_migrate_forms,
6853 NET_TRANSPORT_RPC,
6854 N_("Migrate froms to local server"),
6855 N_("net rpc printer migrate forms\n"
6856 " Migrate froms to local server")
6859 "printers",
6860 rpc_printer_migrate_printers,
6861 NET_TRANSPORT_RPC,
6862 N_("Migrate printers to local server"),
6863 N_("net rpc printer migrate printers\n"
6864 " Migrate printers to local server")
6867 "security",
6868 rpc_printer_migrate_security,
6869 NET_TRANSPORT_RPC,
6870 N_("Mirgate printer ACLs to local server"),
6871 N_("net rpc printer migrate security\n"
6872 " Mirgate printer ACLs to local server")
6875 "settings",
6876 rpc_printer_migrate_settings,
6877 NET_TRANSPORT_RPC,
6878 N_("Migrate printer settings to local server"),
6879 N_("net rpc printer migrate settings\n"
6880 " Migrate printer settings to local server")
6882 {NULL, NULL, 0, NULL, NULL}
6885 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
6890 * List printers on a remote RPC server.
6892 * @param c A net_context structure.
6893 * @param argc Standard main() style argc.
6894 * @param argv Standard main() style argv. Initial components are already
6895 * stripped.
6897 * @return A shell status integer (0 for success).
6899 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
6901 if (c->display_usage) {
6902 d_printf( "%s\n"
6903 "net rpc printer list\n"
6904 " %s\n",
6905 _("Usage:"),
6906 _("List printers on a remote RPC server"));
6907 return 0;
6910 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6911 rpc_printer_list_internals,
6912 argc, argv);
6916 * List printer-drivers on a remote RPC server.
6918 * @param c A net_context structure.
6919 * @param argc Standard main() style argc.
6920 * @param argv Standard main() style argv. Initial components are already
6921 * stripped.
6923 * @return A shell status integer (0 for success).
6925 static int rpc_printer_driver_list(struct net_context *c, int argc,
6926 const char **argv)
6928 if (c->display_usage) {
6929 d_printf( "%s\n"
6930 "net rpc printer driver\n"
6931 " %s\n",
6932 _("Usage:"),
6933 _("List printer-drivers on a remote RPC server"));
6934 return 0;
6937 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6938 rpc_printer_driver_list_internals,
6939 argc, argv);
6943 * Publish printer in ADS via MSRPC.
6945 * @param c A net_context structure.
6946 * @param argc Standard main() style argc.
6947 * @param argv Standard main() style argv. Initial components are already
6948 * stripped.
6950 * @return A shell status integer (0 for success).
6952 static int rpc_printer_publish_publish(struct net_context *c, int argc,
6953 const char **argv)
6955 if (c->display_usage) {
6956 d_printf( "%s\n"
6957 "net rpc printer publish publish\n"
6958 " %s\n",
6959 _("Usage:"),
6960 _("Publish printer in ADS via MSRPC"));
6961 return 0;
6964 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6965 rpc_printer_publish_publish_internals,
6966 argc, argv);
6970 * Update printer in ADS via MSRPC.
6972 * @param c A net_context structure.
6973 * @param argc Standard main() style argc.
6974 * @param argv Standard main() style argv. Initial components are already
6975 * stripped.
6977 * @return A shell status integer (0 for success).
6979 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
6981 if (c->display_usage) {
6982 d_printf( "%s\n"
6983 "net rpc printer publish update\n"
6984 " %s\n",
6985 _("Usage:"),
6986 _("Update printer in ADS via MSRPC"));
6987 return 0;
6990 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6991 rpc_printer_publish_update_internals,
6992 argc, argv);
6996 * UnPublish printer in ADS via MSRPC.
6998 * @param c A net_context structure.
6999 * @param argc Standard main() style argc.
7000 * @param argv Standard main() style argv. Initial components are already
7001 * stripped.
7003 * @return A shell status integer (0 for success).
7005 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7006 const char **argv)
7008 if (c->display_usage) {
7009 d_printf( "%s\n"
7010 "net rpc printer publish unpublish\n"
7011 " %s\n",
7012 _("Usage:\n"),
7013 _("UnPublish printer in ADS via MSRPC"));
7014 return 0;
7017 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7018 rpc_printer_publish_unpublish_internals,
7019 argc, argv);
7023 * List published printers via MSRPC.
7025 * @param c A net_context structure.
7026 * @param argc Standard main() style argc.
7027 * @param argv Standard main() style argv. Initial components are already
7028 * stripped.
7030 * @return A shell status integer (0 for success).
7032 static int rpc_printer_publish_list(struct net_context *c, int argc,
7033 const char **argv)
7035 if (c->display_usage) {
7036 d_printf( "%s\n"
7037 "net rpc printer publish list\n"
7038 " %s\n",
7039 _("Usage:"),
7040 _("List published printers via MSRPC"));
7041 return 0;
7044 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7045 rpc_printer_publish_list_internals,
7046 argc, argv);
7051 * Publish printer in ADS.
7053 * @param c A net_context structure.
7054 * @param argc Standard main() style argc.
7055 * @param argv Standard main() style argv. Initial components are already
7056 * stripped.
7058 * @return A shell status integer (0 for success).
7060 static int rpc_printer_publish(struct net_context *c, int argc,
7061 const char **argv)
7064 struct functable func[] = {
7066 "publish",
7067 rpc_printer_publish_publish,
7068 NET_TRANSPORT_RPC,
7069 N_("Publish printer in AD"),
7070 N_("net rpc printer publish publish\n"
7071 " Publish printer in AD")
7074 "update",
7075 rpc_printer_publish_update,
7076 NET_TRANSPORT_RPC,
7077 N_("Update printer in AD"),
7078 N_("net rpc printer publish update\n"
7079 " Update printer in AD")
7082 "unpublish",
7083 rpc_printer_publish_unpublish,
7084 NET_TRANSPORT_RPC,
7085 N_("Unpublish printer"),
7086 N_("net rpc printer publish unpublish\n"
7087 " Unpublish printer")
7090 "list",
7091 rpc_printer_publish_list,
7092 NET_TRANSPORT_RPC,
7093 N_("List published printers"),
7094 N_("net rpc printer publish list\n"
7095 " List published printers")
7097 {NULL, NULL, 0, NULL, NULL}
7100 if (argc == 0) {
7101 if (c->display_usage) {
7102 d_printf(_("Usage:\n"));
7103 d_printf(_("net rpc printer publish\n"
7104 " List published printers\n"
7105 " Alias of net rpc printer publish "
7106 "list\n"));
7107 net_display_usage_from_functable(func);
7108 return 0;
7110 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7111 rpc_printer_publish_list_internals,
7112 argc, argv);
7115 return net_run_function(c, argc, argv, "net rpc printer publish",func);
7121 * Display rpc printer help page.
7123 * @param c A net_context structure.
7124 * @param argc Standard main() style argc.
7125 * @param argv Standard main() style argv. Initial components are already
7126 * stripped.
7128 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
7130 d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
7131 "\tlists all printers on print-server\n\n"));
7132 d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
7133 "\tlists all printer-drivers on print-server\n\n"));
7134 d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
7135 "\tpublishes printer settings in Active Directory\n"
7136 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
7137 d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
7138 "\n\tmigrates printers from remote to local server\n\n"));
7139 d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
7140 "\n\tmigrates printer-settings from remote to local server\n\n"));
7141 d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
7142 "\n\tmigrates printer-drivers from remote to local server\n\n"));
7143 d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
7144 "\n\tmigrates printer-forms from remote to local server\n\n"));
7145 d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
7146 "\n\tmigrates printer-ACLs from remote to local server\n\n"));
7147 d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
7148 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
7149 "\tremote to local print-server\n\n"));
7150 net_common_methods_usage(c, argc, argv);
7151 net_common_flags_usage(c, argc, argv);
7152 d_printf(_(
7153 "\t-v or --verbose\t\t\tgive verbose output\n"
7154 "\t --destination\t\tmigration target server (default: localhost)\n"));
7156 return -1;
7160 * 'net rpc printer' entrypoint.
7162 * @param c A net_context structure.
7163 * @param argc Standard main() style argc.
7164 * @param argv Standard main() style argv. Initial components are already
7165 * stripped.
7167 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7169 struct functable func[] = {
7171 "list",
7172 rpc_printer_list,
7173 NET_TRANSPORT_RPC,
7174 N_("List all printers on print server"),
7175 N_("net rpc printer list\n"
7176 " List all printers on print server")
7179 "migrate",
7180 rpc_printer_migrate,
7181 NET_TRANSPORT_RPC,
7182 N_("Migrate printer to local server"),
7183 N_("net rpc printer migrate\n"
7184 " Migrate printer to local server")
7187 "driver",
7188 rpc_printer_driver_list,
7189 NET_TRANSPORT_RPC,
7190 N_("List printer drivers"),
7191 N_("net rpc printer driver\n"
7192 " List printer drivers")
7195 "publish",
7196 rpc_printer_publish,
7197 NET_TRANSPORT_RPC,
7198 N_("Publish printer in AD"),
7199 N_("net rpc printer publish\n"
7200 " Publish printer in AD")
7202 {NULL, NULL, 0, NULL, NULL}
7205 if (argc == 0) {
7206 if (c->display_usage) {
7207 d_printf(_("Usage:\n"));
7208 d_printf(_("net rpc printer\n"
7209 " List printers\n"));
7210 net_display_usage_from_functable(func);
7211 return 0;
7213 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7214 rpc_printer_list_internals,
7215 argc, argv);
7218 return net_run_function(c, argc, argv, "net rpc printer", func);
7222 * 'net rpc' entrypoint.
7224 * @param c A net_context structure.
7225 * @param argc Standard main() style argc.
7226 * @param argv Standard main() style argv. Initial components are already
7227 * stripped.
7230 int net_rpc(struct net_context *c, int argc, const char **argv)
7232 NET_API_STATUS status;
7234 struct functable func[] = {
7236 "audit",
7237 net_rpc_audit,
7238 NET_TRANSPORT_RPC,
7239 N_("Modify global audit settings"),
7240 N_("net rpc audit\n"
7241 " Modify global audit settings")
7244 "info",
7245 net_rpc_info,
7246 NET_TRANSPORT_RPC,
7247 N_("Show basic info about a domain"),
7248 N_("net rpc info\n"
7249 " Show basic info about a domain")
7252 "join",
7253 net_rpc_join,
7254 NET_TRANSPORT_RPC,
7255 N_("Join a domain"),
7256 N_("net rpc join\n"
7257 " Join a domain")
7260 "oldjoin",
7261 net_rpc_oldjoin,
7262 NET_TRANSPORT_RPC,
7263 N_("Join a domain created in server manager"),
7264 N_("net rpc oldjoin\n"
7265 " Join a domain created in server manager")
7268 "testjoin",
7269 net_rpc_testjoin,
7270 NET_TRANSPORT_RPC,
7271 N_("Test that a join is valid"),
7272 N_("net rpc testjoin\n"
7273 " Test that a join is valid")
7276 "user",
7277 net_rpc_user,
7278 NET_TRANSPORT_RPC,
7279 N_("List/modify users"),
7280 N_("net rpc user\n"
7281 " List/modify users")
7284 "password",
7285 rpc_user_password,
7286 NET_TRANSPORT_RPC,
7287 N_("Change a user password"),
7288 N_("net rpc password\n"
7289 " Change a user password\n"
7290 " Alias for net rpc user password")
7293 "group",
7294 net_rpc_group,
7295 NET_TRANSPORT_RPC,
7296 N_("List/modify groups"),
7297 N_("net rpc group\n"
7298 " List/modify groups")
7301 "share",
7302 net_rpc_share,
7303 NET_TRANSPORT_RPC,
7304 N_("List/modify shares"),
7305 N_("net rpc share\n"
7306 " List/modify shares")
7309 "file",
7310 net_rpc_file,
7311 NET_TRANSPORT_RPC,
7312 N_("List open files"),
7313 N_("net rpc file\n"
7314 " List open files")
7317 "printer",
7318 net_rpc_printer,
7319 NET_TRANSPORT_RPC,
7320 N_("List/modify printers"),
7321 N_("net rpc printer\n"
7322 " List/modify printers")
7325 "changetrustpw",
7326 net_rpc_changetrustpw,
7327 NET_TRANSPORT_RPC,
7328 N_("Change trust account password"),
7329 N_("net rpc changetrustpw\n"
7330 " Change trust account password")
7333 "trustdom",
7334 rpc_trustdom,
7335 NET_TRANSPORT_RPC,
7336 N_("Modify domain trusts"),
7337 N_("net rpc trustdom\n"
7338 " Modify domain trusts")
7341 "abortshutdown",
7342 rpc_shutdown_abort,
7343 NET_TRANSPORT_RPC,
7344 N_("Abort a remote shutdown"),
7345 N_("net rpc abortshutdown\n"
7346 " Abort a remote shutdown")
7349 "shutdown",
7350 rpc_shutdown,
7351 NET_TRANSPORT_RPC,
7352 N_("Shutdown a remote server"),
7353 N_("net rpc shutdown\n"
7354 " Shutdown a remote server")
7357 "samdump",
7358 rpc_samdump,
7359 NET_TRANSPORT_RPC,
7360 N_("Dump SAM data of remote NT PDC"),
7361 N_("net rpc samdump\n"
7362 " Dump SAM data of remote NT PDC")
7365 "vampire",
7366 rpc_vampire,
7367 NET_TRANSPORT_RPC,
7368 N_("Sync a remote NT PDC's data into local passdb"),
7369 N_("net rpc vampire\n"
7370 " Sync a remote NT PDC's data into local passdb")
7373 "getsid",
7374 net_rpc_getsid,
7375 NET_TRANSPORT_RPC,
7376 N_("Fetch the domain sid into local secrets.tdb"),
7377 N_("net rpc getsid\n"
7378 " Fetch the domain sid into local secrets.tdb")
7381 "rights",
7382 net_rpc_rights,
7383 NET_TRANSPORT_RPC,
7384 N_("Manage privileges assigned to SID"),
7385 N_("net rpc rights\n"
7386 " Manage privileges assigned to SID")
7389 "service",
7390 net_rpc_service,
7391 NET_TRANSPORT_RPC,
7392 N_("Start/stop/query remote services"),
7393 N_("net rpc service\n"
7394 " Start/stop/query remote services")
7397 "registry",
7398 net_rpc_registry,
7399 NET_TRANSPORT_RPC,
7400 N_("Manage registry hives"),
7401 N_("net rpc registry\n"
7402 " Manage registry hives")
7405 "shell",
7406 net_rpc_shell,
7407 NET_TRANSPORT_RPC,
7408 N_("Open interactive shell on remote server"),
7409 N_("net rpc shell\n"
7410 " Open interactive shell on remote server")
7412 {NULL, NULL, 0, NULL, NULL}
7415 status = libnetapi_init(&c->netapi_ctx);
7416 if (status != 0) {
7417 return -1;
7419 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
7420 libnetapi_set_password(c->netapi_ctx, c->opt_password);
7421 if (c->opt_kerberos) {
7422 libnetapi_set_use_kerberos(c->netapi_ctx);
7424 if (c->opt_ccache) {
7425 libnetapi_set_use_ccache(c->netapi_ctx);
7428 return net_run_function(c, argc, argv, "net rpc", func);