build do not add -no-undefined on openbsd
[Samba.git] / source3 / utils / net_rpc.c
blob228f7eb8524907bdcd5d9688352dd46fe7252f20
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 "rpc_client/cli_samr.h"
28 #include "rpc_client/init_samr.h"
29 #include "../librpc/gen_ndr/cli_lsa.h"
30 #include "rpc_client/cli_lsarpc.h"
31 #include "../librpc/gen_ndr/cli_netlogon.h"
32 #include "../librpc/gen_ndr/cli_srvsvc.h"
33 #include "../librpc/gen_ndr/cli_spoolss.h"
34 #include "../librpc/gen_ndr/cli_initshutdown.h"
35 #include "../librpc/gen_ndr/cli_winreg.h"
36 #include "secrets.h"
37 #include "lib/netapi/netapi.h"
38 #include "lib/netapi/netapi_net.h"
39 #include "rpc_client/init_lsa.h"
40 #include "../libcli/security/security.h"
42 static int net_mode_share;
43 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
45 /**
46 * @file net_rpc.c
48 * @brief RPC based subcommands for the 'net' utility.
50 * This file should contain much of the functionality that used to
51 * be found in rpcclient, execpt that the commands should change
52 * less often, and the fucntionality should be sane (the user is not
53 * expected to know a rid/sid before they conduct an operation etc.)
55 * @todo Perhaps eventually these should be split out into a number
56 * of files, as this could get quite big.
57 **/
60 /**
61 * Many of the RPC functions need the domain sid. This function gets
62 * it at the start of every run
64 * @param cli A cli_state already connected to the remote machine
66 * @return The Domain SID of the remote machine.
67 **/
69 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
70 struct dom_sid **domain_sid,
71 const char **domain_name)
73 struct rpc_pipe_client *lsa_pipe = NULL;
74 struct policy_handle pol;
75 NTSTATUS result = NT_STATUS_OK;
76 union lsa_PolicyInformation *info = NULL;
78 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
79 &lsa_pipe);
80 if (!NT_STATUS_IS_OK(result)) {
81 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
82 return result;
85 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
86 SEC_FLAG_MAXIMUM_ALLOWED,
87 &pol);
88 if (!NT_STATUS_IS_OK(result)) {
89 d_fprintf(stderr, "open_policy %s: %s\n",
90 _("failed"),
91 nt_errstr(result));
92 return result;
95 result = rpccli_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx,
96 &pol,
97 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
98 &info);
99 if (!NT_STATUS_IS_OK(result)) {
100 d_fprintf(stderr, "lsaquery %s: %s\n",
101 _("failed"),
102 nt_errstr(result));
103 return result;
106 *domain_name = info->account_domain.name.string;
107 *domain_sid = info->account_domain.sid;
109 rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
110 TALLOC_FREE(lsa_pipe);
112 return NT_STATUS_OK;
116 * Run a single RPC command, from start to finish.
118 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
119 * @param conn_flag a NET_FLAG_ combination. Passed to
120 * net_make_ipc_connection.
121 * @param argc Standard main() style argc.
122 * @param argv Standard main() style argv. Initial components are already
123 * stripped.
124 * @return A shell status integer (0 for success).
127 int run_rpc_command(struct net_context *c,
128 struct cli_state *cli_arg,
129 const struct ndr_syntax_id *interface,
130 int conn_flags,
131 rpc_command_fn fn,
132 int argc,
133 const char **argv)
135 struct cli_state *cli = NULL;
136 struct rpc_pipe_client *pipe_hnd = NULL;
137 TALLOC_CTX *mem_ctx;
138 NTSTATUS nt_status;
139 struct dom_sid *domain_sid;
140 const char *domain_name;
141 int ret = -1;
143 /* make use of cli_state handed over as an argument, if possible */
144 if (!cli_arg) {
145 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
146 if (!NT_STATUS_IS_OK(nt_status)) {
147 DEBUG(1, ("failed to make ipc connection: %s\n",
148 nt_errstr(nt_status)));
149 return -1;
151 } else {
152 cli = cli_arg;
155 if (!cli) {
156 return -1;
159 /* Create mem_ctx */
161 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
162 DEBUG(0, ("talloc_init() failed\n"));
163 goto fail;
166 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
167 &domain_name);
168 if (!NT_STATUS_IS_OK(nt_status)) {
169 goto fail;
172 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
173 if (lp_client_schannel()
174 && (ndr_syntax_id_equal(interface,
175 &ndr_table_netlogon.syntax_id))) {
176 /* Always try and create an schannel netlogon pipe. */
177 nt_status = cli_rpc_pipe_open_schannel(
178 cli, interface, NCACN_NP,
179 DCERPC_AUTH_LEVEL_PRIVACY, domain_name,
180 &pipe_hnd);
181 if (!NT_STATUS_IS_OK(nt_status)) {
182 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
183 nt_errstr(nt_status) ));
184 goto fail;
186 } else {
187 if (conn_flags & NET_FLAGS_SEAL) {
188 nt_status = cli_rpc_pipe_open_ntlmssp(
189 cli, interface,
190 (conn_flags & NET_FLAGS_TCP) ?
191 NCACN_IP_TCP : NCACN_NP,
192 DCERPC_AUTH_LEVEL_PRIVACY,
193 lp_workgroup(), c->opt_user_name,
194 c->opt_password, &pipe_hnd);
195 } else {
196 nt_status = cli_rpc_pipe_open_noauth(
197 cli, interface,
198 &pipe_hnd);
200 if (!NT_STATUS_IS_OK(nt_status)) {
201 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
202 get_pipe_name_from_syntax(
203 talloc_tos(), interface),
204 nt_errstr(nt_status) ));
205 goto fail;
210 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
212 if (!NT_STATUS_IS_OK(nt_status)) {
213 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
214 } else {
215 ret = 0;
216 DEBUG(5, ("rpc command function succedded\n"));
219 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
220 if (pipe_hnd) {
221 TALLOC_FREE(pipe_hnd);
225 fail:
226 /* close the connection only if it was opened here */
227 if (!cli_arg) {
228 cli_shutdown(cli);
231 talloc_destroy(mem_ctx);
232 return ret;
236 * Force a change of the trust acccount password.
238 * All parameters are provided by the run_rpc_command function, except for
239 * argc, argv which are passed through.
241 * @param domain_sid The domain sid acquired from the remote server.
242 * @param cli A cli_state connected to the server.
243 * @param mem_ctx Talloc context, destroyed on completion of the function.
244 * @param argc Standard main() style argc.
245 * @param argv Standard main() style argv. Initial components are already
246 * stripped.
248 * @return Normal NTSTATUS return.
251 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
252 const struct dom_sid *domain_sid,
253 const char *domain_name,
254 struct cli_state *cli,
255 struct rpc_pipe_client *pipe_hnd,
256 TALLOC_CTX *mem_ctx,
257 int argc,
258 const char **argv)
260 NTSTATUS status;
262 status = trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
263 if (!NT_STATUS_IS_OK(status)) {
264 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
265 nt_errstr(status));
266 return status;
269 return NT_STATUS_OK;
273 * Force a change of the trust acccount password.
275 * @param argc Standard main() style argc.
276 * @param argv Standard main() style argv. Initial components are already
277 * stripped.
279 * @return A shell status integer (0 for success).
282 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
284 if (c->display_usage) {
285 d_printf( "%s\n"
286 "net rpc changetrustpw\n"
287 " %s\n",
288 _("Usage:"),
289 _("Change the machine trust password"));
290 return 0;
293 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
294 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
295 rpc_changetrustpw_internals,
296 argc, argv);
300 * Join a domain, the old way.
302 * This uses 'machinename' as the inital password, and changes it.
304 * The password should be created with 'server manager' or equiv first.
306 * All parameters are provided by the run_rpc_command function, except for
307 * argc, argv which are passed through.
309 * @param domain_sid The domain sid acquired from the remote server.
310 * @param cli A cli_state connected to the server.
311 * @param mem_ctx Talloc context, destroyed on completion of the function.
312 * @param argc Standard main() style argc.
313 * @param argv Standard main() style argv. Initial components are already
314 * stripped.
316 * @return Normal NTSTATUS return.
319 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
320 const struct dom_sid *domain_sid,
321 const char *domain_name,
322 struct cli_state *cli,
323 struct rpc_pipe_client *pipe_hnd,
324 TALLOC_CTX *mem_ctx,
325 int argc,
326 const char **argv)
329 fstring trust_passwd;
330 unsigned char orig_trust_passwd_hash[16];
331 NTSTATUS result;
332 enum netr_SchannelType sec_channel_type;
334 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
335 &pipe_hnd);
336 if (!NT_STATUS_IS_OK(result)) {
337 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
338 "error was %s\n",
339 cli->desthost,
340 nt_errstr(result) ));
341 return result;
345 check what type of join - if the user want's to join as
346 a BDC, the server must agree that we are a BDC.
348 if (argc >= 0) {
349 sec_channel_type = get_sec_channel_type(argv[0]);
350 } else {
351 sec_channel_type = get_sec_channel_type(NULL);
354 fstrcpy(trust_passwd, global_myname());
355 strlower_m(trust_passwd);
358 * Machine names can be 15 characters, but the max length on
359 * a password is 14. --jerry
362 trust_passwd[14] = '\0';
364 E_md4hash(trust_passwd, orig_trust_passwd_hash);
366 result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
367 global_myname(),
368 orig_trust_passwd_hash,
369 sec_channel_type);
371 if (NT_STATUS_IS_OK(result))
372 printf(_("Joined domain %s.\n"), c->opt_target_workgroup);
375 if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
376 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
377 result = NT_STATUS_UNSUCCESSFUL;
380 return result;
384 * Join a domain, the old way.
386 * @param argc Standard main() style argc.
387 * @param argv Standard main() style argv. Initial components are already
388 * stripped.
390 * @return A shell status integer (0 for success).
393 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
395 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
396 NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
397 rpc_oldjoin_internals,
398 argc, argv);
402 * Join a domain, the old way. This function exists to allow
403 * the message to be displayed when oldjoin was explicitly
404 * requested, but not when it was implied by "net rpc join".
406 * @param argc Standard main() style argc.
407 * @param argv Standard main() style argv. Initial components are already
408 * stripped.
410 * @return A shell status integer (0 for success).
413 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
415 int rc = -1;
417 if (c->display_usage) {
418 d_printf( "%s\n"
419 "net rpc oldjoin\n"
420 " %s\n",
421 _("Usage:"),
422 _("Join a domain the old way"));
423 return 0;
426 rc = net_rpc_perform_oldjoin(c, argc, argv);
428 if (rc) {
429 d_fprintf(stderr, _("Failed to join domain\n"));
432 return rc;
436 * 'net rpc join' entrypoint.
437 * @param argc Standard main() style argc.
438 * @param argv Standard main() style argv. Initial components are already
439 * stripped
441 * Main 'net_rpc_join()' (where the admin username/password is used) is
442 * in net_rpc_join.c.
443 * Try to just change the password, but if that doesn't work, use/prompt
444 * for a username/password.
447 int net_rpc_join(struct net_context *c, int argc, const char **argv)
449 if (c->display_usage) {
450 d_printf("%s\n%s",
451 _("Usage:"),
452 _("net rpc join -U <username>[%%password] <type>\n"
453 " Join a domain\n"
454 " username\tName of the admin user"
455 " password\tPassword of the admin user, will "
456 "prompt if not specified\n"
457 " type\tCan be one of the following:\n"
458 "\t\tMEMBER\tJoin as member server (default)\n"
459 "\t\tBDC\tJoin as BDC\n"
460 "\t\tPDC\tJoin as PDC\n"));
461 return 0;
464 if (lp_server_role() == ROLE_STANDALONE) {
465 d_printf(_("cannot join as standalone machine\n"));
466 return -1;
469 if (strlen(global_myname()) > 15) {
470 d_printf(_("Our netbios name can be at most 15 chars long, "
471 "\"%s\" is %u chars long\n"),
472 global_myname(), (unsigned int)strlen(global_myname()));
473 return -1;
476 if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
477 return 0;
479 return net_rpc_join_newstyle(c, argc, argv);
483 * display info about a rpc domain
485 * All parameters are provided by the run_rpc_command function, except for
486 * argc, argv which are passed through.
488 * @param domain_sid The domain sid acquired from the remote server
489 * @param cli A cli_state connected to the server.
490 * @param mem_ctx Talloc context, destroyed on completion of the function.
491 * @param argc Standard main() style argc.
492 * @param argv Standard main() style argv. Initial components are already
493 * stripped.
495 * @return Normal NTSTATUS return.
498 NTSTATUS rpc_info_internals(struct net_context *c,
499 const struct dom_sid *domain_sid,
500 const char *domain_name,
501 struct cli_state *cli,
502 struct rpc_pipe_client *pipe_hnd,
503 TALLOC_CTX *mem_ctx,
504 int argc,
505 const char **argv)
507 struct policy_handle connect_pol, domain_pol;
508 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
509 union samr_DomainInfo *info = NULL;
510 fstring sid_str;
512 sid_to_fstring(sid_str, domain_sid);
514 /* Get sam policy handle */
515 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
516 pipe_hnd->desthost,
517 MAXIMUM_ALLOWED_ACCESS,
518 &connect_pol);
519 if (!NT_STATUS_IS_OK(result)) {
520 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
521 nt_errstr(result));
522 goto done;
525 /* Get domain policy handle */
526 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
527 &connect_pol,
528 MAXIMUM_ALLOWED_ACCESS,
529 CONST_DISCARD(struct dom_sid2 *, domain_sid),
530 &domain_pol);
531 if (!NT_STATUS_IS_OK(result)) {
532 d_fprintf(stderr, _("Could not open domain: %s\n"),
533 nt_errstr(result));
534 goto done;
537 result = rpccli_samr_QueryDomainInfo(pipe_hnd, mem_ctx,
538 &domain_pol,
540 &info);
541 if (NT_STATUS_IS_OK(result)) {
542 d_printf(_("Domain Name: %s\n"),
543 info->general.domain_name.string);
544 d_printf(_("Domain SID: %s\n"), sid_str);
545 d_printf(_("Sequence number: %llu\n"),
546 (unsigned long long)info->general.sequence_num);
547 d_printf(_("Num users: %u\n"), info->general.num_users);
548 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
549 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
552 done:
553 return result;
557 * 'net rpc info' entrypoint.
558 * @param argc Standard main() style argc.
559 * @param argv Standard main() style argv. Initial components are already
560 * stripped.
563 int net_rpc_info(struct net_context *c, int argc, const char **argv)
565 if (c->display_usage) {
566 d_printf( "%s\n"
567 "net rpc info\n"
568 " %s\n",
569 _("Usage:"),
570 _("Display information about the domain"));
571 return 0;
574 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
575 NET_FLAGS_PDC, rpc_info_internals,
576 argc, argv);
580 * Fetch domain SID into the local secrets.tdb.
582 * All parameters are provided by the run_rpc_command function, except for
583 * argc, argv which are passed through.
585 * @param domain_sid The domain sid acquired from the remote server.
586 * @param cli A cli_state connected to the server.
587 * @param mem_ctx Talloc context, destroyed on completion of the function.
588 * @param argc Standard main() style argc.
589 * @param argv Standard main() style argv. Initial components are already
590 * stripped.
592 * @return Normal NTSTATUS return.
595 static NTSTATUS rpc_getsid_internals(struct net_context *c,
596 const struct dom_sid *domain_sid,
597 const char *domain_name,
598 struct cli_state *cli,
599 struct rpc_pipe_client *pipe_hnd,
600 TALLOC_CTX *mem_ctx,
601 int argc,
602 const char **argv)
604 fstring sid_str;
606 sid_to_fstring(sid_str, domain_sid);
607 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
608 sid_str, domain_name);
610 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
611 DEBUG(0,("Can't store domain SID\n"));
612 return NT_STATUS_UNSUCCESSFUL;
615 return NT_STATUS_OK;
619 * 'net rpc getsid' entrypoint.
620 * @param argc Standard main() style argc.
621 * @param argv Standard main() style argv. Initial components are already
622 * stripped.
625 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
627 int conn_flags = NET_FLAGS_PDC;
629 if (!c->opt_user_specified) {
630 conn_flags |= NET_FLAGS_ANONYMOUS;
633 if (c->display_usage) {
634 d_printf( "%s\n"
635 "net rpc getsid\n"
636 " %s\n",
637 _("Usage:"),
638 _("Fetch domain SID into local secrets.tdb"));
639 return 0;
642 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
643 conn_flags,
644 rpc_getsid_internals,
645 argc, argv);
648 /****************************************************************************/
651 * Basic usage function for 'net rpc user'.
652 * @param argc Standard main() style argc.
653 * @param argv Standard main() style argv. Initial components are already
654 * stripped.
657 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
659 return net_user_usage(c, argc, argv);
663 * Add a new user to a remote RPC server.
665 * @param argc Standard main() style argc.
666 * @param argv Standard main() style argv. Initial components are already
667 * stripped.
669 * @return A shell status integer (0 for success).
672 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
674 NET_API_STATUS status;
675 struct USER_INFO_1 info1;
676 uint32_t parm_error = 0;
678 if (argc < 1 || c->display_usage) {
679 rpc_user_usage(c, argc, argv);
680 return 0;
683 ZERO_STRUCT(info1);
685 info1.usri1_name = argv[0];
686 if (argc == 2) {
687 info1.usri1_password = argv[1];
690 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
692 if (status != 0) {
693 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
694 argv[0], libnetapi_get_error_string(c->netapi_ctx,
695 status));
696 return -1;
697 } else {
698 d_printf(_("Added user '%s'.\n"), argv[0]);
701 return 0;
705 * Rename a user on a remote RPC server.
707 * @param argc Standard main() style argc.
708 * @param argv Standard main() style argv. Initial components are already
709 * stripped.
711 * @return A shell status integer (0 for success).
714 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
716 NET_API_STATUS status;
717 struct USER_INFO_0 u0;
718 uint32_t parm_err = 0;
720 if (argc != 2 || c->display_usage) {
721 rpc_user_usage(c, argc, argv);
722 return 0;
725 u0.usri0_name = argv[1];
727 status = NetUserSetInfo(c->opt_host, argv[0],
728 0, (uint8_t *)&u0, &parm_err);
729 if (status) {
730 d_fprintf(stderr,
731 _("Failed to rename user from %s to %s - %s\n"),
732 argv[0], argv[1],
733 libnetapi_get_error_string(c->netapi_ctx, status));
734 } else {
735 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
738 return status;
742 * Set a user's primary group
744 * @param argc Standard main() style argc.
745 * @param argv Standard main() style argv. Initial components are already
746 * stripped.
748 * @return A shell status integer (0 for success).
751 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
752 const char **argv)
754 NET_API_STATUS status;
755 uint8_t *buffer;
756 struct GROUP_INFO_2 *g2;
757 struct USER_INFO_1051 u1051;
758 uint32_t parm_err = 0;
760 if (argc != 2 || c->display_usage) {
761 rpc_user_usage(c, argc, argv);
762 return 0;
765 status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
766 if (status) {
767 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
768 argv[1],
769 libnetapi_get_error_string(c->netapi_ctx, status));
770 return status;
772 g2 = (struct GROUP_INFO_2 *)buffer;
774 u1051.usri1051_primary_group_id = g2->grpi2_group_id;
776 NetApiBufferFree(buffer);
778 status = NetUserSetInfo(c->opt_host, argv[0], 1051,
779 (uint8_t *)&u1051, &parm_err);
780 if (status) {
781 d_fprintf(stderr,
782 _("Failed to set user's primary group %s to %s - "
783 "%s\n"), argv[0], argv[1],
784 libnetapi_get_error_string(c->netapi_ctx, status));
785 } else {
786 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
787 argv[1]);
789 return status;
793 * Delete a user from a remote RPC server.
795 * @param argc Standard main() style argc.
796 * @param argv Standard main() style argv. Initial components are already
797 * stripped.
799 * @return A shell status integer (0 for success).
802 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
804 NET_API_STATUS status;
806 if (argc < 1 || c->display_usage) {
807 rpc_user_usage(c, argc, argv);
808 return 0;
811 status = NetUserDel(c->opt_host, argv[0]);
813 if (status != 0) {
814 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
815 argv[0],
816 libnetapi_get_error_string(c->netapi_ctx, status));
817 return -1;
818 } else {
819 d_printf(_("Deleted user '%s'.\n"), argv[0]);
822 return 0;
826 * Set a user's password on a remote RPC server.
828 * @param argc Standard main() style argc.
829 * @param argv Standard main() style argv. Initial components are already
830 * stripped.
832 * @return A shell status integer (0 for success).
835 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
837 NET_API_STATUS status;
838 char *prompt = NULL;
839 struct USER_INFO_1003 u1003;
840 uint32_t parm_err = 0;
841 int ret;
843 if (argc < 1 || c->display_usage) {
844 rpc_user_usage(c, argc, argv);
845 return 0;
848 if (argv[1]) {
849 u1003.usri1003_password = argv[1];
850 } else {
851 ret = asprintf(&prompt, _("Enter new password for %s:"),
852 argv[0]);
853 if (ret == -1) {
854 return -1;
856 u1003.usri1003_password = talloc_strdup(c, getpass(prompt));
857 SAFE_FREE(prompt);
858 if (u1003.usri1003_password == NULL) {
859 return -1;
863 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
865 /* Display results */
866 if (status != 0) {
867 d_fprintf(stderr,
868 _("Failed to set password for '%s' with error: %s.\n"),
869 argv[0], libnetapi_get_error_string(c->netapi_ctx,
870 status));
871 return -1;
874 return 0;
878 * List a user's groups from a remote RPC server.
880 * @param argc Standard main() style argc.
881 * @param argv Standard main() style argv. Initial components are already
882 * stripped.
884 * @return A shell status integer (0 for success)
887 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
890 NET_API_STATUS status;
891 struct GROUP_USERS_INFO_0 *u0 = NULL;
892 uint32_t entries_read = 0;
893 uint32_t total_entries = 0;
894 int i;
897 if (argc < 1 || c->display_usage) {
898 rpc_user_usage(c, argc, argv);
899 return 0;
902 status = NetUserGetGroups(c->opt_host,
903 argv[0],
905 (uint8_t **)(void *)&u0,
906 (uint32_t)-1,
907 &entries_read,
908 &total_entries);
909 if (status != 0) {
910 d_fprintf(stderr,
911 _("Failed to get groups for '%s' with error: %s.\n"),
912 argv[0], libnetapi_get_error_string(c->netapi_ctx,
913 status));
914 return -1;
917 for (i=0; i < entries_read; i++) {
918 printf("%s\n", u0->grui0_name);
919 u0++;
922 return 0;
926 * List users on a remote RPC server.
928 * All parameters are provided by the run_rpc_command function, except for
929 * argc, argv which are passed through.
931 * @param domain_sid The domain sid acquired from the remote server.
932 * @param cli A cli_state connected to the server.
933 * @param mem_ctx Talloc context, destroyed on completion of the function.
934 * @param argc Standard main() style argc.
935 * @param argv Standard main() style argv. Initial components are already
936 * stripped.
938 * @return Normal NTSTATUS return.
941 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
943 NET_API_STATUS status;
944 uint32_t start_idx=0, num_entries, i, loop_count = 0;
945 struct NET_DISPLAY_USER *info = NULL;
946 void *buffer = NULL;
948 /* Query domain users */
949 if (c->opt_long_list_entries)
950 d_printf(_("\nUser name Comment"
951 "\n-----------------------------\n"));
952 do {
953 uint32_t max_entries, max_size;
955 get_query_dispinfo_params(
956 loop_count, &max_entries, &max_size);
958 status = NetQueryDisplayInformation(c->opt_host,
960 start_idx,
961 max_entries,
962 max_size,
963 &num_entries,
964 &buffer);
965 if (status != 0 && status != ERROR_MORE_DATA) {
966 return status;
969 info = (struct NET_DISPLAY_USER *)buffer;
971 for (i = 0; i < num_entries; i++) {
973 if (c->opt_long_list_entries)
974 printf("%-21.21s %s\n", info->usri1_name,
975 info->usri1_comment);
976 else
977 printf("%s\n", info->usri1_name);
978 info++;
981 NetApiBufferFree(buffer);
983 loop_count++;
984 start_idx += num_entries;
986 } while (status == ERROR_MORE_DATA);
988 return status;
992 * 'net rpc user' entrypoint.
993 * @param argc Standard main() style argc.
994 * @param argv Standard main() style argv. Initial components are already
995 * stripped.
998 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1000 NET_API_STATUS status;
1002 struct functable func[] = {
1004 "add",
1005 rpc_user_add,
1006 NET_TRANSPORT_RPC,
1007 N_("Add specified user"),
1008 N_("net rpc user add\n"
1009 " Add specified user")
1012 "info",
1013 rpc_user_info,
1014 NET_TRANSPORT_RPC,
1015 N_("List domain groups of user"),
1016 N_("net rpc user info\n"
1017 " List domain groups of user")
1020 "delete",
1021 rpc_user_delete,
1022 NET_TRANSPORT_RPC,
1023 N_("Remove specified user"),
1024 N_("net rpc user delete\n"
1025 " Remove specified user")
1028 "password",
1029 rpc_user_password,
1030 NET_TRANSPORT_RPC,
1031 N_("Change user password"),
1032 N_("net rpc user password\n"
1033 " Change user password")
1036 "rename",
1037 rpc_user_rename,
1038 NET_TRANSPORT_RPC,
1039 N_("Rename specified user"),
1040 N_("net rpc user rename\n"
1041 " Rename specified user")
1044 "setprimarygroup",
1045 rpc_user_setprimarygroup,
1046 NET_TRANSPORT_RPC,
1047 "Set a user's primary group",
1048 "net rpc user setprimarygroup\n"
1049 " Set a user's primary group"
1051 {NULL, NULL, 0, NULL, NULL}
1054 status = libnetapi_net_init(&c->netapi_ctx);
1055 if (status != 0) {
1056 return -1;
1058 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1059 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1060 if (c->opt_kerberos) {
1061 libnetapi_set_use_kerberos(c->netapi_ctx);
1064 if (argc == 0) {
1065 if (c->display_usage) {
1066 d_printf( "%s\n"
1067 "net rpc user\n"
1068 " %s\n",
1069 _("Usage:"),
1070 _("List all users"));
1071 net_display_usage_from_functable(func);
1072 return 0;
1075 return rpc_user_list(c, argc, argv);
1078 return net_run_function(c, argc, argv, "net rpc user", func);
1081 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1082 TALLOC_CTX *mem_ctx,
1083 struct rpc_sh_ctx *ctx,
1084 struct rpc_pipe_client *pipe_hnd,
1085 int argc, const char **argv)
1087 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1090 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1091 TALLOC_CTX *mem_ctx,
1092 struct rpc_sh_ctx *ctx,
1093 struct rpc_pipe_client *pipe_hnd,
1094 int argc, const char **argv)
1096 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1099 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1100 TALLOC_CTX *mem_ctx,
1101 struct rpc_sh_ctx *ctx,
1102 struct rpc_pipe_client *pipe_hnd,
1103 int argc, const char **argv,
1104 NTSTATUS (*fn)(
1105 struct net_context *c,
1106 TALLOC_CTX *mem_ctx,
1107 struct rpc_sh_ctx *ctx,
1108 struct rpc_pipe_client *pipe_hnd,
1109 struct policy_handle *user_hnd,
1110 int argc, const char **argv))
1112 struct policy_handle connect_pol, domain_pol, user_pol;
1113 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1114 struct dom_sid sid;
1115 uint32 rid;
1116 enum lsa_SidType type;
1118 if (argc == 0) {
1119 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1120 ctx->whoami);
1121 return NT_STATUS_INVALID_PARAMETER;
1124 ZERO_STRUCT(connect_pol);
1125 ZERO_STRUCT(domain_pol);
1126 ZERO_STRUCT(user_pol);
1128 result = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1129 argv[0], NULL, NULL, &sid, &type);
1130 if (!NT_STATUS_IS_OK(result)) {
1131 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1132 nt_errstr(result));
1133 goto done;
1136 if (type != SID_NAME_USER) {
1137 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1138 sid_type_lookup(type));
1139 result = NT_STATUS_NO_SUCH_USER;
1140 goto done;
1143 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1144 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1145 result = NT_STATUS_NO_SUCH_USER;
1146 goto done;
1149 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1150 pipe_hnd->desthost,
1151 MAXIMUM_ALLOWED_ACCESS,
1152 &connect_pol);
1153 if (!NT_STATUS_IS_OK(result)) {
1154 goto done;
1157 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1158 &connect_pol,
1159 MAXIMUM_ALLOWED_ACCESS,
1160 ctx->domain_sid,
1161 &domain_pol);
1162 if (!NT_STATUS_IS_OK(result)) {
1163 goto done;
1166 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1167 &domain_pol,
1168 MAXIMUM_ALLOWED_ACCESS,
1169 rid,
1170 &user_pol);
1171 if (!NT_STATUS_IS_OK(result)) {
1172 goto done;
1175 result = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1177 done:
1178 if (is_valid_policy_hnd(&user_pol)) {
1179 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1181 if (is_valid_policy_hnd(&domain_pol)) {
1182 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
1184 if (is_valid_policy_hnd(&connect_pol)) {
1185 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1187 return result;
1190 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1191 TALLOC_CTX *mem_ctx,
1192 struct rpc_sh_ctx *ctx,
1193 struct rpc_pipe_client *pipe_hnd,
1194 struct policy_handle *user_hnd,
1195 int argc, const char **argv)
1197 NTSTATUS result;
1198 union samr_UserInfo *info = NULL;
1200 if (argc != 0) {
1201 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1202 ctx->whoami);
1203 return NT_STATUS_INVALID_PARAMETER;
1206 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1207 user_hnd,
1209 &info);
1210 if (!NT_STATUS_IS_OK(result)) {
1211 return result;
1214 d_printf(_("user rid: %d, group rid: %d\n"),
1215 info->info21.rid,
1216 info->info21.primary_gid);
1218 return result;
1221 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1222 TALLOC_CTX *mem_ctx,
1223 struct rpc_sh_ctx *ctx,
1224 struct rpc_pipe_client *pipe_hnd,
1225 int argc, const char **argv)
1227 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1228 rpc_sh_user_show_internals);
1231 #define FETCHSTR(name, rec) \
1232 do { if (strequal(ctx->thiscmd, name)) { \
1233 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1234 } while (0);
1236 #define SETSTR(name, rec, flag) \
1237 do { if (strequal(ctx->thiscmd, name)) { \
1238 init_lsa_String(&(info->info21.rec), argv[0]); \
1239 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1240 } while (0);
1242 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1243 TALLOC_CTX *mem_ctx,
1244 struct rpc_sh_ctx *ctx,
1245 struct rpc_pipe_client *pipe_hnd,
1246 struct policy_handle *user_hnd,
1247 int argc, const char **argv)
1249 NTSTATUS result;
1250 const char *username;
1251 const char *oldval = "";
1252 union samr_UserInfo *info = NULL;
1254 if (argc > 1) {
1255 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1256 _("Usage:"), ctx->whoami);
1257 return NT_STATUS_INVALID_PARAMETER;
1260 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1261 user_hnd,
1263 &info);
1264 if (!NT_STATUS_IS_OK(result)) {
1265 return result;
1268 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1270 FETCHSTR("fullname", full_name);
1271 FETCHSTR("homedir", home_directory);
1272 FETCHSTR("homedrive", home_drive);
1273 FETCHSTR("logonscript", logon_script);
1274 FETCHSTR("profilepath", profile_path);
1275 FETCHSTR("description", description);
1277 if (argc == 0) {
1278 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1279 goto done;
1282 if (strcmp(argv[0], "NULL") == 0) {
1283 argv[0] = "";
1286 ZERO_STRUCT(info->info21);
1288 SETSTR("fullname", full_name, FULL_NAME);
1289 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1290 SETSTR("homedrive", home_drive, HOME_DRIVE);
1291 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1292 SETSTR("profilepath", profile_path, PROFILE_PATH);
1293 SETSTR("description", description, DESCRIPTION);
1295 result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1296 user_hnd,
1298 info);
1300 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1301 ctx->thiscmd, oldval, argv[0]);
1303 done:
1305 return result;
1308 #define HANDLEFLG(name, rec) \
1309 do { if (strequal(ctx->thiscmd, name)) { \
1310 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1311 if (newval) { \
1312 newflags = oldflags | ACB_##rec; \
1313 } else { \
1314 newflags = oldflags & ~ACB_##rec; \
1315 } } } while (0);
1317 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1318 TALLOC_CTX *mem_ctx,
1319 struct rpc_sh_ctx *ctx,
1320 struct rpc_pipe_client *pipe_hnd,
1321 int argc, const char **argv)
1323 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1324 rpc_sh_user_str_edit_internals);
1327 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1328 TALLOC_CTX *mem_ctx,
1329 struct rpc_sh_ctx *ctx,
1330 struct rpc_pipe_client *pipe_hnd,
1331 struct policy_handle *user_hnd,
1332 int argc, const char **argv)
1334 NTSTATUS result;
1335 const char *username;
1336 const char *oldval = "unknown";
1337 uint32 oldflags, newflags;
1338 bool newval;
1339 union samr_UserInfo *info = NULL;
1341 if ((argc > 1) ||
1342 ((argc == 1) && !strequal(argv[0], "yes") &&
1343 !strequal(argv[0], "no"))) {
1344 /* TRANSATORS: The yes|no here are program keywords. Please do
1345 not translate. */
1346 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1347 ctx->whoami);
1348 return NT_STATUS_INVALID_PARAMETER;
1351 newval = strequal(argv[0], "yes");
1353 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1354 user_hnd,
1356 &info);
1357 if (!NT_STATUS_IS_OK(result)) {
1358 return result;
1361 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1362 oldflags = info->info21.acct_flags;
1363 newflags = info->info21.acct_flags;
1365 HANDLEFLG("disabled", DISABLED);
1366 HANDLEFLG("pwnotreq", PWNOTREQ);
1367 HANDLEFLG("autolock", AUTOLOCK);
1368 HANDLEFLG("pwnoexp", PWNOEXP);
1370 if (argc == 0) {
1371 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1372 oldval);
1373 goto done;
1376 ZERO_STRUCT(info->info21);
1378 info->info21.acct_flags = newflags;
1379 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1381 result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1382 user_hnd,
1384 info);
1386 if (NT_STATUS_IS_OK(result)) {
1387 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1388 ctx->thiscmd, oldval, argv[0]);
1391 done:
1393 return result;
1396 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1397 TALLOC_CTX *mem_ctx,
1398 struct rpc_sh_ctx *ctx,
1399 struct rpc_pipe_client *pipe_hnd,
1400 int argc, const char **argv)
1402 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1403 rpc_sh_user_flag_edit_internals);
1406 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1407 TALLOC_CTX *mem_ctx,
1408 struct rpc_sh_ctx *ctx)
1410 static struct rpc_sh_cmd cmds[] = {
1412 { "fullname", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1413 N_("Show/Set a user's full name") },
1415 { "homedir", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1416 N_("Show/Set a user's home directory") },
1418 { "homedrive", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1419 N_("Show/Set a user's home drive") },
1421 { "logonscript", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1422 N_("Show/Set a user's logon script") },
1424 { "profilepath", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1425 N_("Show/Set a user's profile path") },
1427 { "description", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1428 N_("Show/Set a user's description") },
1430 { "disabled", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1431 N_("Show/Set whether a user is disabled") },
1433 { "autolock", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1434 N_("Show/Set whether a user locked out") },
1436 { "pwnotreq", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1437 N_("Show/Set whether a user does not need a password") },
1439 { "pwnoexp", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1440 N_("Show/Set whether a user's password does not expire") },
1442 { NULL, NULL, 0, NULL, NULL }
1445 return cmds;
1448 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1449 TALLOC_CTX *mem_ctx,
1450 struct rpc_sh_ctx *ctx)
1452 static struct rpc_sh_cmd cmds[] = {
1454 { "list", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_list,
1455 N_("List available users") },
1457 { "info", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_info,
1458 N_("List the domain groups a user is member of") },
1460 { "show", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_show,
1461 N_("Show info about a user") },
1463 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1464 N_("Show/Modify a user's fields") },
1466 { NULL, NULL, 0, NULL, NULL }
1469 return cmds;
1472 /****************************************************************************/
1475 * Basic usage function for 'net rpc group'.
1476 * @param argc Standard main() style argc.
1477 * @param argv Standard main() style argv. Initial components are already
1478 * stripped.
1481 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1483 return net_group_usage(c, argc, argv);
1487 * Delete group on a remote RPC server.
1489 * All parameters are provided by the run_rpc_command function, except for
1490 * argc, argv which are passed through.
1492 * @param domain_sid The domain sid acquired from the remote server.
1493 * @param cli A cli_state connected to the server.
1494 * @param mem_ctx Talloc context, destroyed on completion of the function.
1495 * @param argc Standard main() style argc.
1496 * @param argv Standard main() style argv. Initial components are already
1497 * stripped.
1499 * @return Normal NTSTATUS return.
1502 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1503 const struct dom_sid *domain_sid,
1504 const char *domain_name,
1505 struct cli_state *cli,
1506 struct rpc_pipe_client *pipe_hnd,
1507 TALLOC_CTX *mem_ctx,
1508 int argc,
1509 const char **argv)
1511 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1512 bool group_is_primary = false;
1513 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1514 uint32_t group_rid;
1515 struct samr_RidAttrArray *rids = NULL;
1516 /* char **names; */
1517 int i;
1518 /* struct samr_RidWithAttribute *user_gids; */
1520 struct samr_Ids group_rids, name_types;
1521 struct lsa_String lsa_acct_name;
1522 union samr_UserInfo *info = NULL;
1524 if (argc < 1 || c->display_usage) {
1525 rpc_group_usage(c, argc,argv);
1526 return NT_STATUS_OK; /* ok? */
1529 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1530 pipe_hnd->desthost,
1531 MAXIMUM_ALLOWED_ACCESS,
1532 &connect_pol);
1534 if (!NT_STATUS_IS_OK(result)) {
1535 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1536 goto done;
1539 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1540 &connect_pol,
1541 MAXIMUM_ALLOWED_ACCESS,
1542 CONST_DISCARD(struct dom_sid2 *, domain_sid),
1543 &domain_pol);
1545 if (!NT_STATUS_IS_OK(result)) {
1546 d_fprintf(stderr, _("Request open_domain failed\n"));
1547 goto done;
1550 init_lsa_String(&lsa_acct_name, argv[0]);
1552 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1553 &domain_pol,
1555 &lsa_acct_name,
1556 &group_rids,
1557 &name_types);
1558 if (!NT_STATUS_IS_OK(result)) {
1559 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1560 goto done;
1563 switch (name_types.ids[0])
1565 case SID_NAME_DOM_GRP:
1566 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1567 &domain_pol,
1568 MAXIMUM_ALLOWED_ACCESS,
1569 group_rids.ids[0],
1570 &group_pol);
1571 if (!NT_STATUS_IS_OK(result)) {
1572 d_fprintf(stderr, _("Request open_group failed"));
1573 goto done;
1576 group_rid = group_rids.ids[0];
1578 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
1579 &group_pol,
1580 &rids);
1582 if (!NT_STATUS_IS_OK(result)) {
1583 d_fprintf(stderr,
1584 _("Unable to query group members of %s"),
1585 argv[0]);
1586 goto done;
1589 if (c->opt_verbose) {
1590 d_printf(
1591 _("Domain Group %s (rid: %d) has %d members\n"),
1592 argv[0],group_rid, rids->count);
1595 /* Check if group is anyone's primary group */
1596 for (i = 0; i < rids->count; i++)
1598 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1599 &domain_pol,
1600 MAXIMUM_ALLOWED_ACCESS,
1601 rids->rids[i],
1602 &user_pol);
1604 if (!NT_STATUS_IS_OK(result)) {
1605 d_fprintf(stderr,
1606 _("Unable to open group member %d\n"),
1607 rids->rids[i]);
1608 goto done;
1611 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1612 &user_pol,
1614 &info);
1616 if (!NT_STATUS_IS_OK(result)) {
1617 d_fprintf(stderr,
1618 _("Unable to lookup userinfo for group "
1619 "member %d\n"),
1620 rids->rids[i]);
1621 goto done;
1624 if (info->info21.primary_gid == group_rid) {
1625 if (c->opt_verbose) {
1626 d_printf(_("Group is primary group "
1627 "of %s\n"),
1628 info->info21.account_name.string);
1630 group_is_primary = true;
1633 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1636 if (group_is_primary) {
1637 d_fprintf(stderr, _("Unable to delete group because "
1638 "some of it's members have it as primary "
1639 "group\n"));
1640 result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1641 goto done;
1644 /* remove all group members */
1645 for (i = 0; i < rids->count; i++)
1647 if (c->opt_verbose)
1648 d_printf(_("Remove group member %d..."),
1649 rids->rids[i]);
1650 result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
1651 &group_pol,
1652 rids->rids[i]);
1654 if (NT_STATUS_IS_OK(result)) {
1655 if (c->opt_verbose)
1656 d_printf(_("ok\n"));
1657 } else {
1658 if (c->opt_verbose)
1659 d_printf("%s\n", _("failed"));
1660 goto done;
1664 result = rpccli_samr_DeleteDomainGroup(pipe_hnd, mem_ctx,
1665 &group_pol);
1667 break;
1668 /* removing a local group is easier... */
1669 case SID_NAME_ALIAS:
1670 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1671 &domain_pol,
1672 MAXIMUM_ALLOWED_ACCESS,
1673 group_rids.ids[0],
1674 &group_pol);
1676 if (!NT_STATUS_IS_OK(result)) {
1677 d_fprintf(stderr, _("Request open_alias failed\n"));
1678 goto done;
1681 result = rpccli_samr_DeleteDomAlias(pipe_hnd, mem_ctx,
1682 &group_pol);
1683 break;
1684 default:
1685 d_fprintf(stderr, _("%s is of type %s. This command is only "
1686 "for deleting local or global groups\n"),
1687 argv[0],sid_type_lookup(name_types.ids[0]));
1688 result = NT_STATUS_UNSUCCESSFUL;
1689 goto done;
1692 if (NT_STATUS_IS_OK(result)) {
1693 if (c->opt_verbose)
1694 d_printf(_("Deleted %s '%s'\n"),
1695 sid_type_lookup(name_types.ids[0]), argv[0]);
1696 } else {
1697 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
1698 get_friendly_nt_error_msg(result));
1701 done:
1702 return result;
1706 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1708 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1709 rpc_group_delete_internals, argc,argv);
1712 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1714 NET_API_STATUS status;
1715 struct GROUP_INFO_1 info1;
1716 uint32_t parm_error = 0;
1718 if (argc != 1 || c->display_usage) {
1719 rpc_group_usage(c, argc, argv);
1720 return 0;
1723 ZERO_STRUCT(info1);
1725 info1.grpi1_name = argv[0];
1726 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1727 info1.grpi1_comment = c->opt_comment;
1730 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1732 if (status != 0) {
1733 d_fprintf(stderr,
1734 _("Failed to add group '%s' with error: %s.\n"),
1735 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1736 status));
1737 return -1;
1738 } else {
1739 d_printf(_("Added group '%s'.\n"), argv[0]);
1742 return 0;
1745 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
1747 NET_API_STATUS status;
1748 struct LOCALGROUP_INFO_1 info1;
1749 uint32_t parm_error = 0;
1751 if (argc != 1 || c->display_usage) {
1752 rpc_group_usage(c, argc, argv);
1753 return 0;
1756 ZERO_STRUCT(info1);
1758 info1.lgrpi1_name = argv[0];
1759 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1760 info1.lgrpi1_comment = c->opt_comment;
1763 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1765 if (status != 0) {
1766 d_fprintf(stderr,
1767 _("Failed to add alias '%s' with error: %s.\n"),
1768 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1769 status));
1770 return -1;
1771 } else {
1772 d_printf(_("Added alias '%s'.\n"), argv[0]);
1775 return 0;
1778 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1780 if (c->opt_localgroup)
1781 return rpc_alias_add_internals(c, argc, argv);
1783 return rpc_group_add_internals(c, argc, argv);
1786 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1787 TALLOC_CTX *mem_ctx,
1788 const char *name,
1789 struct dom_sid *sid,
1790 enum lsa_SidType *type)
1792 struct dom_sid *sids = NULL;
1793 enum lsa_SidType *types = NULL;
1794 struct rpc_pipe_client *pipe_hnd = NULL;
1795 struct policy_handle lsa_pol;
1796 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1798 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1799 &pipe_hnd);
1800 if (!NT_STATUS_IS_OK(result)) {
1801 goto done;
1804 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1805 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1807 if (!NT_STATUS_IS_OK(result)) {
1808 goto done;
1811 result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1812 &name, NULL, 1, &sids, &types);
1814 if (NT_STATUS_IS_OK(result)) {
1815 sid_copy(sid, &sids[0]);
1816 *type = types[0];
1819 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
1821 done:
1822 if (pipe_hnd) {
1823 TALLOC_FREE(pipe_hnd);
1826 if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
1828 /* Try as S-1-5-whatever */
1830 struct dom_sid tmp_sid;
1832 if (string_to_sid(&tmp_sid, name)) {
1833 sid_copy(sid, &tmp_sid);
1834 *type = SID_NAME_UNKNOWN;
1835 result = NT_STATUS_OK;
1839 return result;
1842 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
1843 TALLOC_CTX *mem_ctx,
1844 const struct dom_sid *group_sid,
1845 const char *member)
1847 struct policy_handle connect_pol, domain_pol;
1848 NTSTATUS result;
1849 uint32 group_rid;
1850 struct policy_handle group_pol;
1852 struct samr_Ids rids, rid_types;
1853 struct lsa_String lsa_acct_name;
1855 struct dom_sid sid;
1857 sid_copy(&sid, group_sid);
1859 if (!sid_split_rid(&sid, &group_rid)) {
1860 return NT_STATUS_UNSUCCESSFUL;
1863 /* Get sam policy handle */
1864 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1865 pipe_hnd->desthost,
1866 MAXIMUM_ALLOWED_ACCESS,
1867 &connect_pol);
1868 if (!NT_STATUS_IS_OK(result)) {
1869 return result;
1872 /* Get domain policy handle */
1873 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1874 &connect_pol,
1875 MAXIMUM_ALLOWED_ACCESS,
1876 &sid,
1877 &domain_pol);
1878 if (!NT_STATUS_IS_OK(result)) {
1879 return result;
1882 init_lsa_String(&lsa_acct_name, member);
1884 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1885 &domain_pol,
1887 &lsa_acct_name,
1888 &rids,
1889 &rid_types);
1891 if (!NT_STATUS_IS_OK(result)) {
1892 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
1893 member);
1894 goto done;
1897 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1898 &domain_pol,
1899 MAXIMUM_ALLOWED_ACCESS,
1900 group_rid,
1901 &group_pol);
1903 if (!NT_STATUS_IS_OK(result)) {
1904 goto done;
1907 result = rpccli_samr_AddGroupMember(pipe_hnd, mem_ctx,
1908 &group_pol,
1909 rids.ids[0],
1910 0x0005); /* unknown flags */
1912 done:
1913 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1914 return result;
1917 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
1918 TALLOC_CTX *mem_ctx,
1919 const struct dom_sid *alias_sid,
1920 const char *member)
1922 struct policy_handle connect_pol, domain_pol;
1923 NTSTATUS result;
1924 uint32 alias_rid;
1925 struct policy_handle alias_pol;
1927 struct dom_sid member_sid;
1928 enum lsa_SidType member_type;
1930 struct dom_sid sid;
1932 sid_copy(&sid, alias_sid);
1934 if (!sid_split_rid(&sid, &alias_rid)) {
1935 return NT_STATUS_UNSUCCESSFUL;
1938 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
1939 member, &member_sid, &member_type);
1941 if (!NT_STATUS_IS_OK(result)) {
1942 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
1943 member);
1944 return result;
1947 /* Get sam policy handle */
1948 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1949 pipe_hnd->desthost,
1950 MAXIMUM_ALLOWED_ACCESS,
1951 &connect_pol);
1952 if (!NT_STATUS_IS_OK(result)) {
1953 goto done;
1956 /* Get domain policy handle */
1957 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1958 &connect_pol,
1959 MAXIMUM_ALLOWED_ACCESS,
1960 &sid,
1961 &domain_pol);
1962 if (!NT_STATUS_IS_OK(result)) {
1963 goto done;
1966 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1967 &domain_pol,
1968 MAXIMUM_ALLOWED_ACCESS,
1969 alias_rid,
1970 &alias_pol);
1972 if (!NT_STATUS_IS_OK(result)) {
1973 return result;
1976 result = rpccli_samr_AddAliasMember(pipe_hnd, mem_ctx,
1977 &alias_pol,
1978 &member_sid);
1980 if (!NT_STATUS_IS_OK(result)) {
1981 return result;
1984 done:
1985 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1986 return result;
1989 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
1990 const struct dom_sid *domain_sid,
1991 const char *domain_name,
1992 struct cli_state *cli,
1993 struct rpc_pipe_client *pipe_hnd,
1994 TALLOC_CTX *mem_ctx,
1995 int argc,
1996 const char **argv)
1998 struct dom_sid group_sid;
1999 enum lsa_SidType group_type;
2001 if (argc != 2 || c->display_usage) {
2002 d_printf("%s\n%s",
2003 _("Usage:"),
2004 _("net rpc group addmem <group> <member>\n"
2005 " Add a member to a group\n"
2006 " group\tGroup to add member to\n"
2007 " member\tMember to add to group\n"));
2008 return NT_STATUS_UNSUCCESSFUL;
2011 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2012 &group_sid, &group_type))) {
2013 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2014 argv[0]);
2015 return NT_STATUS_UNSUCCESSFUL;
2018 if (group_type == SID_NAME_DOM_GRP) {
2019 NTSTATUS result = rpc_add_groupmem(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 if (group_type == SID_NAME_ALIAS) {
2030 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2031 &group_sid, argv[1]);
2033 if (!NT_STATUS_IS_OK(result)) {
2034 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2035 argv[1], argv[0], nt_errstr(result));
2037 return result;
2040 d_fprintf(stderr, _("Can only add members to global or local groups "
2041 "which %s is not\n"), argv[0]);
2043 return NT_STATUS_UNSUCCESSFUL;
2046 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2048 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2049 rpc_group_addmem_internals,
2050 argc, argv);
2053 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2054 struct rpc_pipe_client *pipe_hnd,
2055 TALLOC_CTX *mem_ctx,
2056 const struct dom_sid *group_sid,
2057 const char *member)
2059 struct policy_handle connect_pol, domain_pol;
2060 NTSTATUS result;
2061 uint32 group_rid;
2062 struct policy_handle group_pol;
2064 struct samr_Ids rids, rid_types;
2065 struct lsa_String lsa_acct_name;
2067 struct dom_sid sid;
2069 sid_copy(&sid, group_sid);
2071 if (!sid_split_rid(&sid, &group_rid))
2072 return NT_STATUS_UNSUCCESSFUL;
2074 /* Get sam policy handle */
2075 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2076 pipe_hnd->desthost,
2077 MAXIMUM_ALLOWED_ACCESS,
2078 &connect_pol);
2079 if (!NT_STATUS_IS_OK(result))
2080 return result;
2082 /* Get domain policy handle */
2083 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2084 &connect_pol,
2085 MAXIMUM_ALLOWED_ACCESS,
2086 &sid,
2087 &domain_pol);
2088 if (!NT_STATUS_IS_OK(result))
2089 return result;
2091 init_lsa_String(&lsa_acct_name, member);
2093 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2094 &domain_pol,
2096 &lsa_acct_name,
2097 &rids,
2098 &rid_types);
2099 if (!NT_STATUS_IS_OK(result)) {
2100 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2101 member);
2102 goto done;
2105 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2106 &domain_pol,
2107 MAXIMUM_ALLOWED_ACCESS,
2108 group_rid,
2109 &group_pol);
2111 if (!NT_STATUS_IS_OK(result))
2112 goto done;
2114 result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
2115 &group_pol,
2116 rids.ids[0]);
2118 done:
2119 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2120 return result;
2123 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2124 TALLOC_CTX *mem_ctx,
2125 const struct dom_sid *alias_sid,
2126 const char *member)
2128 struct policy_handle connect_pol, domain_pol;
2129 NTSTATUS result;
2130 uint32 alias_rid;
2131 struct policy_handle alias_pol;
2133 struct dom_sid member_sid;
2134 enum lsa_SidType member_type;
2136 struct dom_sid sid;
2138 sid_copy(&sid, alias_sid);
2140 if (!sid_split_rid(&sid, &alias_rid))
2141 return NT_STATUS_UNSUCCESSFUL;
2143 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2144 member, &member_sid, &member_type);
2146 if (!NT_STATUS_IS_OK(result)) {
2147 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2148 member);
2149 return result;
2152 /* Get sam policy handle */
2153 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2154 pipe_hnd->desthost,
2155 MAXIMUM_ALLOWED_ACCESS,
2156 &connect_pol);
2157 if (!NT_STATUS_IS_OK(result)) {
2158 goto done;
2161 /* Get domain policy handle */
2162 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2163 &connect_pol,
2164 MAXIMUM_ALLOWED_ACCESS,
2165 &sid,
2166 &domain_pol);
2167 if (!NT_STATUS_IS_OK(result)) {
2168 goto done;
2171 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2172 &domain_pol,
2173 MAXIMUM_ALLOWED_ACCESS,
2174 alias_rid,
2175 &alias_pol);
2177 if (!NT_STATUS_IS_OK(result))
2178 return result;
2180 result = rpccli_samr_DeleteAliasMember(pipe_hnd, mem_ctx,
2181 &alias_pol,
2182 &member_sid);
2184 if (!NT_STATUS_IS_OK(result))
2185 return result;
2187 done:
2188 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2189 return result;
2192 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2193 const struct dom_sid *domain_sid,
2194 const char *domain_name,
2195 struct cli_state *cli,
2196 struct rpc_pipe_client *pipe_hnd,
2197 TALLOC_CTX *mem_ctx,
2198 int argc,
2199 const char **argv)
2201 struct dom_sid group_sid;
2202 enum lsa_SidType group_type;
2204 if (argc != 2 || c->display_usage) {
2205 d_printf("%s\n%s",
2206 _("Usage:"),
2207 _("net rpc group delmem <group> <member>\n"
2208 " Delete a member from a group\n"
2209 " group\tGroup to delete member from\n"
2210 " member\tMember to delete from group\n"));
2211 return NT_STATUS_UNSUCCESSFUL;
2214 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2215 &group_sid, &group_type))) {
2216 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2217 argv[0]);
2218 return NT_STATUS_UNSUCCESSFUL;
2221 if (group_type == SID_NAME_DOM_GRP) {
2222 NTSTATUS result = rpc_del_groupmem(c, 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 if (group_type == SID_NAME_ALIAS) {
2233 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2234 &group_sid, argv[1]);
2236 if (!NT_STATUS_IS_OK(result)) {
2237 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2238 argv[1], argv[0], nt_errstr(result));
2240 return result;
2243 d_fprintf(stderr, _("Can only delete members from global or local "
2244 "groups which %s is not\n"), argv[0]);
2246 return NT_STATUS_UNSUCCESSFUL;
2249 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2251 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2252 rpc_group_delmem_internals,
2253 argc, argv);
2257 * List groups on a remote RPC server.
2259 * All parameters are provided by the run_rpc_command function, except for
2260 * argc, argv which are passes through.
2262 * @param domain_sid The domain sid acquired from the remote server.
2263 * @param cli A cli_state connected to the server.
2264 * @param mem_ctx Talloc context, destroyed on completion of the function.
2265 * @param argc Standard main() style argc.
2266 * @param argv Standard main() style argv. Initial components are already
2267 * stripped.
2269 * @return Normal NTSTATUS return.
2272 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2273 const struct dom_sid *domain_sid,
2274 const char *domain_name,
2275 struct cli_state *cli,
2276 struct rpc_pipe_client *pipe_hnd,
2277 TALLOC_CTX *mem_ctx,
2278 int argc,
2279 const char **argv)
2281 struct policy_handle connect_pol, domain_pol;
2282 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2283 uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2284 struct samr_SamArray *groups = NULL;
2285 bool global = false;
2286 bool local = false;
2287 bool builtin = false;
2289 if (c->display_usage) {
2290 d_printf("%s\n%s",
2291 _("Usage:"),
2292 _("net rpc group list [global] [local] [builtin]\n"
2293 " List groups on RPC server\n"
2294 " global\tList global groups\n"
2295 " local\tList local groups\n"
2296 " builtin\tList builtin groups\n"
2297 " If none of global, local or builtin is "
2298 "specified, all three options are considered "
2299 "set\n"));
2300 return NT_STATUS_OK;
2303 if (argc == 0) {
2304 global = true;
2305 local = true;
2306 builtin = true;
2309 for (i=0; i<argc; i++) {
2310 if (strequal(argv[i], "global"))
2311 global = true;
2313 if (strequal(argv[i], "local"))
2314 local = true;
2316 if (strequal(argv[i], "builtin"))
2317 builtin = true;
2320 /* Get sam policy handle */
2322 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2323 pipe_hnd->desthost,
2324 MAXIMUM_ALLOWED_ACCESS,
2325 &connect_pol);
2326 if (!NT_STATUS_IS_OK(result)) {
2327 goto done;
2330 /* Get domain policy handle */
2332 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2333 &connect_pol,
2334 MAXIMUM_ALLOWED_ACCESS,
2335 CONST_DISCARD(struct dom_sid2 *, domain_sid),
2336 &domain_pol);
2337 if (!NT_STATUS_IS_OK(result)) {
2338 goto done;
2341 /* Query domain groups */
2342 if (c->opt_long_list_entries)
2343 d_printf(_("\nGroup name Comment"
2344 "\n-----------------------------\n"));
2345 do {
2346 uint32_t max_size, total_size, returned_size;
2347 union samr_DispInfo info;
2349 if (!global) break;
2351 get_query_dispinfo_params(
2352 loop_count, &max_entries, &max_size);
2354 result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
2355 &domain_pol,
2357 start_idx,
2358 max_entries,
2359 max_size,
2360 &total_size,
2361 &returned_size,
2362 &info);
2363 num_entries = info.info3.count;
2364 start_idx += info.info3.count;
2366 if (!NT_STATUS_IS_OK(result) &&
2367 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2368 break;
2370 for (i = 0; i < num_entries; i++) {
2372 const char *group = NULL;
2373 const char *desc = NULL;
2375 group = info.info3.entries[i].account_name.string;
2376 desc = info.info3.entries[i].description.string;
2378 if (c->opt_long_list_entries)
2379 printf("%-21.21s %-50.50s\n",
2380 group, desc);
2381 else
2382 printf("%s\n", group);
2384 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2385 /* query domain aliases */
2386 start_idx = 0;
2387 do {
2388 if (!local) break;
2390 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2391 &domain_pol,
2392 &start_idx,
2393 &groups,
2394 0xffff,
2395 &num_entries);
2396 if (!NT_STATUS_IS_OK(result) &&
2397 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2398 break;
2400 for (i = 0; i < num_entries; i++) {
2402 const char *description = NULL;
2404 if (c->opt_long_list_entries) {
2406 struct policy_handle alias_pol;
2407 union samr_AliasInfo *info = NULL;
2409 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2410 &domain_pol,
2411 0x8,
2412 groups->entries[i].idx,
2413 &alias_pol))) &&
2414 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2415 &alias_pol,
2417 &info))) &&
2418 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2419 &alias_pol)))) {
2420 description = info->description.string;
2424 if (description != NULL) {
2425 printf("%-21.21s %-50.50s\n",
2426 groups->entries[i].name.string,
2427 description);
2428 } else {
2429 printf("%s\n", groups->entries[i].name.string);
2432 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2433 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2434 /* Get builtin policy handle */
2436 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2437 &connect_pol,
2438 MAXIMUM_ALLOWED_ACCESS,
2439 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2440 &domain_pol);
2441 if (!NT_STATUS_IS_OK(result)) {
2442 goto done;
2444 /* query builtin aliases */
2445 start_idx = 0;
2446 do {
2447 if (!builtin) break;
2449 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2450 &domain_pol,
2451 &start_idx,
2452 &groups,
2453 max_entries,
2454 &num_entries);
2455 if (!NT_STATUS_IS_OK(result) &&
2456 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2457 break;
2459 for (i = 0; i < num_entries; i++) {
2461 const char *description = NULL;
2463 if (c->opt_long_list_entries) {
2465 struct policy_handle alias_pol;
2466 union samr_AliasInfo *info = NULL;
2468 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2469 &domain_pol,
2470 0x8,
2471 groups->entries[i].idx,
2472 &alias_pol))) &&
2473 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2474 &alias_pol,
2476 &info))) &&
2477 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2478 &alias_pol)))) {
2479 description = info->description.string;
2483 if (description != NULL) {
2484 printf("%-21.21s %-50.50s\n",
2485 groups->entries[i].name.string,
2486 description);
2487 } else {
2488 printf("%s\n", groups->entries[i].name.string);
2491 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2493 done:
2494 return result;
2497 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2499 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2500 rpc_group_list_internals,
2501 argc, argv);
2504 static NTSTATUS rpc_list_group_members(struct net_context *c,
2505 struct rpc_pipe_client *pipe_hnd,
2506 TALLOC_CTX *mem_ctx,
2507 const char *domain_name,
2508 const struct dom_sid *domain_sid,
2509 struct policy_handle *domain_pol,
2510 uint32 rid)
2512 NTSTATUS result;
2513 struct policy_handle group_pol;
2514 uint32 num_members, *group_rids;
2515 int i;
2516 struct samr_RidAttrArray *rids = NULL;
2517 struct lsa_Strings names;
2518 struct samr_Ids types;
2520 fstring sid_str;
2521 sid_to_fstring(sid_str, domain_sid);
2523 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2524 domain_pol,
2525 MAXIMUM_ALLOWED_ACCESS,
2526 rid,
2527 &group_pol);
2529 if (!NT_STATUS_IS_OK(result))
2530 return result;
2532 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
2533 &group_pol,
2534 &rids);
2536 if (!NT_STATUS_IS_OK(result))
2537 return result;
2539 num_members = rids->count;
2540 group_rids = rids->rids;
2542 while (num_members > 0) {
2543 int this_time = 512;
2545 if (num_members < this_time)
2546 this_time = num_members;
2548 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
2549 domain_pol,
2550 this_time,
2551 group_rids,
2552 &names,
2553 &types);
2555 if (!NT_STATUS_IS_OK(result))
2556 return result;
2558 /* We only have users as members, but make the output
2559 the same as the output of alias members */
2561 for (i = 0; i < this_time; i++) {
2563 if (c->opt_long_list_entries) {
2564 printf("%s-%d %s\\%s %d\n", sid_str,
2565 group_rids[i], domain_name,
2566 names.names[i].string,
2567 SID_NAME_USER);
2568 } else {
2569 printf("%s\\%s\n", domain_name,
2570 names.names[i].string);
2574 num_members -= this_time;
2575 group_rids += 512;
2578 return NT_STATUS_OK;
2581 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2582 struct rpc_pipe_client *pipe_hnd,
2583 TALLOC_CTX *mem_ctx,
2584 struct policy_handle *domain_pol,
2585 uint32 rid)
2587 NTSTATUS result;
2588 struct rpc_pipe_client *lsa_pipe;
2589 struct policy_handle alias_pol, lsa_pol;
2590 uint32 num_members;
2591 struct dom_sid *alias_sids;
2592 char **domains;
2593 char **names;
2594 enum lsa_SidType *types;
2595 int i;
2596 struct lsa_SidArray sid_array;
2598 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2599 domain_pol,
2600 MAXIMUM_ALLOWED_ACCESS,
2601 rid,
2602 &alias_pol);
2604 if (!NT_STATUS_IS_OK(result))
2605 return result;
2607 result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
2608 &alias_pol,
2609 &sid_array);
2611 if (!NT_STATUS_IS_OK(result)) {
2612 d_fprintf(stderr, _("Couldn't list alias members\n"));
2613 return result;
2616 num_members = sid_array.num_sids;
2618 if (num_members == 0) {
2619 return NT_STATUS_OK;
2622 result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2623 &ndr_table_lsarpc.syntax_id,
2624 &lsa_pipe);
2625 if (!NT_STATUS_IS_OK(result)) {
2626 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
2627 nt_errstr(result) );
2628 return result;
2631 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2632 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2634 if (!NT_STATUS_IS_OK(result)) {
2635 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
2636 TALLOC_FREE(lsa_pipe);
2637 return result;
2640 alias_sids = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, num_members);
2641 if (!alias_sids) {
2642 d_fprintf(stderr, _("Out of memory\n"));
2643 TALLOC_FREE(lsa_pipe);
2644 return NT_STATUS_NO_MEMORY;
2647 for (i=0; i<num_members; i++) {
2648 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2651 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
2652 num_members, alias_sids,
2653 &domains, &names, &types);
2655 if (!NT_STATUS_IS_OK(result) &&
2656 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2657 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
2658 TALLOC_FREE(lsa_pipe);
2659 return result;
2662 for (i = 0; i < num_members; i++) {
2663 fstring sid_str;
2664 sid_to_fstring(sid_str, &alias_sids[i]);
2666 if (c->opt_long_list_entries) {
2667 printf("%s %s\\%s %d\n", sid_str,
2668 domains[i] ? domains[i] : _("*unknown*"),
2669 names[i] ? names[i] : _("*unknown*"), types[i]);
2670 } else {
2671 if (domains[i])
2672 printf("%s\\%s\n", domains[i], names[i]);
2673 else
2674 printf("%s\n", sid_str);
2678 TALLOC_FREE(lsa_pipe);
2679 return NT_STATUS_OK;
2682 static NTSTATUS rpc_group_members_internals(struct net_context *c,
2683 const struct dom_sid *domain_sid,
2684 const char *domain_name,
2685 struct cli_state *cli,
2686 struct rpc_pipe_client *pipe_hnd,
2687 TALLOC_CTX *mem_ctx,
2688 int argc,
2689 const char **argv)
2691 NTSTATUS result;
2692 struct policy_handle connect_pol, domain_pol;
2693 struct samr_Ids rids, rid_types;
2694 struct lsa_String lsa_acct_name;
2696 /* Get sam policy handle */
2698 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2699 pipe_hnd->desthost,
2700 MAXIMUM_ALLOWED_ACCESS,
2701 &connect_pol);
2703 if (!NT_STATUS_IS_OK(result))
2704 return result;
2706 /* Get domain policy handle */
2708 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2709 &connect_pol,
2710 MAXIMUM_ALLOWED_ACCESS,
2711 CONST_DISCARD(struct dom_sid2 *, domain_sid),
2712 &domain_pol);
2714 if (!NT_STATUS_IS_OK(result))
2715 return result;
2717 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
2719 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2720 &domain_pol,
2722 &lsa_acct_name,
2723 &rids,
2724 &rid_types);
2726 if (!NT_STATUS_IS_OK(result)) {
2728 /* Ok, did not find it in the global sam, try with builtin */
2730 struct dom_sid sid_Builtin;
2732 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2734 sid_copy(&sid_Builtin, &global_sid_Builtin);
2736 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2737 &connect_pol,
2738 MAXIMUM_ALLOWED_ACCESS,
2739 &sid_Builtin,
2740 &domain_pol);
2742 if (!NT_STATUS_IS_OK(result)) {
2743 d_fprintf(stderr, _("Couldn't find group %s\n"),
2744 argv[0]);
2745 return result;
2748 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2749 &domain_pol,
2751 &lsa_acct_name,
2752 &rids,
2753 &rid_types);
2755 if (!NT_STATUS_IS_OK(result)) {
2756 d_fprintf(stderr, _("Couldn't find group %s\n"),
2757 argv[0]);
2758 return result;
2762 if (rids.count != 1) {
2763 d_fprintf(stderr, _("Couldn't find group %s\n"),
2764 argv[0]);
2765 return result;
2768 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
2769 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
2770 domain_sid, &domain_pol,
2771 rids.ids[0]);
2774 if (rid_types.ids[0] == SID_NAME_ALIAS) {
2775 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
2776 rids.ids[0]);
2779 return NT_STATUS_NO_SUCH_GROUP;
2782 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
2784 if (argc != 1 || c->display_usage) {
2785 return rpc_group_usage(c, argc, argv);
2788 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2789 rpc_group_members_internals,
2790 argc, argv);
2793 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
2795 NET_API_STATUS status;
2796 struct GROUP_INFO_0 g0;
2797 uint32_t parm_err;
2799 if (argc != 2) {
2800 d_printf(_("Usage:\n"));
2801 d_printf("net rpc group rename group newname\n");
2802 return -1;
2805 g0.grpi0_name = argv[1];
2807 status = NetGroupSetInfo(c->opt_host,
2808 argv[0],
2810 (uint8_t *)&g0,
2811 &parm_err);
2813 if (status != 0) {
2814 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
2815 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2816 status));
2817 return -1;
2820 return 0;
2823 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
2825 if (argc != 2 || c->display_usage) {
2826 return rpc_group_usage(c, argc, argv);
2829 return rpc_group_rename_internals(c, argc, argv);
2833 * 'net rpc group' entrypoint.
2834 * @param argc Standard main() style argc.
2835 * @param argv Standard main() style argv. Initial components are already
2836 * stripped.
2839 int net_rpc_group(struct net_context *c, int argc, const char **argv)
2841 NET_API_STATUS status;
2843 struct functable func[] = {
2845 "add",
2846 rpc_group_add,
2847 NET_TRANSPORT_RPC,
2848 N_("Create specified group"),
2849 N_("net rpc group add\n"
2850 " Create specified group")
2853 "delete",
2854 rpc_group_delete,
2855 NET_TRANSPORT_RPC,
2856 N_("Delete specified group"),
2857 N_("net rpc group delete\n"
2858 " Delete specified group")
2861 "addmem",
2862 rpc_group_addmem,
2863 NET_TRANSPORT_RPC,
2864 N_("Add member to group"),
2865 N_("net rpc group addmem\n"
2866 " Add member to group")
2869 "delmem",
2870 rpc_group_delmem,
2871 NET_TRANSPORT_RPC,
2872 N_("Remove member from group"),
2873 N_("net rpc group delmem\n"
2874 " Remove member from group")
2877 "list",
2878 rpc_group_list,
2879 NET_TRANSPORT_RPC,
2880 N_("List groups"),
2881 N_("net rpc group list\n"
2882 " List groups")
2885 "members",
2886 rpc_group_members,
2887 NET_TRANSPORT_RPC,
2888 N_("List group members"),
2889 N_("net rpc group members\n"
2890 " List group members")
2893 "rename",
2894 rpc_group_rename,
2895 NET_TRANSPORT_RPC,
2896 N_("Rename group"),
2897 N_("net rpc group rename\n"
2898 " Rename group")
2900 {NULL, NULL, 0, NULL, NULL}
2903 status = libnetapi_net_init(&c->netapi_ctx);
2904 if (status != 0) {
2905 return -1;
2907 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
2908 libnetapi_set_password(c->netapi_ctx, c->opt_password);
2909 if (c->opt_kerberos) {
2910 libnetapi_set_use_kerberos(c->netapi_ctx);
2913 if (argc == 0) {
2914 if (c->display_usage) {
2915 d_printf(_("Usage:\n"));
2916 d_printf(_("net rpc group\n"
2917 " Alias for net rpc group list global "
2918 "local builtin\n"));
2919 net_display_usage_from_functable(func);
2920 return 0;
2923 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2924 rpc_group_list_internals,
2925 argc, argv);
2928 return net_run_function(c, argc, argv, "net rpc group", func);
2931 /****************************************************************************/
2933 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
2935 return net_share_usage(c, argc, argv);
2939 * Add a share on a remote RPC server.
2941 * @param argc Standard main() style argc.
2942 * @param argv Standard main() style argv. Initial components are already
2943 * stripped.
2945 * @return A shell status integer (0 for success).
2948 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
2950 NET_API_STATUS status;
2951 char *sharename;
2952 char *path;
2953 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
2954 uint32 num_users=0, perms=0;
2955 char *password=NULL; /* don't allow a share password */
2956 struct SHARE_INFO_2 i2;
2957 uint32_t parm_error = 0;
2959 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
2960 return rpc_share_usage(c, argc, argv);
2963 if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
2964 return -1;
2967 path = strchr(sharename, '=');
2968 if (!path) {
2969 return -1;
2972 *path++ = '\0';
2974 i2.shi2_netname = sharename;
2975 i2.shi2_type = type;
2976 i2.shi2_remark = c->opt_comment;
2977 i2.shi2_permissions = perms;
2978 i2.shi2_max_uses = c->opt_maxusers;
2979 i2.shi2_current_uses = num_users;
2980 i2.shi2_path = path;
2981 i2.shi2_passwd = password;
2983 status = NetShareAdd(c->opt_host,
2985 (uint8_t *)&i2,
2986 &parm_error);
2987 if (status != 0) {
2988 printf(_("NetShareAdd failed with: %s\n"),
2989 libnetapi_get_error_string(c->netapi_ctx, status));
2992 return status;
2996 * Delete a share on a remote RPC server.
2998 * @param domain_sid The domain sid acquired from the remote server.
2999 * @param argc Standard main() style argc.
3000 * @param argv Standard main() style argv. Initial components are already
3001 * stripped.
3003 * @return A shell status integer (0 for success).
3005 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3007 if (argc < 1 || c->display_usage) {
3008 return rpc_share_usage(c, argc, argv);
3011 return NetShareDel(c->opt_host, argv[0], 0);
3015 * Formatted print of share info
3017 * @param r pointer to SHARE_INFO_1 to format
3020 static void display_share_info_1(struct net_context *c,
3021 struct SHARE_INFO_1 *r)
3023 if (c->opt_long_list_entries) {
3024 d_printf("%-12s %-8.8s %-50s\n",
3025 r->shi1_netname,
3026 net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3027 r->shi1_remark);
3028 } else {
3029 d_printf("%s\n", r->shi1_netname);
3033 static WERROR get_share_info(struct net_context *c,
3034 struct rpc_pipe_client *pipe_hnd,
3035 TALLOC_CTX *mem_ctx,
3036 uint32 level,
3037 int argc,
3038 const char **argv,
3039 struct srvsvc_NetShareInfoCtr *info_ctr)
3041 WERROR result;
3042 NTSTATUS status;
3043 union srvsvc_NetShareInfo info;
3045 /* no specific share requested, enumerate all */
3046 if (argc == 0) {
3048 uint32_t preferred_len = 0xffffffff;
3049 uint32_t total_entries = 0;
3050 uint32_t resume_handle = 0;
3052 info_ctr->level = level;
3054 status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, mem_ctx,
3055 pipe_hnd->desthost,
3056 info_ctr,
3057 preferred_len,
3058 &total_entries,
3059 &resume_handle,
3060 &result);
3061 return result;
3064 /* request just one share */
3065 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
3066 pipe_hnd->desthost,
3067 argv[0],
3068 level,
3069 &info,
3070 &result);
3072 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
3073 goto done;
3076 /* construct ctr */
3077 ZERO_STRUCTP(info_ctr);
3079 info_ctr->level = level;
3081 switch (level) {
3082 case 1:
3084 struct srvsvc_NetShareCtr1 *ctr1;
3086 ctr1 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr1);
3087 W_ERROR_HAVE_NO_MEMORY(ctr1);
3089 ctr1->count = 1;
3090 ctr1->array = info.info1;
3092 info_ctr->ctr.ctr1 = ctr1;
3094 case 2:
3096 struct srvsvc_NetShareCtr2 *ctr2;
3098 ctr2 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr2);
3099 W_ERROR_HAVE_NO_MEMORY(ctr2);
3101 ctr2->count = 1;
3102 ctr2->array = info.info2;
3104 info_ctr->ctr.ctr2 = ctr2;
3106 case 502:
3108 struct srvsvc_NetShareCtr502 *ctr502;
3110 ctr502 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr502);
3111 W_ERROR_HAVE_NO_MEMORY(ctr502);
3113 ctr502->count = 1;
3114 ctr502->array = info.info502;
3116 info_ctr->ctr.ctr502 = ctr502;
3118 } /* switch */
3119 done:
3120 return result;
3123 /***
3124 * 'net rpc share list' entrypoint.
3125 * @param argc Standard main() style argc.
3126 * @param argv Standard main() style argv. Initial components are already
3127 * stripped.
3129 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3131 NET_API_STATUS status;
3132 struct SHARE_INFO_1 *i1 = NULL;
3133 uint32_t entries_read = 0;
3134 uint32_t total_entries = 0;
3135 uint32_t resume_handle = 0;
3136 uint32_t i, level = 1;
3138 if (c->display_usage) {
3139 d_printf( "%s\n"
3140 "net rpc share list\n"
3141 " %s\n",
3142 _("Usage:"),
3143 _("List shares on remote server"));
3144 return 0;
3147 status = NetShareEnum(c->opt_host,
3148 level,
3149 (uint8_t **)(void *)&i1,
3150 (uint32_t)-1,
3151 &entries_read,
3152 &total_entries,
3153 &resume_handle);
3154 if (status != 0) {
3155 goto done;
3158 /* Display results */
3160 if (c->opt_long_list_entries) {
3161 d_printf(_(
3162 "\nEnumerating shared resources (exports) on remote server:\n\n"
3163 "\nShare name Type Description\n"
3164 "---------- ---- -----------\n"));
3166 for (i = 0; i < entries_read; i++)
3167 display_share_info_1(c, &i1[i]);
3168 done:
3169 return status;
3172 static bool check_share_availability(struct cli_state *cli, const char *netname)
3174 NTSTATUS status;
3176 status = cli_tcon_andx(cli, netname, "A:", "", 0);
3177 if (!NT_STATUS_IS_OK(status)) {
3178 d_printf(_("skipping [%s]: not a file share.\n"), netname);
3179 return false;
3182 status = cli_tdis(cli);
3183 if (!NT_STATUS_IS_OK(status)) {
3184 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3185 return false;
3188 return true;
3191 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3192 const char *netname, uint32 type)
3194 /* only support disk shares */
3195 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3196 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3197 type);
3198 return false;
3201 /* skip builtin shares */
3202 /* FIXME: should print$ be added too ? */
3203 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3204 strequal(netname,"global"))
3205 return false;
3207 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3208 printf(_("excluding [%s]\n"), netname);
3209 return false;
3212 return check_share_availability(cli, netname);
3216 * Migrate shares from a remote RPC server to the local RPC server.
3218 * All parameters are provided by the run_rpc_command function, except for
3219 * argc, argv which are passed through.
3221 * @param domain_sid The domain sid acquired from the remote server.
3222 * @param cli A cli_state connected to the server.
3223 * @param mem_ctx Talloc context, destroyed on completion of the function.
3224 * @param argc Standard main() style argc.
3225 * @param argv Standard main() style argv. Initial components are already
3226 * stripped.
3228 * @return Normal NTSTATUS return.
3231 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3232 const struct dom_sid *domain_sid,
3233 const char *domain_name,
3234 struct cli_state *cli,
3235 struct rpc_pipe_client *pipe_hnd,
3236 TALLOC_CTX *mem_ctx,
3237 int argc,
3238 const char **argv)
3240 WERROR result;
3241 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3242 struct srvsvc_NetShareInfoCtr ctr_src;
3243 uint32 i;
3244 struct rpc_pipe_client *srvsvc_pipe = NULL;
3245 struct cli_state *cli_dst = NULL;
3246 uint32 level = 502; /* includes secdesc */
3247 uint32_t parm_error = 0;
3249 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3250 &ctr_src);
3251 if (!W_ERROR_IS_OK(result))
3252 goto done;
3254 /* connect destination PI_SRVSVC */
3255 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3256 &ndr_table_srvsvc.syntax_id);
3257 if (!NT_STATUS_IS_OK(nt_status))
3258 return nt_status;
3261 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3263 union srvsvc_NetShareInfo info;
3264 struct srvsvc_NetShareInfo502 info502 =
3265 ctr_src.ctr.ctr502->array[i];
3267 /* reset error-code */
3268 nt_status = NT_STATUS_UNSUCCESSFUL;
3270 if (!check_share_sanity(c, cli, info502.name, info502.type))
3271 continue;
3273 /* finally add the share on the dst server */
3275 printf(_("migrating: [%s], path: %s, comment: %s, without "
3276 "share-ACLs\n"),
3277 info502.name, info502.path, info502.comment);
3279 info.info502 = &info502;
3281 nt_status = rpccli_srvsvc_NetShareAdd(srvsvc_pipe, mem_ctx,
3282 srvsvc_pipe->desthost,
3283 502,
3284 &info,
3285 &parm_error,
3286 &result);
3288 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3289 printf(_(" [%s] does already exist\n"),
3290 info502.name);
3291 continue;
3294 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3295 printf(_("cannot add share: %s\n"), win_errstr(result));
3296 goto done;
3301 nt_status = NT_STATUS_OK;
3303 done:
3304 if (cli_dst) {
3305 cli_shutdown(cli_dst);
3308 return nt_status;
3313 * Migrate shares from a RPC server to another.
3315 * @param argc Standard main() style argc.
3316 * @param argv Standard main() style argv. Initial components are already
3317 * stripped.
3319 * @return A shell status integer (0 for success).
3321 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3322 const char **argv)
3324 if (c->display_usage) {
3325 d_printf( "%s\n"
3326 "net rpc share migrate shares\n"
3327 " %s\n",
3328 _("Usage:"),
3329 _("Migrate shares to local server"));
3330 return 0;
3333 if (!c->opt_host) {
3334 printf(_("no server to migrate\n"));
3335 return -1;
3338 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3339 rpc_share_migrate_shares_internals,
3340 argc, argv);
3344 * Copy a file/dir
3346 * @param f file_info
3347 * @param mask current search mask
3348 * @param state arg-pointer
3351 static NTSTATUS copy_fn(const char *mnt, struct file_info *f,
3352 const char *mask, void *state)
3354 static NTSTATUS nt_status;
3355 static struct copy_clistate *local_state;
3356 static fstring filename, new_mask;
3357 fstring dir;
3358 char *old_dir;
3359 struct net_context *c;
3361 local_state = (struct copy_clistate *)state;
3362 nt_status = NT_STATUS_UNSUCCESSFUL;
3364 c = local_state->c;
3366 if (strequal(f->name, ".") || strequal(f->name, ".."))
3367 return NT_STATUS_OK;
3369 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3371 /* DIRECTORY */
3372 if (f->mode & aDIR) {
3374 DEBUG(3,("got dir: %s\n", f->name));
3376 fstrcpy(dir, local_state->cwd);
3377 fstrcat(dir, "\\");
3378 fstrcat(dir, f->name);
3380 switch (net_mode_share)
3382 case NET_MODE_SHARE_MIGRATE:
3383 /* create that directory */
3384 nt_status = net_copy_file(c, local_state->mem_ctx,
3385 local_state->cli_share_src,
3386 local_state->cli_share_dst,
3387 dir, dir,
3388 c->opt_acls? true : false,
3389 c->opt_attrs? true : false,
3390 c->opt_timestamps? true:false,
3391 false);
3392 break;
3393 default:
3394 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3395 return NT_STATUS_INTERNAL_ERROR;
3398 if (!NT_STATUS_IS_OK(nt_status)) {
3399 printf(_("could not handle dir %s: %s\n"),
3400 dir, nt_errstr(nt_status));
3401 return nt_status;
3404 /* search below that directory */
3405 fstrcpy(new_mask, dir);
3406 fstrcat(new_mask, "\\*");
3408 old_dir = local_state->cwd;
3409 local_state->cwd = dir;
3410 nt_status = sync_files(local_state, new_mask);
3411 if (!NT_STATUS_IS_OK(nt_status)) {
3412 printf(_("could not handle files\n"));
3414 local_state->cwd = old_dir;
3416 return nt_status;
3420 /* FILE */
3421 fstrcpy(filename, local_state->cwd);
3422 fstrcat(filename, "\\");
3423 fstrcat(filename, f->name);
3425 DEBUG(3,("got file: %s\n", filename));
3427 switch (net_mode_share)
3429 case NET_MODE_SHARE_MIGRATE:
3430 nt_status = net_copy_file(c, local_state->mem_ctx,
3431 local_state->cli_share_src,
3432 local_state->cli_share_dst,
3433 filename, filename,
3434 c->opt_acls? true : false,
3435 c->opt_attrs? true : false,
3436 c->opt_timestamps? true: false,
3437 true);
3438 break;
3439 default:
3440 d_fprintf(stderr, _("Unsupported file mode %d\n"),
3441 net_mode_share);
3442 return NT_STATUS_INTERNAL_ERROR;
3445 if (!NT_STATUS_IS_OK(nt_status))
3446 printf(_("could not handle file %s: %s\n"),
3447 filename, nt_errstr(nt_status));
3448 return nt_status;
3452 * sync files, can be called recursivly to list files
3453 * and then call copy_fn for each file
3455 * @param cp_clistate pointer to the copy_clistate we work with
3456 * @param mask the current search mask
3458 * @return Boolean result
3460 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask)
3462 struct cli_state *targetcli;
3463 char *targetpath = NULL;
3464 NTSTATUS status;
3466 DEBUG(3,("calling cli_list with mask: %s\n", mask));
3468 if ( !cli_resolve_path(talloc_tos(), "", NULL, cp_clistate->cli_share_src,
3469 mask, &targetcli, &targetpath ) ) {
3470 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
3471 "%s\n"),
3472 mask, cli_errstr(cp_clistate->cli_share_src));
3473 return cli_nt_error(cp_clistate->cli_share_src);
3476 status = cli_list(targetcli, targetpath, cp_clistate->attribute,
3477 copy_fn, cp_clistate);
3478 if (!NT_STATUS_IS_OK(status)) {
3479 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
3480 mask, nt_errstr(status));
3483 return status;
3488 * Set the top level directory permissions before we do any further copies.
3489 * Should set up ACL inheritance.
3492 bool copy_top_level_perms(struct net_context *c,
3493 struct copy_clistate *cp_clistate,
3494 const char *sharename)
3496 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3498 switch (net_mode_share) {
3499 case NET_MODE_SHARE_MIGRATE:
3500 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3501 nt_status = net_copy_fileattr(c,
3502 cp_clistate->mem_ctx,
3503 cp_clistate->cli_share_src,
3504 cp_clistate->cli_share_dst,
3505 "\\", "\\",
3506 c->opt_acls? true : false,
3507 c->opt_attrs? true : false,
3508 c->opt_timestamps? true: false,
3509 false);
3510 break;
3511 default:
3512 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3513 break;
3516 if (!NT_STATUS_IS_OK(nt_status)) {
3517 printf(_("Could handle directory attributes for top level "
3518 "directory of share %s. Error %s\n"),
3519 sharename, nt_errstr(nt_status));
3520 return false;
3523 return true;
3527 * Sync all files inside a remote share to another share (over smb).
3529 * All parameters are provided by the run_rpc_command function, except for
3530 * argc, argv which are passed through.
3532 * @param domain_sid The domain sid acquired from the remote server.
3533 * @param cli A cli_state connected to the server.
3534 * @param mem_ctx Talloc context, destroyed on completion of the function.
3535 * @param argc Standard main() style argc.
3536 * @param argv Standard main() style argv. Initial components are already
3537 * stripped.
3539 * @return Normal NTSTATUS return.
3542 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
3543 const struct dom_sid *domain_sid,
3544 const char *domain_name,
3545 struct cli_state *cli,
3546 struct rpc_pipe_client *pipe_hnd,
3547 TALLOC_CTX *mem_ctx,
3548 int argc,
3549 const char **argv)
3551 WERROR result;
3552 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3553 struct srvsvc_NetShareInfoCtr ctr_src;
3554 uint32 i;
3555 uint32 level = 502;
3556 struct copy_clistate cp_clistate;
3557 bool got_src_share = false;
3558 bool got_dst_share = false;
3559 const char *mask = "\\*";
3560 char *dst = NULL;
3562 dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3563 if (dst == NULL) {
3564 nt_status = NT_STATUS_NO_MEMORY;
3565 goto done;
3568 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3569 &ctr_src);
3571 if (!W_ERROR_IS_OK(result))
3572 goto done;
3574 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3576 struct srvsvc_NetShareInfo502 info502 =
3577 ctr_src.ctr.ctr502->array[i];
3579 if (!check_share_sanity(c, cli, info502.name, info502.type))
3580 continue;
3582 /* one might not want to mirror whole discs :) */
3583 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3584 d_printf(_("skipping [%s]: builtin/hidden share\n"),
3585 info502.name);
3586 continue;
3589 switch (net_mode_share)
3591 case NET_MODE_SHARE_MIGRATE:
3592 printf("syncing");
3593 break;
3594 default:
3595 d_fprintf(stderr, _("Unsupported mode %d\n"),
3596 net_mode_share);
3597 break;
3599 printf(_(" [%s] files and directories %s ACLs, %s DOS "
3600 "Attributes %s\n"),
3601 info502.name,
3602 c->opt_acls ? _("including") : _("without"),
3603 c->opt_attrs ? _("including") : _("without"),
3604 c->opt_timestamps ? _("(preserving timestamps)") : "");
3606 cp_clistate.mem_ctx = mem_ctx;
3607 cp_clistate.cli_share_src = NULL;
3608 cp_clistate.cli_share_dst = NULL;
3609 cp_clistate.cwd = NULL;
3610 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3611 cp_clistate.c = c;
3613 /* open share source */
3614 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
3615 &cli->dest_ss, cli->desthost,
3616 info502.name, "A:");
3617 if (!NT_STATUS_IS_OK(nt_status))
3618 goto done;
3620 got_src_share = true;
3622 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3623 /* open share destination */
3624 nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
3625 NULL, dst, info502.name, "A:");
3626 if (!NT_STATUS_IS_OK(nt_status))
3627 goto done;
3629 got_dst_share = true;
3632 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
3633 d_fprintf(stderr, _("Could not handle the top level "
3634 "directory permissions for the "
3635 "share: %s\n"), info502.name);
3636 nt_status = NT_STATUS_UNSUCCESSFUL;
3637 goto done;
3640 nt_status = sync_files(&cp_clistate, mask);
3641 if (!NT_STATUS_IS_OK(nt_status)) {
3642 d_fprintf(stderr, _("could not handle files for share: "
3643 "%s\n"), info502.name);
3644 goto done;
3648 nt_status = NT_STATUS_OK;
3650 done:
3652 if (got_src_share)
3653 cli_shutdown(cp_clistate.cli_share_src);
3655 if (got_dst_share)
3656 cli_shutdown(cp_clistate.cli_share_dst);
3658 SAFE_FREE(dst);
3659 return nt_status;
3663 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
3665 if (c->display_usage) {
3666 d_printf( "%s\n"
3667 "net share migrate files\n"
3668 " %s\n",
3669 _("Usage:"),
3670 _("Migrate files to local server"));
3671 return 0;
3674 if (!c->opt_host) {
3675 d_printf(_("no server to migrate\n"));
3676 return -1;
3679 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3680 rpc_share_migrate_files_internals,
3681 argc, argv);
3685 * Migrate share-ACLs from a remote RPC server to the local RPC server.
3687 * All parameters are provided by the run_rpc_command function, except for
3688 * argc, argv which are passed through.
3690 * @param domain_sid The domain sid acquired from the remote server.
3691 * @param cli A cli_state connected to the server.
3692 * @param mem_ctx Talloc context, destroyed on completion of the function.
3693 * @param argc Standard main() style argc.
3694 * @param argv Standard main() style argv. Initial components are already
3695 * stripped.
3697 * @return Normal NTSTATUS return.
3700 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
3701 const struct dom_sid *domain_sid,
3702 const char *domain_name,
3703 struct cli_state *cli,
3704 struct rpc_pipe_client *pipe_hnd,
3705 TALLOC_CTX *mem_ctx,
3706 int argc,
3707 const char **argv)
3709 WERROR result;
3710 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3711 struct srvsvc_NetShareInfoCtr ctr_src;
3712 union srvsvc_NetShareInfo info;
3713 uint32 i;
3714 struct rpc_pipe_client *srvsvc_pipe = NULL;
3715 struct cli_state *cli_dst = NULL;
3716 uint32 level = 502; /* includes secdesc */
3717 uint32_t parm_error = 0;
3719 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3720 &ctr_src);
3722 if (!W_ERROR_IS_OK(result))
3723 goto done;
3725 /* connect destination PI_SRVSVC */
3726 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3727 &ndr_table_srvsvc.syntax_id);
3728 if (!NT_STATUS_IS_OK(nt_status))
3729 return nt_status;
3732 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3734 struct srvsvc_NetShareInfo502 info502 =
3735 ctr_src.ctr.ctr502->array[i];
3737 /* reset error-code */
3738 nt_status = NT_STATUS_UNSUCCESSFUL;
3740 if (!check_share_sanity(c, cli, info502.name, info502.type))
3741 continue;
3743 printf(_("migrating: [%s], path: %s, comment: %s, including "
3744 "share-ACLs\n"),
3745 info502.name, info502.path, info502.comment);
3747 if (c->opt_verbose)
3748 display_sec_desc(info502.sd_buf.sd);
3750 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3751 info.info502 = &info502;
3753 /* finally modify the share on the dst server */
3754 nt_status = rpccli_srvsvc_NetShareSetInfo(srvsvc_pipe, mem_ctx,
3755 srvsvc_pipe->desthost,
3756 info502.name,
3757 level,
3758 &info,
3759 &parm_error,
3760 &result);
3761 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3762 printf(_("cannot set share-acl: %s\n"),
3763 win_errstr(result));
3764 goto done;
3769 nt_status = NT_STATUS_OK;
3771 done:
3772 if (cli_dst) {
3773 cli_shutdown(cli_dst);
3776 return nt_status;
3781 * Migrate share-acls from a RPC server to another.
3783 * @param argc Standard main() style argc.
3784 * @param argv Standard main() style argv. Initial components are already
3785 * stripped.
3787 * @return A shell status integer (0 for success).
3789 static int rpc_share_migrate_security(struct net_context *c, int argc,
3790 const char **argv)
3792 if (c->display_usage) {
3793 d_printf( "%s\n"
3794 "net rpc share migrate security\n"
3795 " %s\n",
3796 _("Usage:"),
3797 _("Migrate share-acls to local server"));
3798 return 0;
3801 if (!c->opt_host) {
3802 d_printf(_("no server to migrate\n"));
3803 return -1;
3806 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3807 rpc_share_migrate_security_internals,
3808 argc, argv);
3812 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3813 * from one server to another.
3815 * @param argc Standard main() style argc.
3816 * @param argv Standard main() style argv. Initial components are already
3817 * stripped.
3819 * @return A shell status integer (0 for success).
3822 static int rpc_share_migrate_all(struct net_context *c, int argc,
3823 const char **argv)
3825 int ret;
3827 if (c->display_usage) {
3828 d_printf( "%s\n"
3829 "net rpc share migrate all\n"
3830 " %s\n",
3831 _("Usage:"),
3832 _("Migrates shares including all share settings"));
3833 return 0;
3836 if (!c->opt_host) {
3837 d_printf(_("no server to migrate\n"));
3838 return -1;
3841 /* order is important. we don't want to be locked out by the share-acl
3842 * before copying files - gd */
3844 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3845 rpc_share_migrate_shares_internals, argc, argv);
3846 if (ret)
3847 return ret;
3849 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3850 rpc_share_migrate_files_internals, argc, argv);
3851 if (ret)
3852 return ret;
3854 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3855 rpc_share_migrate_security_internals, argc,
3856 argv);
3861 * 'net rpc share migrate' entrypoint.
3862 * @param argc Standard main() style argc.
3863 * @param argv Standard main() style argv. Initial components are already
3864 * stripped.
3866 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
3869 struct functable func[] = {
3871 "all",
3872 rpc_share_migrate_all,
3873 NET_TRANSPORT_RPC,
3874 N_("Migrate shares from remote to local server"),
3875 N_("net rpc share migrate all\n"
3876 " Migrate shares from remote to local server")
3879 "files",
3880 rpc_share_migrate_files,
3881 NET_TRANSPORT_RPC,
3882 N_("Migrate files from remote to local server"),
3883 N_("net rpc share migrate files\n"
3884 " Migrate files from remote to local server")
3887 "security",
3888 rpc_share_migrate_security,
3889 NET_TRANSPORT_RPC,
3890 N_("Migrate share-ACLs from remote to local server"),
3891 N_("net rpc share migrate security\n"
3892 " Migrate share-ACLs from remote to local server")
3895 "shares",
3896 rpc_share_migrate_shares,
3897 NET_TRANSPORT_RPC,
3898 N_("Migrate shares from remote to local server"),
3899 N_("net rpc share migrate shares\n"
3900 " Migrate shares from remote to local server")
3902 {NULL, NULL, 0, NULL, NULL}
3905 net_mode_share = NET_MODE_SHARE_MIGRATE;
3907 return net_run_function(c, argc, argv, "net rpc share migrate", func);
3910 struct full_alias {
3911 struct dom_sid sid;
3912 uint32 num_members;
3913 struct dom_sid *members;
3916 static int num_server_aliases;
3917 static struct full_alias *server_aliases;
3920 * Add an alias to the static list.
3922 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
3924 if (server_aliases == NULL)
3925 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
3927 server_aliases[num_server_aliases] = *alias;
3928 num_server_aliases += 1;
3932 * For a specific domain on the server, fetch all the aliases
3933 * and their members. Add all of them to the server_aliases.
3936 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
3937 TALLOC_CTX *mem_ctx,
3938 struct policy_handle *connect_pol,
3939 const struct dom_sid *domain_sid)
3941 uint32 start_idx, max_entries, num_entries, i;
3942 struct samr_SamArray *groups = NULL;
3943 NTSTATUS result;
3944 struct policy_handle domain_pol;
3946 /* Get domain policy handle */
3948 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
3949 connect_pol,
3950 MAXIMUM_ALLOWED_ACCESS,
3951 CONST_DISCARD(struct dom_sid2 *, domain_sid),
3952 &domain_pol);
3953 if (!NT_STATUS_IS_OK(result))
3954 return result;
3956 start_idx = 0;
3957 max_entries = 250;
3959 do {
3960 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
3961 &domain_pol,
3962 &start_idx,
3963 &groups,
3964 max_entries,
3965 &num_entries);
3966 for (i = 0; i < num_entries; i++) {
3968 struct policy_handle alias_pol;
3969 struct full_alias alias;
3970 struct lsa_SidArray sid_array;
3971 int j;
3973 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
3974 &domain_pol,
3975 MAXIMUM_ALLOWED_ACCESS,
3976 groups->entries[i].idx,
3977 &alias_pol);
3978 if (!NT_STATUS_IS_OK(result))
3979 goto done;
3981 result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
3982 &alias_pol,
3983 &sid_array);
3984 if (!NT_STATUS_IS_OK(result))
3985 goto done;
3987 alias.num_members = sid_array.num_sids;
3989 result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
3990 if (!NT_STATUS_IS_OK(result))
3991 goto done;
3993 alias.members = NULL;
3995 if (alias.num_members > 0) {
3996 alias.members = SMB_MALLOC_ARRAY(struct dom_sid, alias.num_members);
3998 for (j = 0; j < alias.num_members; j++)
3999 sid_copy(&alias.members[j],
4000 sid_array.sids[j].sid);
4003 sid_compose(&alias.sid, domain_sid,
4004 groups->entries[i].idx);
4006 push_alias(mem_ctx, &alias);
4008 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4010 result = NT_STATUS_OK;
4012 done:
4013 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
4015 return result;
4019 * Dump server_aliases as names for debugging purposes.
4022 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4023 const struct dom_sid *domain_sid,
4024 const char *domain_name,
4025 struct cli_state *cli,
4026 struct rpc_pipe_client *pipe_hnd,
4027 TALLOC_CTX *mem_ctx,
4028 int argc,
4029 const char **argv)
4031 int i;
4032 NTSTATUS result;
4033 struct policy_handle lsa_pol;
4035 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4036 SEC_FLAG_MAXIMUM_ALLOWED,
4037 &lsa_pol);
4038 if (!NT_STATUS_IS_OK(result))
4039 return result;
4041 for (i=0; i<num_server_aliases; i++) {
4042 char **names;
4043 char **domains;
4044 enum lsa_SidType *types;
4045 int j;
4047 struct full_alias *alias = &server_aliases[i];
4049 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4050 &alias->sid,
4051 &domains, &names, &types);
4052 if (!NT_STATUS_IS_OK(result))
4053 continue;
4055 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4057 if (alias->num_members == 0) {
4058 DEBUG(1, ("\n"));
4059 continue;
4062 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4063 alias->num_members,
4064 alias->members,
4065 &domains, &names, &types);
4067 if (!NT_STATUS_IS_OK(result) &&
4068 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4069 continue;
4071 for (j=0; j<alias->num_members; j++)
4072 DEBUG(1, ("%s\\%s (%d); ",
4073 domains[j] ? domains[j] : "*unknown*",
4074 names[j] ? names[j] : "*unknown*",types[j]));
4075 DEBUG(1, ("\n"));
4078 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
4080 return NT_STATUS_OK;
4084 * Fetch a list of all server aliases and their members into
4085 * server_aliases.
4088 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4089 const struct dom_sid *domain_sid,
4090 const char *domain_name,
4091 struct cli_state *cli,
4092 struct rpc_pipe_client *pipe_hnd,
4093 TALLOC_CTX *mem_ctx,
4094 int argc,
4095 const char **argv)
4097 NTSTATUS result;
4098 struct policy_handle connect_pol;
4100 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
4101 pipe_hnd->desthost,
4102 MAXIMUM_ALLOWED_ACCESS,
4103 &connect_pol);
4105 if (!NT_STATUS_IS_OK(result))
4106 goto done;
4108 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4109 &global_sid_Builtin);
4111 if (!NT_STATUS_IS_OK(result))
4112 goto done;
4114 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4115 domain_sid);
4117 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
4118 done:
4119 return result;
4122 static void init_user_token(struct security_token *token, struct dom_sid *user_sid)
4124 token->num_sids = 4;
4126 if (!(token->sids = SMB_MALLOC_ARRAY(struct dom_sid, 4))) {
4127 d_fprintf(stderr, "malloc %s\n",_("failed"));
4128 token->num_sids = 0;
4129 return;
4132 token->sids[0] = *user_sid;
4133 sid_copy(&token->sids[1], &global_sid_World);
4134 sid_copy(&token->sids[2], &global_sid_Network);
4135 sid_copy(&token->sids[3], &global_sid_Authenticated_Users);
4138 static void free_user_token(struct security_token *token)
4140 SAFE_FREE(token->sids);
4143 static void add_sid_to_token(struct security_token *token, struct dom_sid *sid)
4145 if (security_token_has_sid(token, sid))
4146 return;
4148 token->sids = SMB_REALLOC_ARRAY(token->sids, struct dom_sid, token->num_sids+1);
4149 if (!token->sids) {
4150 return;
4153 sid_copy(&token->sids[token->num_sids], sid);
4155 token->num_sids += 1;
4158 struct user_token {
4159 fstring name;
4160 struct security_token token;
4163 static void dump_user_token(struct user_token *token)
4165 int i;
4167 d_printf("%s\n", token->name);
4169 for (i=0; i<token->token.num_sids; i++) {
4170 d_printf(" %s\n", sid_string_tos(&token->token.sids[i]));
4174 static bool is_alias_member(struct dom_sid *sid, struct full_alias *alias)
4176 int i;
4178 for (i=0; i<alias->num_members; i++) {
4179 if (dom_sid_compare(sid, &alias->members[i]) == 0)
4180 return true;
4183 return false;
4186 static void collect_sid_memberships(struct security_token *token, struct dom_sid sid)
4188 int i;
4190 for (i=0; i<num_server_aliases; i++) {
4191 if (is_alias_member(&sid, &server_aliases[i]))
4192 add_sid_to_token(token, &server_aliases[i].sid);
4197 * We got a user token with all the SIDs we can know about without asking the
4198 * server directly. These are the user and domain group sids. All of these can
4199 * be members of aliases. So scan the list of aliases for each of the SIDs and
4200 * add them to the token.
4203 static void collect_alias_memberships(struct security_token *token)
4205 int num_global_sids = token->num_sids;
4206 int i;
4208 for (i=0; i<num_global_sids; i++) {
4209 collect_sid_memberships(token, token->sids[i]);
4213 static bool get_user_sids(const char *domain, const char *user, struct security_token *token)
4215 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4216 enum wbcSidType type;
4217 fstring full_name;
4218 struct wbcDomainSid wsid;
4219 char *sid_str = NULL;
4220 struct dom_sid user_sid;
4221 uint32_t num_groups;
4222 gid_t *groups = NULL;
4223 uint32_t i;
4225 fstr_sprintf(full_name, "%s%c%s",
4226 domain, *lp_winbind_separator(), user);
4228 /* First let's find out the user sid */
4230 wbc_status = wbcLookupName(domain, user, &wsid, &type);
4232 if (!WBC_ERROR_IS_OK(wbc_status)) {
4233 DEBUG(1, ("winbind could not find %s: %s\n",
4234 full_name, wbcErrorString(wbc_status)));
4235 return false;
4238 wbc_status = wbcSidToString(&wsid, &sid_str);
4239 if (!WBC_ERROR_IS_OK(wbc_status)) {
4240 return false;
4243 if (type != SID_NAME_USER) {
4244 wbcFreeMemory(sid_str);
4245 DEBUG(1, ("%s is not a user\n", full_name));
4246 return false;
4249 if (!string_to_sid(&user_sid, sid_str)) {
4250 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4251 return false;
4254 wbcFreeMemory(sid_str);
4255 sid_str = NULL;
4257 init_user_token(token, &user_sid);
4259 /* And now the groups winbind knows about */
4261 wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4262 if (!WBC_ERROR_IS_OK(wbc_status)) {
4263 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4264 full_name, wbcErrorString(wbc_status)));
4265 return false;
4268 for (i = 0; i < num_groups; i++) {
4269 gid_t gid = groups[i];
4270 struct dom_sid sid;
4272 wbc_status = wbcGidToSid(gid, &wsid);
4273 if (!WBC_ERROR_IS_OK(wbc_status)) {
4274 DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4275 (unsigned int)gid, wbcErrorString(wbc_status)));
4276 wbcFreeMemory(groups);
4277 return false;
4280 wbc_status = wbcSidToString(&wsid, &sid_str);
4281 if (!WBC_ERROR_IS_OK(wbc_status)) {
4282 wbcFreeMemory(groups);
4283 return false;
4286 DEBUG(3, (" %s\n", sid_str));
4288 string_to_sid(&sid, sid_str);
4289 wbcFreeMemory(sid_str);
4290 sid_str = NULL;
4292 add_sid_to_token(token, &sid);
4294 wbcFreeMemory(groups);
4296 return true;
4300 * Get a list of all user tokens we want to look at
4303 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4304 struct user_token **user_tokens)
4306 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4307 uint32_t i, num_users;
4308 const char **users;
4309 struct user_token *result;
4310 TALLOC_CTX *frame = NULL;
4312 if (lp_winbind_use_default_domain() &&
4313 (c->opt_target_workgroup == NULL)) {
4314 d_fprintf(stderr, _("winbind use default domain = yes set, "
4315 "please specify a workgroup\n"));
4316 return false;
4319 /* Send request to winbind daemon */
4321 wbc_status = wbcListUsers(NULL, &num_users, &users);
4322 if (!WBC_ERROR_IS_OK(wbc_status)) {
4323 DEBUG(1, (_("winbind could not list users: %s\n"),
4324 wbcErrorString(wbc_status)));
4325 return false;
4328 result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4330 if (result == NULL) {
4331 DEBUG(1, ("Could not malloc sid array\n"));
4332 wbcFreeMemory(users);
4333 return false;
4336 frame = talloc_stackframe();
4337 for (i=0; i < num_users; i++) {
4338 fstring domain, user;
4339 char *p;
4341 fstrcpy(result[i].name, users[i]);
4343 p = strchr(users[i], *lp_winbind_separator());
4345 DEBUG(3, ("%s\n", users[i]));
4347 if (p == NULL) {
4348 fstrcpy(domain, c->opt_target_workgroup);
4349 fstrcpy(user, users[i]);
4350 } else {
4351 *p++ = '\0';
4352 fstrcpy(domain, users[i]);
4353 strupper_m(domain);
4354 fstrcpy(user, p);
4357 get_user_sids(domain, user, &(result[i].token));
4358 i+=1;
4360 TALLOC_FREE(frame);
4361 wbcFreeMemory(users);
4363 *num_tokens = num_users;
4364 *user_tokens = result;
4366 return true;
4369 static bool get_user_tokens_from_file(FILE *f,
4370 int *num_tokens,
4371 struct user_token **tokens)
4373 struct user_token *token = NULL;
4375 while (!feof(f)) {
4376 fstring line;
4378 if (fgets(line, sizeof(line)-1, f) == NULL) {
4379 return true;
4382 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
4383 line[strlen(line)-1] = '\0';
4386 if (line[0] == ' ') {
4387 /* We have a SID */
4389 struct dom_sid sid;
4390 if(!string_to_sid(&sid, &line[1])) {
4391 DEBUG(1,("get_user_tokens_from_file: Could "
4392 "not convert sid %s \n",&line[1]));
4393 return false;
4396 if (token == NULL) {
4397 DEBUG(0, ("File does not begin with username"));
4398 return false;
4401 add_sid_to_token(&token->token, &sid);
4402 continue;
4405 /* And a new user... */
4407 *num_tokens += 1;
4408 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4409 if (*tokens == NULL) {
4410 DEBUG(0, ("Could not realloc tokens\n"));
4411 return false;
4414 token = &((*tokens)[*num_tokens-1]);
4416 fstrcpy(token->name, line);
4417 token->token.num_sids = 0;
4418 token->token.sids = NULL;
4419 continue;
4422 return false;
4427 * Show the list of all users that have access to a share
4430 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4431 TALLOC_CTX *mem_ctx,
4432 const char *netname,
4433 int num_tokens,
4434 struct user_token *tokens)
4436 uint16_t fnum;
4437 struct security_descriptor *share_sd = NULL;
4438 struct security_descriptor *root_sd = NULL;
4439 struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4440 int i;
4441 union srvsvc_NetShareInfo info;
4442 WERROR result;
4443 NTSTATUS status;
4444 uint16 cnum;
4446 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4447 pipe_hnd->desthost,
4448 netname,
4449 502,
4450 &info,
4451 &result);
4453 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4454 DEBUG(1, ("Coult not query secdesc for share %s\n",
4455 netname));
4456 return;
4459 share_sd = info.info502->sd_buf.sd;
4460 if (share_sd == NULL) {
4461 DEBUG(1, ("Got no secdesc for share %s\n",
4462 netname));
4465 cnum = cli->cnum;
4467 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
4468 return;
4471 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
4472 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
4473 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4476 for (i=0; i<num_tokens; i++) {
4477 uint32 acc_granted;
4479 if (share_sd != NULL) {
4480 status = se_access_check(share_sd, &tokens[i].token,
4481 1, &acc_granted);
4483 if (!NT_STATUS_IS_OK(status)) {
4484 DEBUG(1, ("Could not check share_sd for "
4485 "user %s\n",
4486 tokens[i].name));
4487 continue;
4491 if (root_sd == NULL) {
4492 d_printf(" %s\n", tokens[i].name);
4493 continue;
4496 status = se_access_check(root_sd, &tokens[i].token,
4497 1, &acc_granted);
4498 if (!NT_STATUS_IS_OK(status)) {
4499 DEBUG(1, ("Could not check root_sd for user %s\n",
4500 tokens[i].name));
4501 continue;
4503 d_printf(" %s\n", tokens[i].name);
4506 if (fnum != (uint16_t)-1)
4507 cli_close(cli, fnum);
4508 cli_tdis(cli);
4509 cli->cnum = cnum;
4511 return;
4514 struct share_list {
4515 int num_shares;
4516 char **shares;
4519 static void collect_share(const char *name, uint32 m,
4520 const char *comment, void *state)
4522 struct share_list *share_list = (struct share_list *)state;
4524 if (m != STYPE_DISKTREE)
4525 return;
4527 share_list->num_shares += 1;
4528 share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4529 if (!share_list->shares) {
4530 share_list->num_shares = 0;
4531 return;
4533 share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4537 * List shares on a remote RPC server, including the security descriptors.
4539 * All parameters are provided by the run_rpc_command function, except for
4540 * argc, argv which are passed through.
4542 * @param domain_sid The domain sid acquired from the remote server.
4543 * @param cli A cli_state connected to the server.
4544 * @param mem_ctx Talloc context, destroyed on completion of the function.
4545 * @param argc Standard main() style argc.
4546 * @param argv Standard main() style argv. Initial components are already
4547 * stripped.
4549 * @return Normal NTSTATUS return.
4552 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
4553 const struct dom_sid *domain_sid,
4554 const char *domain_name,
4555 struct cli_state *cli,
4556 struct rpc_pipe_client *pipe_hnd,
4557 TALLOC_CTX *mem_ctx,
4558 int argc,
4559 const char **argv)
4561 int ret;
4562 bool r;
4563 uint32 i;
4564 FILE *f;
4566 struct user_token *tokens = NULL;
4567 int num_tokens = 0;
4569 struct share_list share_list;
4571 if (argc == 0) {
4572 f = stdin;
4573 } else {
4574 f = fopen(argv[0], "r");
4577 if (f == NULL) {
4578 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4579 return NT_STATUS_UNSUCCESSFUL;
4582 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4584 if (f != stdin)
4585 fclose(f);
4587 if (!r) {
4588 DEBUG(0, ("Could not read users from file\n"));
4589 return NT_STATUS_UNSUCCESSFUL;
4592 for (i=0; i<num_tokens; i++)
4593 collect_alias_memberships(&tokens[i].token);
4595 share_list.num_shares = 0;
4596 share_list.shares = NULL;
4598 ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4600 if (ret == -1) {
4601 DEBUG(0, ("Error returning browse list: %s\n",
4602 cli_errstr(cli)));
4603 goto done;
4606 for (i = 0; i < share_list.num_shares; i++) {
4607 char *netname = share_list.shares[i];
4609 if (netname[strlen(netname)-1] == '$')
4610 continue;
4612 d_printf("%s\n", netname);
4614 show_userlist(pipe_hnd, mem_ctx, netname,
4615 num_tokens, tokens);
4617 done:
4618 for (i=0; i<num_tokens; i++) {
4619 free_user_token(&tokens[i].token);
4621 SAFE_FREE(tokens);
4622 SAFE_FREE(share_list.shares);
4624 return NT_STATUS_OK;
4627 static int rpc_share_allowedusers(struct net_context *c, int argc,
4628 const char **argv)
4630 int result;
4632 if (c->display_usage) {
4633 d_printf( "%s\n"
4634 "net rpc share allowedusers\n"
4635 " %s\n",
4636 _("Usage:"),
4637 _("List allowed users"));
4638 return 0;
4641 result = run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
4642 rpc_aliaslist_internals,
4643 argc, argv);
4644 if (result != 0)
4645 return result;
4647 result = run_rpc_command(c, NULL, &ndr_table_lsarpc.syntax_id, 0,
4648 rpc_aliaslist_dump,
4649 argc, argv);
4650 if (result != 0)
4651 return result;
4653 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4654 rpc_share_allowedusers_internals,
4655 argc, argv);
4658 int net_usersidlist(struct net_context *c, int argc, const char **argv)
4660 int num_tokens = 0;
4661 struct user_token *tokens = NULL;
4662 int i;
4664 if (argc != 0) {
4665 net_usersidlist_usage(c, argc, argv);
4666 return 0;
4669 if (!get_user_tokens(c, &num_tokens, &tokens)) {
4670 DEBUG(0, ("Could not get the user/sid list\n"));
4671 return 0;
4674 for (i=0; i<num_tokens; i++) {
4675 dump_user_token(&tokens[i]);
4676 free_user_token(&tokens[i].token);
4679 SAFE_FREE(tokens);
4680 return 1;
4683 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
4685 d_printf(_("net usersidlist\n"
4686 "\tprints out a list of all users the running winbind knows\n"
4687 "\tabout, together with all their SIDs. This is used as\n"
4688 "\tinput to the 'net rpc share allowedusers' command.\n\n"));
4690 net_common_flags_usage(c, argc, argv);
4691 return -1;
4695 * 'net rpc share' entrypoint.
4696 * @param argc Standard main() style argc.
4697 * @param argv Standard main() style argv. Initial components are already
4698 * stripped.
4701 int net_rpc_share(struct net_context *c, int argc, const char **argv)
4703 NET_API_STATUS status;
4705 struct functable func[] = {
4707 "add",
4708 rpc_share_add,
4709 NET_TRANSPORT_RPC,
4710 N_("Add share"),
4711 N_("net rpc share add\n"
4712 " Add share")
4715 "delete",
4716 rpc_share_delete,
4717 NET_TRANSPORT_RPC,
4718 N_("Remove share"),
4719 N_("net rpc share delete\n"
4720 " Remove share")
4723 "allowedusers",
4724 rpc_share_allowedusers,
4725 NET_TRANSPORT_RPC,
4726 N_("Modify allowed users"),
4727 N_("net rpc share allowedusers\n"
4728 " Modify allowed users")
4731 "migrate",
4732 rpc_share_migrate,
4733 NET_TRANSPORT_RPC,
4734 N_("Migrate share to local server"),
4735 N_("net rpc share migrate\n"
4736 " Migrate share to local server")
4739 "list",
4740 rpc_share_list,
4741 NET_TRANSPORT_RPC,
4742 N_("List shares"),
4743 N_("net rpc share list\n"
4744 " List shares")
4746 {NULL, NULL, 0, NULL, NULL}
4749 status = libnetapi_net_init(&c->netapi_ctx);
4750 if (status != 0) {
4751 return -1;
4753 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
4754 libnetapi_set_password(c->netapi_ctx, c->opt_password);
4755 if (c->opt_kerberos) {
4756 libnetapi_set_use_kerberos(c->netapi_ctx);
4759 if (argc == 0) {
4760 if (c->display_usage) {
4761 d_printf("%s\n%s",
4762 _("Usage:"),
4763 _("net rpc share\n"
4764 " List shares\n"
4765 " Alias for net rpc share list\n"));
4766 net_display_usage_from_functable(func);
4767 return 0;
4770 return rpc_share_list(c, argc, argv);
4773 return net_run_function(c, argc, argv, "net rpc share", func);
4776 static NTSTATUS rpc_sh_share_list(struct net_context *c,
4777 TALLOC_CTX *mem_ctx,
4778 struct rpc_sh_ctx *ctx,
4779 struct rpc_pipe_client *pipe_hnd,
4780 int argc, const char **argv)
4783 return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
4786 static NTSTATUS rpc_sh_share_add(struct net_context *c,
4787 TALLOC_CTX *mem_ctx,
4788 struct rpc_sh_ctx *ctx,
4789 struct rpc_pipe_client *pipe_hnd,
4790 int argc, const char **argv)
4792 NET_API_STATUS status;
4793 uint32_t parm_err = 0;
4794 struct SHARE_INFO_2 i2;
4796 if ((argc < 2) || (argc > 3)) {
4797 d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
4798 ctx->whoami);
4799 return NT_STATUS_INVALID_PARAMETER;
4802 i2.shi2_netname = argv[0];
4803 i2.shi2_type = STYPE_DISKTREE;
4804 i2.shi2_remark = (argc == 3) ? argv[2] : "";
4805 i2.shi2_permissions = 0;
4806 i2.shi2_max_uses = 0;
4807 i2.shi2_current_uses = 0;
4808 i2.shi2_path = argv[1];
4809 i2.shi2_passwd = NULL;
4811 status = NetShareAdd(pipe_hnd->desthost,
4813 (uint8_t *)&i2,
4814 &parm_err);
4816 return werror_to_ntstatus(W_ERROR(status));
4819 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
4820 TALLOC_CTX *mem_ctx,
4821 struct rpc_sh_ctx *ctx,
4822 struct rpc_pipe_client *pipe_hnd,
4823 int argc, const char **argv)
4825 if (argc != 1) {
4826 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
4827 return NT_STATUS_INVALID_PARAMETER;
4830 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
4833 static NTSTATUS rpc_sh_share_info(struct net_context *c,
4834 TALLOC_CTX *mem_ctx,
4835 struct rpc_sh_ctx *ctx,
4836 struct rpc_pipe_client *pipe_hnd,
4837 int argc, const char **argv)
4839 union srvsvc_NetShareInfo info;
4840 WERROR result;
4841 NTSTATUS status;
4843 if (argc != 1) {
4844 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
4845 return NT_STATUS_INVALID_PARAMETER;
4848 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4849 pipe_hnd->desthost,
4850 argv[0],
4852 &info,
4853 &result);
4854 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4855 goto done;
4858 d_printf(_("Name: %s\n"), info.info2->name);
4859 d_printf(_("Comment: %s\n"), info.info2->comment);
4860 d_printf(_("Path: %s\n"), info.info2->path);
4861 d_printf(_("Password: %s\n"), info.info2->password);
4863 done:
4864 return werror_to_ntstatus(result);
4867 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
4868 struct rpc_sh_ctx *ctx)
4870 static struct rpc_sh_cmd cmds[] = {
4872 { "list", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_list,
4873 N_("List available shares") },
4875 { "add", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_add,
4876 N_("Add a share") },
4878 { "delete", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_delete,
4879 N_("Delete a share") },
4881 { "info", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_info,
4882 N_("Get information about a share") },
4884 { NULL, NULL, 0, NULL, NULL }
4887 return cmds;
4890 /****************************************************************************/
4892 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
4894 return net_file_usage(c, argc, argv);
4898 * Close a file on a remote RPC server.
4900 * @param argc Standard main() style argc.
4901 * @param argv Standard main() style argv. Initial components are already
4902 * stripped.
4904 * @return A shell status integer (0 for success).
4906 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
4908 if (argc < 1 || c->display_usage) {
4909 return rpc_file_usage(c, argc, argv);
4912 return NetFileClose(c->opt_host, atoi(argv[0]));
4916 * Formatted print of open file info
4918 * @param r struct FILE_INFO_3 contents
4921 static void display_file_info_3(struct FILE_INFO_3 *r)
4923 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
4924 r->fi3_id, r->fi3_username, r->fi3_permissions,
4925 r->fi3_num_locks, r->fi3_pathname);
4929 * List files for a user on a remote RPC server.
4931 * @param argc Standard main() style argc.
4932 * @param argv Standard main() style argv. Initial components are already
4933 * stripped.
4935 * @return A shell status integer (0 for success)..
4938 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
4940 NET_API_STATUS status;
4941 uint32 preferred_len = 0xffffffff, i;
4942 const char *username=NULL;
4943 uint32_t total_entries = 0;
4944 uint32_t entries_read = 0;
4945 uint32_t resume_handle = 0;
4946 struct FILE_INFO_3 *i3 = NULL;
4948 if (c->display_usage) {
4949 return rpc_file_usage(c, argc, argv);
4952 /* if argc > 0, must be user command */
4953 if (argc > 0) {
4954 username = smb_xstrdup(argv[0]);
4957 status = NetFileEnum(c->opt_host,
4958 NULL,
4959 username,
4961 (uint8_t **)(void *)&i3,
4962 preferred_len,
4963 &entries_read,
4964 &total_entries,
4965 &resume_handle);
4967 if (status != 0) {
4968 goto done;
4971 /* Display results */
4973 d_printf(_(
4974 "\nEnumerating open files on remote server:\n\n"
4975 "\nFileId Opened by Perms Locks Path"
4976 "\n------ --------- ----- ----- ---- \n"));
4977 for (i = 0; i < entries_read; i++) {
4978 display_file_info_3(&i3[i]);
4980 done:
4981 return status;
4985 * 'net rpc file' entrypoint.
4986 * @param argc Standard main() style argc.
4987 * @param argv Standard main() style argv. Initial components are already
4988 * stripped.
4991 int net_rpc_file(struct net_context *c, int argc, const char **argv)
4993 NET_API_STATUS status;
4995 struct functable func[] = {
4997 "close",
4998 rpc_file_close,
4999 NET_TRANSPORT_RPC,
5000 N_("Close opened file"),
5001 N_("net rpc file close\n"
5002 " Close opened file")
5005 "user",
5006 rpc_file_user,
5007 NET_TRANSPORT_RPC,
5008 N_("List files opened by user"),
5009 N_("net rpc file user\n"
5010 " List files opened by user")
5012 #if 0
5014 "info",
5015 rpc_file_info,
5016 NET_TRANSPORT_RPC,
5017 N_("Display information about opened file"),
5018 N_("net rpc file info\n"
5019 " Display information about opened file")
5021 #endif
5022 {NULL, NULL, 0, NULL, NULL}
5025 status = libnetapi_net_init(&c->netapi_ctx);
5026 if (status != 0) {
5027 return -1;
5029 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5030 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5031 if (c->opt_kerberos) {
5032 libnetapi_set_use_kerberos(c->netapi_ctx);
5035 if (argc == 0) {
5036 if (c->display_usage) {
5037 d_printf(_("Usage:\n"));
5038 d_printf(_("net rpc file\n"
5039 " List opened files\n"));
5040 net_display_usage_from_functable(func);
5041 return 0;
5044 return rpc_file_user(c, argc, argv);
5047 return net_run_function(c, argc, argv, "net rpc file", func);
5051 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5053 * All parameters are provided by the run_rpc_command function, except for
5054 * argc, argv which are passed through.
5056 * @param c A net_context structure.
5057 * @param domain_sid The domain sid acquired from the remote server.
5058 * @param cli A cli_state connected to the server.
5059 * @param mem_ctx Talloc context, destroyed on completion of the function.
5060 * @param argc Standard main() style argc.
5061 * @param argv Standard main() style argv. Initial components are already
5062 * stripped.
5064 * @return Normal NTSTATUS return.
5067 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5068 const struct dom_sid *domain_sid,
5069 const char *domain_name,
5070 struct cli_state *cli,
5071 struct rpc_pipe_client *pipe_hnd,
5072 TALLOC_CTX *mem_ctx,
5073 int argc,
5074 const char **argv)
5076 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5078 result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
5080 if (NT_STATUS_IS_OK(result)) {
5081 d_printf(_("\nShutdown successfully aborted\n"));
5082 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5083 } else
5084 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5086 return result;
5090 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5092 * All parameters are provided by the run_rpc_command function, except for
5093 * argc, argv which are passed through.
5095 * @param c A net_context structure.
5096 * @param domain_sid The domain sid acquired from the remote server.
5097 * @param cli A cli_state connected to the server.
5098 * @param mem_ctx Talloc context, destroyed on completion of the function.
5099 * @param argc Standard main() style argc.
5100 * @param argv Standard main() style argv. Initial components are already
5101 * stripped.
5103 * @return Normal NTSTATUS return.
5106 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5107 const struct dom_sid *domain_sid,
5108 const char *domain_name,
5109 struct cli_state *cli,
5110 struct rpc_pipe_client *pipe_hnd,
5111 TALLOC_CTX *mem_ctx,
5112 int argc,
5113 const char **argv)
5115 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5117 result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
5119 if (NT_STATUS_IS_OK(result)) {
5120 d_printf(_("\nShutdown successfully aborted\n"));
5121 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5122 } else
5123 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5125 return result;
5129 * ABORT the shutdown of a remote RPC server.
5131 * @param argc Standard main() style argc.
5132 * @param argv Standard main() style argv. Initial components are already
5133 * stripped.
5135 * @return A shell status integer (0 for success).
5138 static int rpc_shutdown_abort(struct net_context *c, int argc,
5139 const char **argv)
5141 int rc = -1;
5143 if (c->display_usage) {
5144 d_printf( "%s\n"
5145 "net rpc abortshutdown\n"
5146 " %s\n",
5147 _("Usage:"),
5148 _("Abort a scheduled shutdown"));
5149 return 0;
5152 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5153 rpc_shutdown_abort_internals, argc, argv);
5155 if (rc == 0)
5156 return rc;
5158 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5160 return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5161 rpc_reg_shutdown_abort_internals,
5162 argc, argv);
5166 * Shut down a remote RPC Server via initshutdown pipe.
5168 * All parameters are provided by the run_rpc_command function, except for
5169 * argc, argv which are passed through.
5171 * @param c A net_context structure.
5172 * @param domain_sid The domain sid acquired from the remote server.
5173 * @param cli A cli_state connected to the server.
5174 * @param mem_ctx Talloc context, destroyed on completion of the function.
5175 * @param argc Standard main() style argc.
5176 * @param argv Standard main() style argv. Initial components are already
5177 * stripped.
5179 * @return Normal NTSTATUS return.
5182 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5183 const struct dom_sid *domain_sid,
5184 const char *domain_name,
5185 struct cli_state *cli,
5186 struct rpc_pipe_client *pipe_hnd,
5187 TALLOC_CTX *mem_ctx,
5188 int argc,
5189 const char **argv)
5191 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5192 const char *msg = N_("This machine will be shutdown shortly");
5193 uint32 timeout = 20;
5194 struct lsa_StringLarge msg_string;
5196 if (c->opt_comment) {
5197 msg = c->opt_comment;
5199 if (c->opt_timeout) {
5200 timeout = c->opt_timeout;
5203 msg_string.string = msg;
5205 /* create an entry */
5206 result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5207 &msg_string, timeout, c->opt_force, c->opt_reboot,
5208 NULL);
5210 if (NT_STATUS_IS_OK(result)) {
5211 d_printf(_("\nShutdown of remote machine succeeded\n"));
5212 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5213 } else {
5214 DEBUG(1,("Shutdown of remote machine failed!\n"));
5216 return result;
5220 * Shut down a remote RPC Server via winreg pipe.
5222 * All parameters are provided by the run_rpc_command function, except for
5223 * argc, argv which are passed through.
5225 * @param c A net_context structure.
5226 * @param domain_sid The domain sid acquired from the remote server.
5227 * @param cli A cli_state connected to the server.
5228 * @param mem_ctx Talloc context, destroyed on completion of the function.
5229 * @param argc Standard main() style argc.
5230 * @param argv Standard main() style argv. Initial components are already
5231 * stripped.
5233 * @return Normal NTSTATUS return.
5236 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5237 const struct dom_sid *domain_sid,
5238 const char *domain_name,
5239 struct cli_state *cli,
5240 struct rpc_pipe_client *pipe_hnd,
5241 TALLOC_CTX *mem_ctx,
5242 int argc,
5243 const char **argv)
5245 const char *msg = N_("This machine will be shutdown shortly");
5246 uint32 timeout = 20;
5247 struct lsa_StringLarge msg_string;
5248 NTSTATUS result;
5249 WERROR werr;
5251 if (c->opt_comment) {
5252 msg = c->opt_comment;
5254 msg_string.string = msg;
5256 if (c->opt_timeout) {
5257 timeout = c->opt_timeout;
5260 /* create an entry */
5261 result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5262 &msg_string, timeout, c->opt_force, c->opt_reboot,
5263 &werr);
5265 if (NT_STATUS_IS_OK(result)) {
5266 d_printf(_("\nShutdown of remote machine succeeded\n"));
5267 } else {
5268 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5269 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5270 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5271 else
5272 d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5275 return result;
5279 * Shut down a remote RPC server.
5281 * @param argc Standard main() style argc.
5282 * @param argv Standard main() style argv. Initial components are already
5283 * stripped.
5285 * @return A shell status integer (0 for success).
5288 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5290 int rc = -1;
5292 if (c->display_usage) {
5293 d_printf( "%s\n"
5294 "net rpc shutdown\n"
5295 " %s\n",
5296 _("Usage:"),
5297 _("Shut down a remote RPC server"));
5298 return 0;
5301 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5302 rpc_init_shutdown_internals, argc, argv);
5304 if (rc) {
5305 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5306 rc = run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5307 rpc_reg_shutdown_internals, argc, argv);
5310 return rc;
5313 /***************************************************************************
5314 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5315 ***************************************************************************/
5318 * Add interdomain trust account to the RPC server.
5319 * All parameters (except for argc and argv) are passed by run_rpc_command
5320 * function.
5322 * @param c A net_context structure.
5323 * @param domain_sid The domain sid acquired from the server.
5324 * @param cli A cli_state connected to the server.
5325 * @param mem_ctx Talloc context, destroyed on completion of the function.
5326 * @param argc Standard main() style argc.
5327 * @param argv Standard main() style argv. Initial components are already
5328 * stripped.
5330 * @return normal NTSTATUS return code.
5333 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
5334 const struct dom_sid *domain_sid,
5335 const char *domain_name,
5336 struct cli_state *cli,
5337 struct rpc_pipe_client *pipe_hnd,
5338 TALLOC_CTX *mem_ctx,
5339 int argc,
5340 const char **argv)
5342 struct policy_handle connect_pol, domain_pol, user_pol;
5343 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5344 char *acct_name;
5345 struct lsa_String lsa_acct_name;
5346 uint32 acb_info;
5347 uint32 acct_flags=0;
5348 uint32 user_rid;
5349 uint32_t access_granted = 0;
5350 union samr_UserInfo info;
5351 unsigned int orig_timeout;
5353 if (argc != 2) {
5354 d_printf("%s\n%s",
5355 _("Usage:"),
5356 _(" net rpc trustdom add <domain_name> "
5357 "<trust password>\n"));
5358 return NT_STATUS_INVALID_PARAMETER;
5362 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5365 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5366 return NT_STATUS_NO_MEMORY;
5369 strupper_m(acct_name);
5371 init_lsa_String(&lsa_acct_name, acct_name);
5373 /* Get samr policy handle */
5374 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5375 pipe_hnd->desthost,
5376 MAXIMUM_ALLOWED_ACCESS,
5377 &connect_pol);
5378 if (!NT_STATUS_IS_OK(result)) {
5379 goto done;
5382 /* Get domain policy handle */
5383 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5384 &connect_pol,
5385 MAXIMUM_ALLOWED_ACCESS,
5386 CONST_DISCARD(struct dom_sid2 *, domain_sid),
5387 &domain_pol);
5388 if (!NT_STATUS_IS_OK(result)) {
5389 goto done;
5392 /* This call can take a long time - allow the server to time out.
5393 * 35 seconds should do it. */
5395 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5397 /* Create trusting domain's account */
5398 acb_info = ACB_NORMAL;
5399 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5400 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5401 SAMR_USER_ACCESS_SET_PASSWORD |
5402 SAMR_USER_ACCESS_GET_ATTRIBUTES |
5403 SAMR_USER_ACCESS_SET_ATTRIBUTES;
5405 result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5406 &domain_pol,
5407 &lsa_acct_name,
5408 acb_info,
5409 acct_flags,
5410 &user_pol,
5411 &access_granted,
5412 &user_rid);
5414 /* And restore our original timeout. */
5415 rpccli_set_timeout(pipe_hnd, orig_timeout);
5417 if (!NT_STATUS_IS_OK(result)) {
5418 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
5419 acct_name, nt_errstr(result));
5420 goto done;
5424 struct samr_CryptPassword crypt_pwd;
5426 ZERO_STRUCT(info.info23);
5428 init_samr_CryptPassword(argv[1],
5429 &cli->user_session_key,
5430 &crypt_pwd);
5432 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
5433 SAMR_FIELD_NT_PASSWORD_PRESENT;
5434 info.info23.info.acct_flags = ACB_DOMTRUST;
5435 info.info23.password = crypt_pwd;
5437 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5438 &user_pol,
5440 &info);
5442 if (!NT_STATUS_IS_OK(result)) {
5443 DEBUG(0,("Could not set trust account password: %s\n",
5444 nt_errstr(result)));
5445 goto done;
5449 done:
5450 SAFE_FREE(acct_name);
5451 return result;
5455 * Create interdomain trust account for a remote domain.
5457 * @param argc Standard argc.
5458 * @param argv Standard argv without initial components.
5460 * @return Integer status (0 means success).
5463 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5465 if (argc > 0 && !c->display_usage) {
5466 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5467 rpc_trustdom_add_internals, argc, argv);
5468 } else {
5469 d_printf("%s\n%s",
5470 _("Usage:"),
5471 _("net rpc trustdom add <domain_name> <trust "
5472 "password>\n"));
5473 return -1;
5479 * Remove interdomain trust account from the RPC server.
5480 * All parameters (except for argc and argv) are passed by run_rpc_command
5481 * function.
5483 * @param c A net_context structure.
5484 * @param domain_sid The domain sid acquired from the server.
5485 * @param cli A cli_state connected to the server.
5486 * @param mem_ctx Talloc context, destroyed on completion of the function.
5487 * @param argc Standard main() style argc.
5488 * @param argv Standard main() style argv. Initial components are already
5489 * stripped.
5491 * @return normal NTSTATUS return code.
5494 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
5495 const struct dom_sid *domain_sid,
5496 const char *domain_name,
5497 struct cli_state *cli,
5498 struct rpc_pipe_client *pipe_hnd,
5499 TALLOC_CTX *mem_ctx,
5500 int argc,
5501 const char **argv)
5503 struct policy_handle connect_pol, domain_pol, user_pol;
5504 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5505 char *acct_name;
5506 struct dom_sid trust_acct_sid;
5507 struct samr_Ids user_rids, name_types;
5508 struct lsa_String lsa_acct_name;
5510 if (argc != 1) {
5511 d_printf("%s\n%s",
5512 _("Usage:"),
5513 _(" net rpc trustdom del <domain_name>\n"));
5514 return NT_STATUS_INVALID_PARAMETER;
5518 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5520 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5522 if (acct_name == NULL)
5523 return NT_STATUS_NO_MEMORY;
5525 strupper_m(acct_name);
5527 /* Get samr policy handle */
5528 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5529 pipe_hnd->desthost,
5530 MAXIMUM_ALLOWED_ACCESS,
5531 &connect_pol);
5532 if (!NT_STATUS_IS_OK(result)) {
5533 goto done;
5536 /* Get domain policy handle */
5537 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5538 &connect_pol,
5539 MAXIMUM_ALLOWED_ACCESS,
5540 CONST_DISCARD(struct dom_sid2 *, domain_sid),
5541 &domain_pol);
5542 if (!NT_STATUS_IS_OK(result)) {
5543 goto done;
5546 init_lsa_String(&lsa_acct_name, acct_name);
5548 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5549 &domain_pol,
5551 &lsa_acct_name,
5552 &user_rids,
5553 &name_types);
5555 if (!NT_STATUS_IS_OK(result)) {
5556 d_printf(_("net rpc trustdom del: LookupNames on user %s "
5557 "failed %s\n"),
5558 acct_name, nt_errstr(result) );
5559 goto done;
5562 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5563 &domain_pol,
5564 MAXIMUM_ALLOWED_ACCESS,
5565 user_rids.ids[0],
5566 &user_pol);
5568 if (!NT_STATUS_IS_OK(result)) {
5569 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
5570 "%s\n"),
5571 acct_name, nt_errstr(result) );
5572 goto done;
5575 /* append the rid to the domain sid */
5576 if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
5577 goto done;
5580 /* remove the sid */
5582 result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5583 &user_pol,
5584 &trust_acct_sid);
5585 if (!NT_STATUS_IS_OK(result)) {
5586 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
5587 " on user %s failed %s\n"),
5588 acct_name, nt_errstr(result) );
5589 goto done;
5592 /* Delete user */
5594 result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5595 &user_pol);
5597 if (!NT_STATUS_IS_OK(result)) {
5598 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
5599 "%s\n"),
5600 acct_name, nt_errstr(result) );
5601 goto done;
5604 if (!NT_STATUS_IS_OK(result)) {
5605 d_printf(_("Could not set trust account password: %s\n"),
5606 nt_errstr(result));
5607 goto done;
5610 done:
5611 return result;
5615 * Delete interdomain trust account for a remote domain.
5617 * @param argc Standard argc.
5618 * @param argv Standard argv without initial components.
5620 * @return Integer status (0 means success).
5623 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
5625 if (argc > 0 && !c->display_usage) {
5626 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5627 rpc_trustdom_del_internals, argc, argv);
5628 } else {
5629 d_printf("%s\n%s",
5630 _("Usage:"),
5631 _("net rpc trustdom del <domain>\n"));
5632 return -1;
5636 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
5637 struct cli_state *cli,
5638 TALLOC_CTX *mem_ctx,
5639 const char *domain_name)
5641 char *dc_name = NULL;
5642 const char *buffer = NULL;
5643 struct rpc_pipe_client *netr;
5644 NTSTATUS status;
5646 /* Use NetServerEnum2 */
5648 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
5649 SAFE_FREE(dc_name);
5650 return NT_STATUS_OK;
5653 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
5654 for domain %s\n", domain_name));
5656 /* Try netr_GetDcName */
5658 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
5659 &netr);
5660 if (!NT_STATUS_IS_OK(status)) {
5661 return status;
5664 status = rpccli_netr_GetDcName(netr, mem_ctx,
5665 cli->desthost,
5666 domain_name,
5667 &buffer,
5668 NULL);
5669 TALLOC_FREE(netr);
5671 if (NT_STATUS_IS_OK(status)) {
5672 return status;
5675 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
5676 for domain %s\n", domain_name));
5678 return status;
5682 * Establish trust relationship to a trusting domain.
5683 * Interdomain account must already be created on remote PDC.
5685 * @param c A net_context structure.
5686 * @param argc Standard argc.
5687 * @param argv Standard argv without initial components.
5689 * @return Integer status (0 means success).
5692 static int rpc_trustdom_establish(struct net_context *c, int argc,
5693 const char **argv)
5695 struct cli_state *cli = NULL;
5696 struct sockaddr_storage server_ss;
5697 struct rpc_pipe_client *pipe_hnd = NULL;
5698 struct policy_handle connect_hnd;
5699 TALLOC_CTX *mem_ctx;
5700 NTSTATUS nt_status;
5701 struct dom_sid *domain_sid;
5703 char* domain_name;
5704 char* acct_name;
5705 fstring pdc_name;
5706 union lsa_PolicyInformation *info = NULL;
5709 * Connect to \\server\ipc$ as 'our domain' account with password
5712 if (argc != 1 || c->display_usage) {
5713 d_printf("%s\n%s",
5714 _("Usage:"),
5715 _("net rpc trustdom establish <domain_name>\n"));
5716 return -1;
5719 domain_name = smb_xstrdup(argv[0]);
5720 strupper_m(domain_name);
5722 /* account name used at first is our domain's name with '$' */
5723 if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
5724 return -1;
5726 strupper_m(acct_name);
5729 * opt_workgroup will be used by connection functions further,
5730 * hence it should be set to remote domain name instead of ours
5732 if (c->opt_workgroup) {
5733 c->opt_workgroup = smb_xstrdup(domain_name);
5736 c->opt_user_name = acct_name;
5738 /* find the domain controller */
5739 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5740 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5741 return -1;
5744 /* connect to ipc$ as username/password */
5745 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
5746 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5748 /* Is it trusting domain account for sure ? */
5749 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5750 nt_errstr(nt_status)));
5751 return -1;
5754 /* store who we connected to */
5756 saf_store( domain_name, pdc_name );
5759 * Connect to \\server\ipc$ again (this time anonymously)
5762 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
5763 (char*)pdc_name);
5765 if (NT_STATUS_IS_ERR(nt_status)) {
5766 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5767 domain_name, nt_errstr(nt_status)));
5768 return -1;
5771 if (!(mem_ctx = talloc_init("establishing trust relationship to "
5772 "domain %s", domain_name))) {
5773 DEBUG(0, ("talloc_init() failed\n"));
5774 cli_shutdown(cli);
5775 return -1;
5778 /* Make sure we're talking to a proper server */
5780 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
5781 if (!NT_STATUS_IS_OK(nt_status)) {
5782 cli_shutdown(cli);
5783 talloc_destroy(mem_ctx);
5784 return -1;
5788 * Call LsaOpenPolicy and LsaQueryInfo
5791 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5792 &pipe_hnd);
5793 if (!NT_STATUS_IS_OK(nt_status)) {
5794 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5795 cli_shutdown(cli);
5796 talloc_destroy(mem_ctx);
5797 return -1;
5800 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
5801 &connect_hnd);
5802 if (NT_STATUS_IS_ERR(nt_status)) {
5803 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5804 nt_errstr(nt_status)));
5805 cli_shutdown(cli);
5806 talloc_destroy(mem_ctx);
5807 return -1;
5810 /* Querying info level 5 */
5812 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5813 &connect_hnd,
5814 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5815 &info);
5816 if (NT_STATUS_IS_ERR(nt_status)) {
5817 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5818 nt_errstr(nt_status)));
5819 cli_shutdown(cli);
5820 talloc_destroy(mem_ctx);
5821 return -1;
5824 domain_sid = info->account_domain.sid;
5826 /* There should be actually query info level 3 (following nt serv behaviour),
5827 but I still don't know if it's _really_ necessary */
5830 * Store the password in secrets db
5833 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
5834 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5835 cli_shutdown(cli);
5836 talloc_destroy(mem_ctx);
5837 return -1;
5841 * Close the pipes and clean up
5844 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5845 if (NT_STATUS_IS_ERR(nt_status)) {
5846 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5847 nt_errstr(nt_status)));
5848 cli_shutdown(cli);
5849 talloc_destroy(mem_ctx);
5850 return -1;
5853 cli_shutdown(cli);
5855 talloc_destroy(mem_ctx);
5857 d_printf(_("Trust to domain %s established\n"), domain_name);
5858 return 0;
5862 * Revoke trust relationship to the remote domain.
5864 * @param c A net_context structure.
5865 * @param argc Standard argc.
5866 * @param argv Standard argv without initial components.
5868 * @return Integer status (0 means success).
5871 static int rpc_trustdom_revoke(struct net_context *c, int argc,
5872 const char **argv)
5874 char* domain_name;
5875 int rc = -1;
5877 if (argc < 1 || c->display_usage) {
5878 d_printf("%s\n%s",
5879 _("Usage:"),
5880 _("net rpc trustdom revoke <domain_name>\n"
5881 " Revoke trust relationship\n"
5882 " domain_name\tName of domain to revoke trust\n"));
5883 return -1;
5886 /* generate upper cased domain name */
5887 domain_name = smb_xstrdup(argv[0]);
5888 strupper_m(domain_name);
5890 /* delete password of the trust */
5891 if (!pdb_del_trusteddom_pw(domain_name)) {
5892 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
5893 domain_name));
5894 goto done;
5897 rc = 0;
5898 done:
5899 SAFE_FREE(domain_name);
5900 return rc;
5903 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
5904 const struct dom_sid *domain_sid,
5905 const char *domain_name,
5906 struct cli_state *cli,
5907 struct rpc_pipe_client *pipe_hnd,
5908 TALLOC_CTX *mem_ctx,
5909 int argc,
5910 const char **argv)
5912 fstring str_sid;
5913 if (!sid_to_fstring(str_sid, domain_sid)) {
5914 return NT_STATUS_UNSUCCESSFUL;
5916 d_printf("%s\n", str_sid);
5917 return NT_STATUS_OK;
5920 static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
5922 fstring ascii_sid;
5924 /* convert sid into ascii string */
5925 sid_to_fstring(ascii_sid, dom_sid);
5927 d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
5930 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
5931 TALLOC_CTX *mem_ctx,
5932 struct policy_handle *pol,
5933 struct dom_sid dom_sid,
5934 const char *trusted_dom_name)
5936 NTSTATUS nt_status;
5937 union lsa_TrustedDomainInfo *info = NULL;
5938 char *cleartextpwd = NULL;
5939 uint8_t session_key[16];
5940 DATA_BLOB session_key_blob;
5941 DATA_BLOB data = data_blob_null;
5943 nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
5944 pol,
5945 &dom_sid,
5946 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
5947 &info);
5948 if (NT_STATUS_IS_ERR(nt_status)) {
5949 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5950 nt_errstr(nt_status)));
5951 goto done;
5954 data = data_blob(info->password.password->data,
5955 info->password.password->length);
5957 if (!rpccli_get_pwd_hash(pipe_hnd, session_key)) {
5958 DEBUG(0, ("Could not retrieve password hash\n"));
5959 goto done;
5962 session_key_blob = data_blob_const(session_key, sizeof(session_key));
5963 cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key_blob);
5965 if (cleartextpwd == NULL) {
5966 DEBUG(0,("retrieved NULL password\n"));
5967 nt_status = NT_STATUS_UNSUCCESSFUL;
5968 goto done;
5971 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
5972 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5973 nt_status = NT_STATUS_UNSUCCESSFUL;
5974 goto done;
5977 #ifdef DEBUG_PASSWORD
5978 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
5979 "password: [%s]\n", trusted_dom_name,
5980 sid_string_dbg(&dom_sid), cleartextpwd));
5981 #endif
5983 done:
5984 SAFE_FREE(cleartextpwd);
5985 data_blob_free(&data);
5987 return nt_status;
5990 static int rpc_trustdom_vampire(struct net_context *c, int argc,
5991 const char **argv)
5993 /* common variables */
5994 TALLOC_CTX* mem_ctx;
5995 struct cli_state *cli = NULL;
5996 struct rpc_pipe_client *pipe_hnd = NULL;
5997 NTSTATUS nt_status;
5998 const char *domain_name = NULL;
5999 struct dom_sid *queried_dom_sid;
6000 struct policy_handle connect_hnd;
6001 union lsa_PolicyInformation *info = NULL;
6003 /* trusted domains listing variables */
6004 unsigned int enum_ctx = 0;
6005 int i;
6006 struct lsa_DomainList dom_list;
6007 fstring pdc_name;
6009 if (c->display_usage) {
6010 d_printf( "%s\n"
6011 "net rpc trustdom vampire\n"
6012 " %s\n",
6013 _("Usage:"),
6014 _("Vampire trust relationship from remote server"));
6015 return 0;
6019 * Listing trusted domains (stored in secrets.tdb, if local)
6022 mem_ctx = talloc_init("trust relationships vampire");
6025 * set domain and pdc name to local samba server (default)
6026 * or to remote one given in command line
6029 if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6030 domain_name = c->opt_workgroup;
6031 c->opt_target_workgroup = c->opt_workgroup;
6032 } else {
6033 fstrcpy(pdc_name, global_myname());
6034 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6035 c->opt_target_workgroup = domain_name;
6038 /* open \PIPE\lsarpc and open policy handle */
6039 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6040 if (!NT_STATUS_IS_OK(nt_status)) {
6041 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6042 nt_errstr(nt_status)));
6043 talloc_destroy(mem_ctx);
6044 return -1;
6047 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6048 &pipe_hnd);
6049 if (!NT_STATUS_IS_OK(nt_status)) {
6050 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6051 nt_errstr(nt_status) ));
6052 cli_shutdown(cli);
6053 talloc_destroy(mem_ctx);
6054 return -1;
6057 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6058 &connect_hnd);
6059 if (NT_STATUS_IS_ERR(nt_status)) {
6060 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6061 nt_errstr(nt_status)));
6062 cli_shutdown(cli);
6063 talloc_destroy(mem_ctx);
6064 return -1;
6067 /* query info level 5 to obtain sid of a domain being queried */
6068 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6069 &connect_hnd,
6070 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6071 &info);
6073 if (NT_STATUS_IS_ERR(nt_status)) {
6074 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6075 nt_errstr(nt_status)));
6076 cli_shutdown(cli);
6077 talloc_destroy(mem_ctx);
6078 return -1;
6081 queried_dom_sid = info->account_domain.sid;
6084 * Keep calling LsaEnumTrustdom over opened pipe until
6085 * the end of enumeration is reached
6088 d_printf(_("Vampire trusted domains:\n\n"));
6090 do {
6091 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6092 &connect_hnd,
6093 &enum_ctx,
6094 &dom_list,
6095 (uint32_t)-1);
6096 if (NT_STATUS_IS_ERR(nt_status)) {
6097 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6098 nt_errstr(nt_status)));
6099 cli_shutdown(cli);
6100 talloc_destroy(mem_ctx);
6101 return -1;
6104 for (i = 0; i < dom_list.count; i++) {
6106 print_trusted_domain(dom_list.domains[i].sid,
6107 dom_list.domains[i].name.string);
6109 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
6110 *dom_list.domains[i].sid,
6111 dom_list.domains[i].name.string);
6112 if (!NT_STATUS_IS_OK(nt_status)) {
6113 cli_shutdown(cli);
6114 talloc_destroy(mem_ctx);
6115 return -1;
6120 * in case of no trusted domains say something rather
6121 * than just display blank line
6123 if (!dom_list.count) d_printf(_("none\n"));
6125 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6127 /* close this connection before doing next one */
6128 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6129 if (NT_STATUS_IS_ERR(nt_status)) {
6130 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6131 nt_errstr(nt_status)));
6132 cli_shutdown(cli);
6133 talloc_destroy(mem_ctx);
6134 return -1;
6137 /* close lsarpc pipe and connection to IPC$ */
6138 cli_shutdown(cli);
6140 talloc_destroy(mem_ctx);
6141 return 0;
6144 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6146 /* common variables */
6147 TALLOC_CTX* mem_ctx;
6148 struct cli_state *cli = NULL, *remote_cli = NULL;
6149 struct rpc_pipe_client *pipe_hnd = NULL;
6150 NTSTATUS nt_status;
6151 const char *domain_name = NULL;
6152 struct dom_sid *queried_dom_sid;
6153 int ascii_dom_name_len;
6154 struct policy_handle connect_hnd;
6155 union lsa_PolicyInformation *info = NULL;
6157 /* trusted domains listing variables */
6158 unsigned int num_domains, enum_ctx = 0;
6159 int i;
6160 struct lsa_DomainList dom_list;
6161 fstring pdc_name;
6162 bool found_domain;
6164 /* trusting domains listing variables */
6165 struct policy_handle domain_hnd;
6166 struct samr_SamArray *trusts = NULL;
6168 if (c->display_usage) {
6169 d_printf( "%s\n"
6170 "net rpc trustdom list\n"
6171 " %s\n",
6172 _("Usage:"),
6173 _("List incoming and outgoing trust relationships"));
6174 return 0;
6178 * Listing trusted domains (stored in secrets.tdb, if local)
6181 mem_ctx = talloc_init("trust relationships listing");
6184 * set domain and pdc name to local samba server (default)
6185 * or to remote one given in command line
6188 if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6189 domain_name = c->opt_workgroup;
6190 c->opt_target_workgroup = c->opt_workgroup;
6191 } else {
6192 fstrcpy(pdc_name, global_myname());
6193 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6194 c->opt_target_workgroup = domain_name;
6197 /* open \PIPE\lsarpc and open policy handle */
6198 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6199 if (!NT_STATUS_IS_OK(nt_status)) {
6200 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6201 nt_errstr(nt_status)));
6202 talloc_destroy(mem_ctx);
6203 return -1;
6206 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6207 &pipe_hnd);
6208 if (!NT_STATUS_IS_OK(nt_status)) {
6209 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6210 nt_errstr(nt_status) ));
6211 cli_shutdown(cli);
6212 talloc_destroy(mem_ctx);
6213 return -1;
6216 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6217 &connect_hnd);
6218 if (NT_STATUS_IS_ERR(nt_status)) {
6219 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6220 nt_errstr(nt_status)));
6221 cli_shutdown(cli);
6222 talloc_destroy(mem_ctx);
6223 return -1;
6226 /* query info level 5 to obtain sid of a domain being queried */
6227 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6228 &connect_hnd,
6229 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6230 &info);
6232 if (NT_STATUS_IS_ERR(nt_status)) {
6233 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6234 nt_errstr(nt_status)));
6235 cli_shutdown(cli);
6236 talloc_destroy(mem_ctx);
6237 return -1;
6240 queried_dom_sid = info->account_domain.sid;
6243 * Keep calling LsaEnumTrustdom over opened pipe until
6244 * the end of enumeration is reached
6247 d_printf(_("Trusted domains list:\n\n"));
6249 found_domain = false;
6251 do {
6252 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6253 &connect_hnd,
6254 &enum_ctx,
6255 &dom_list,
6256 (uint32_t)-1);
6257 if (NT_STATUS_IS_ERR(nt_status)) {
6258 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6259 nt_errstr(nt_status)));
6260 cli_shutdown(cli);
6261 talloc_destroy(mem_ctx);
6262 return -1;
6265 for (i = 0; i < dom_list.count; i++) {
6266 print_trusted_domain(dom_list.domains[i].sid,
6267 dom_list.domains[i].name.string);
6268 found_domain = true;
6272 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6275 * in case of no trusted domains say something rather
6276 * than just display blank line
6278 if (!found_domain) {
6279 d_printf(_("none\n"));
6282 /* close this connection before doing next one */
6283 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6284 if (NT_STATUS_IS_ERR(nt_status)) {
6285 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6286 nt_errstr(nt_status)));
6287 cli_shutdown(cli);
6288 talloc_destroy(mem_ctx);
6289 return -1;
6292 TALLOC_FREE(pipe_hnd);
6295 * Listing trusting domains (stored in passdb backend, if local)
6298 d_printf(_("\nTrusting domains list:\n\n"));
6301 * Open \PIPE\samr and get needed policy handles
6303 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6304 &pipe_hnd);
6305 if (!NT_STATUS_IS_OK(nt_status)) {
6306 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6307 cli_shutdown(cli);
6308 talloc_destroy(mem_ctx);
6309 return -1;
6312 /* SamrConnect2 */
6313 nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6314 pipe_hnd->desthost,
6315 SAMR_ACCESS_LOOKUP_DOMAIN,
6316 &connect_hnd);
6317 if (!NT_STATUS_IS_OK(nt_status)) {
6318 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6319 nt_errstr(nt_status)));
6320 cli_shutdown(cli);
6321 talloc_destroy(mem_ctx);
6322 return -1;
6325 /* SamrOpenDomain - we have to open domain policy handle in order to be
6326 able to enumerate accounts*/
6327 nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6328 &connect_hnd,
6329 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6330 queried_dom_sid,
6331 &domain_hnd);
6332 if (!NT_STATUS_IS_OK(nt_status)) {
6333 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6334 nt_errstr(nt_status)));
6335 cli_shutdown(cli);
6336 talloc_destroy(mem_ctx);
6337 return -1;
6341 * perform actual enumeration
6344 found_domain = false;
6346 enum_ctx = 0; /* reset enumeration context from last enumeration */
6347 do {
6349 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6350 &domain_hnd,
6351 &enum_ctx,
6352 ACB_DOMTRUST,
6353 &trusts,
6354 0xffff,
6355 &num_domains);
6356 if (NT_STATUS_IS_ERR(nt_status)) {
6357 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6358 nt_errstr(nt_status)));
6359 cli_shutdown(cli);
6360 talloc_destroy(mem_ctx);
6361 return -1;
6364 for (i = 0; i < num_domains; i++) {
6366 char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6368 found_domain = true;
6371 * get each single domain's sid (do we _really_ need this ?):
6372 * 1) connect to domain's pdc
6373 * 2) query the pdc for domain's sid
6376 /* get rid of '$' tail */
6377 ascii_dom_name_len = strlen(str);
6378 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6379 str[ascii_dom_name_len - 1] = '\0';
6381 /* set opt_* variables to remote domain */
6382 strupper_m(str);
6383 c->opt_workgroup = talloc_strdup(mem_ctx, str);
6384 c->opt_target_workgroup = c->opt_workgroup;
6386 d_printf("%-20s", str);
6388 /* connect to remote domain controller */
6389 nt_status = net_make_ipc_connection(c,
6390 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6391 &remote_cli);
6392 if (NT_STATUS_IS_OK(nt_status)) {
6393 /* query for domain's sid */
6394 if (run_rpc_command(
6395 c, remote_cli,
6396 &ndr_table_lsarpc.syntax_id, 0,
6397 rpc_query_domain_sid, argc,
6398 argv))
6399 d_printf(_("strange - couldn't get domain's sid\n"));
6401 cli_shutdown(remote_cli);
6403 } else {
6404 d_fprintf(stderr, _("domain controller is not "
6405 "responding: %s\n"),
6406 nt_errstr(nt_status));
6407 d_printf(_("couldn't get domain's sid\n"));
6411 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6413 if (!found_domain) {
6414 d_printf("none\n");
6417 /* close opened samr and domain policy handles */
6418 nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6419 if (!NT_STATUS_IS_OK(nt_status)) {
6420 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6423 nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6424 if (!NT_STATUS_IS_OK(nt_status)) {
6425 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6428 /* close samr pipe and connection to IPC$ */
6429 cli_shutdown(cli);
6431 talloc_destroy(mem_ctx);
6432 return 0;
6436 * Entrypoint for 'net rpc trustdom' code.
6438 * @param argc Standard argc.
6439 * @param argv Standard argv without initial components.
6441 * @return Integer status (0 means success).
6444 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
6446 struct functable func[] = {
6448 "add",
6449 rpc_trustdom_add,
6450 NET_TRANSPORT_RPC,
6451 N_("Add trusting domain's account"),
6452 N_("net rpc trustdom add\n"
6453 " Add trusting domain's account")
6456 "del",
6457 rpc_trustdom_del,
6458 NET_TRANSPORT_RPC,
6459 N_("Remove trusting domain's account"),
6460 N_("net rpc trustdom del\n"
6461 " Remove trusting domain's account")
6464 "establish",
6465 rpc_trustdom_establish,
6466 NET_TRANSPORT_RPC,
6467 N_("Establish outgoing trust relationship"),
6468 N_("net rpc trustdom establish\n"
6469 " Establish outgoing trust relationship")
6472 "revoke",
6473 rpc_trustdom_revoke,
6474 NET_TRANSPORT_RPC,
6475 N_("Revoke outgoing trust relationship"),
6476 N_("net rpc trustdom revoke\n"
6477 " Revoke outgoing trust relationship")
6480 "list",
6481 rpc_trustdom_list,
6482 NET_TRANSPORT_RPC,
6483 N_("List in- and outgoing domain trusts"),
6484 N_("net rpc trustdom list\n"
6485 " List in- and outgoing domain trusts")
6488 "vampire",
6489 rpc_trustdom_vampire,
6490 NET_TRANSPORT_RPC,
6491 N_("Vampire trusts from remote server"),
6492 N_("net rpc trustdom vampire\n"
6493 " Vampire trusts from remote server")
6495 {NULL, NULL, 0, NULL, NULL}
6498 return net_run_function(c, argc, argv, "net rpc trustdom", func);
6502 * Check if a server will take rpc commands
6503 * @param flags Type of server to connect to (PDC, DMB, localhost)
6504 * if the host is not explicitly specified
6505 * @return bool (true means rpc supported)
6507 bool net_rpc_check(struct net_context *c, unsigned flags)
6509 struct cli_state *cli;
6510 bool ret = false;
6511 struct sockaddr_storage server_ss;
6512 char *server_name = NULL;
6513 NTSTATUS status;
6515 /* flags (i.e. server type) may depend on command */
6516 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
6517 return false;
6519 if ((cli = cli_initialise()) == NULL) {
6520 return false;
6523 status = cli_connect(cli, server_name, &server_ss);
6524 if (!NT_STATUS_IS_OK(status))
6525 goto done;
6526 if (!attempt_netbios_session_request(&cli, global_myname(),
6527 server_name, &server_ss))
6528 goto done;
6529 status = cli_negprot(cli);
6530 if (!NT_STATUS_IS_OK(status))
6531 goto done;
6532 if (cli->protocol < PROTOCOL_NT1)
6533 goto done;
6535 ret = true;
6536 done:
6537 cli_shutdown(cli);
6538 return ret;
6541 /* dump sam database via samsync rpc calls */
6542 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
6543 if (c->display_usage) {
6544 d_printf( "%s\n"
6545 "net rpc samdump\n"
6546 " %s\n",
6547 _("Usage:"),
6548 _("Dump remote SAM database"));
6549 return 0;
6552 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6553 NET_FLAGS_ANONYMOUS,
6554 rpc_samdump_internals, argc, argv);
6557 /* syncronise sam database via samsync rpc calls */
6558 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
6560 struct functable func[] = {
6562 "ldif",
6563 rpc_vampire_ldif,
6564 NET_TRANSPORT_RPC,
6565 N_("Dump remote SAM database to ldif"),
6566 N_("net rpc vampire ldif\n"
6567 " Dump remote SAM database to LDIF file or "
6568 "stdout")
6571 "keytab",
6572 rpc_vampire_keytab,
6573 NET_TRANSPORT_RPC,
6574 N_("Dump remote SAM database to Kerberos Keytab"),
6575 N_("net rpc vampire keytab\n"
6576 " Dump remote SAM database to Kerberos keytab "
6577 "file")
6580 "passdb",
6581 rpc_vampire_passdb,
6582 NET_TRANSPORT_RPC,
6583 N_("Dump remote SAM database to passdb"),
6584 N_("net rpc vampire passdb\n"
6585 " Dump remote SAM database to passdb")
6588 {NULL, NULL, 0, NULL, NULL}
6591 if (argc == 0) {
6592 if (c->display_usage) {
6593 d_printf( "%s\n"
6594 "net rpc vampire\n"
6595 " %s\n",
6596 _("Usage:"),
6597 _("Vampire remote SAM database"));
6598 return 0;
6601 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6602 NET_FLAGS_ANONYMOUS,
6603 rpc_vampire_internals,
6604 argc, argv);
6607 return net_run_function(c, argc, argv, "net rpc vampire", func);
6611 * Migrate everything from a print server.
6613 * @param c A net_context structure.
6614 * @param argc Standard main() style argc.
6615 * @param argv Standard main() style argv. Initial components are already
6616 * stripped.
6618 * @return A shell status integer (0 for success).
6620 * The order is important !
6621 * To successfully add drivers the print queues have to exist !
6622 * Applying ACLs should be the last step, because you're easily locked out.
6625 static int rpc_printer_migrate_all(struct net_context *c, int argc,
6626 const char **argv)
6628 int ret;
6630 if (c->display_usage) {
6631 d_printf( "%s\n"
6632 "net rpc printer migrate all\n"
6633 " %s\n",
6634 _("Usage:"),
6635 _("Migrate everything from a print server"));
6636 return 0;
6639 if (!c->opt_host) {
6640 d_printf(_("no server to migrate\n"));
6641 return -1;
6644 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6645 rpc_printer_migrate_printers_internals, argc,
6646 argv);
6647 if (ret)
6648 return ret;
6650 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6651 rpc_printer_migrate_drivers_internals, argc,
6652 argv);
6653 if (ret)
6654 return ret;
6656 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6657 rpc_printer_migrate_forms_internals, argc, argv);
6658 if (ret)
6659 return ret;
6661 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6662 rpc_printer_migrate_settings_internals, argc,
6663 argv);
6664 if (ret)
6665 return ret;
6667 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6668 rpc_printer_migrate_security_internals, argc,
6669 argv);
6674 * Migrate print drivers from a print server.
6676 * @param c A net_context structure.
6677 * @param argc Standard main() style argc.
6678 * @param argv Standard main() style argv. Initial components are already
6679 * stripped.
6681 * @return A shell status integer (0 for success).
6683 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
6684 const char **argv)
6686 if (c->display_usage) {
6687 d_printf( "%s\n"
6688 "net rpc printer migrate drivers\n"
6689 " %s\n",
6690 _("Usage:"),
6691 _("Migrate print-drivers from a print-server"));
6692 return 0;
6695 if (!c->opt_host) {
6696 d_printf(_("no server to migrate\n"));
6697 return -1;
6700 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6701 rpc_printer_migrate_drivers_internals,
6702 argc, argv);
6706 * Migrate print-forms from a print-server.
6708 * @param c A net_context structure.
6709 * @param argc Standard main() style argc.
6710 * @param argv Standard main() style argv. Initial components are already
6711 * stripped.
6713 * @return A shell status integer (0 for success).
6715 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
6716 const char **argv)
6718 if (c->display_usage) {
6719 d_printf( "%s\n"
6720 "net rpc printer migrate forms\n"
6721 " %s\n",
6722 _("Usage:"),
6723 _("Migrate print-forms from a print-server"));
6724 return 0;
6727 if (!c->opt_host) {
6728 d_printf(_("no server to migrate\n"));
6729 return -1;
6732 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6733 rpc_printer_migrate_forms_internals,
6734 argc, argv);
6738 * Migrate printers from a print-server.
6740 * @param c A net_context structure.
6741 * @param argc Standard main() style argc.
6742 * @param argv Standard main() style argv. Initial components are already
6743 * stripped.
6745 * @return A shell status integer (0 for success).
6747 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
6748 const char **argv)
6750 if (c->display_usage) {
6751 d_printf( "%s\n"
6752 "net rpc printer migrate printers\n"
6753 " %s\n",
6754 _("Usage:"),
6755 _("Migrate printers from a print-server"));
6756 return 0;
6759 if (!c->opt_host) {
6760 d_printf(_("no server to migrate\n"));
6761 return -1;
6764 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6765 rpc_printer_migrate_printers_internals,
6766 argc, argv);
6770 * Migrate printer-ACLs from a print-server
6772 * @param c A net_context structure.
6773 * @param argc Standard main() style argc.
6774 * @param argv Standard main() style argv. Initial components are already
6775 * stripped.
6777 * @return A shell status integer (0 for success).
6779 static int rpc_printer_migrate_security(struct net_context *c, int argc,
6780 const char **argv)
6782 if (c->display_usage) {
6783 d_printf( "%s\n"
6784 "net rpc printer migrate security\n"
6785 " %s\n",
6786 _("Usage:"),
6787 _("Migrate printer-ACLs from a print-server"));
6788 return 0;
6791 if (!c->opt_host) {
6792 d_printf(_("no server to migrate\n"));
6793 return -1;
6796 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6797 rpc_printer_migrate_security_internals,
6798 argc, argv);
6802 * Migrate printer-settings from a print-server.
6804 * @param c A net_context structure.
6805 * @param argc Standard main() style argc.
6806 * @param argv Standard main() style argv. Initial components are already
6807 * stripped.
6809 * @return A shell status integer (0 for success).
6811 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
6812 const char **argv)
6814 if (c->display_usage) {
6815 d_printf( "%s\n"
6816 "net rpc printer migrate settings\n"
6817 " %s\n",
6818 _("Usage:"),
6819 _("Migrate printer-settings from a "
6820 "print-server"));
6821 return 0;
6824 if (!c->opt_host) {
6825 d_printf(_("no server to migrate\n"));
6826 return -1;
6829 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6830 rpc_printer_migrate_settings_internals,
6831 argc, argv);
6835 * 'net rpc printer' entrypoint.
6837 * @param c A net_context structure.
6838 * @param argc Standard main() style argc.
6839 * @param argv Standard main() style argv. Initial components are already
6840 * stripped.
6843 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
6846 /* ouch: when addriver and setdriver are called from within
6847 rpc_printer_migrate_drivers_internals, the printer-queue already
6848 *has* to exist */
6850 struct functable func[] = {
6852 "all",
6853 rpc_printer_migrate_all,
6854 NET_TRANSPORT_RPC,
6855 N_("Migrate all from remote to local print server"),
6856 N_("net rpc printer migrate all\n"
6857 " Migrate all from remote to local print server")
6860 "drivers",
6861 rpc_printer_migrate_drivers,
6862 NET_TRANSPORT_RPC,
6863 N_("Migrate drivers to local server"),
6864 N_("net rpc printer migrate drivers\n"
6865 " Migrate drivers to local server")
6868 "forms",
6869 rpc_printer_migrate_forms,
6870 NET_TRANSPORT_RPC,
6871 N_("Migrate froms to local server"),
6872 N_("net rpc printer migrate forms\n"
6873 " Migrate froms to local server")
6876 "printers",
6877 rpc_printer_migrate_printers,
6878 NET_TRANSPORT_RPC,
6879 N_("Migrate printers to local server"),
6880 N_("net rpc printer migrate printers\n"
6881 " Migrate printers to local server")
6884 "security",
6885 rpc_printer_migrate_security,
6886 NET_TRANSPORT_RPC,
6887 N_("Mirgate printer ACLs to local server"),
6888 N_("net rpc printer migrate security\n"
6889 " Mirgate printer ACLs to local server")
6892 "settings",
6893 rpc_printer_migrate_settings,
6894 NET_TRANSPORT_RPC,
6895 N_("Migrate printer settings to local server"),
6896 N_("net rpc printer migrate settings\n"
6897 " Migrate printer settings to local server")
6899 {NULL, NULL, 0, NULL, NULL}
6902 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
6907 * List printers on a remote RPC server.
6909 * @param c A net_context structure.
6910 * @param argc Standard main() style argc.
6911 * @param argv Standard main() style argv. Initial components are already
6912 * stripped.
6914 * @return A shell status integer (0 for success).
6916 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
6918 if (c->display_usage) {
6919 d_printf( "%s\n"
6920 "net rpc printer list\n"
6921 " %s\n",
6922 _("Usage:"),
6923 _("List printers on a remote RPC server"));
6924 return 0;
6927 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6928 rpc_printer_list_internals,
6929 argc, argv);
6933 * List printer-drivers on a remote RPC server.
6935 * @param c A net_context structure.
6936 * @param argc Standard main() style argc.
6937 * @param argv Standard main() style argv. Initial components are already
6938 * stripped.
6940 * @return A shell status integer (0 for success).
6942 static int rpc_printer_driver_list(struct net_context *c, int argc,
6943 const char **argv)
6945 if (c->display_usage) {
6946 d_printf( "%s\n"
6947 "net rpc printer driver\n"
6948 " %s\n",
6949 _("Usage:"),
6950 _("List printer-drivers on a remote RPC server"));
6951 return 0;
6954 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6955 rpc_printer_driver_list_internals,
6956 argc, argv);
6960 * Publish printer in ADS via MSRPC.
6962 * @param c A net_context structure.
6963 * @param argc Standard main() style argc.
6964 * @param argv Standard main() style argv. Initial components are already
6965 * stripped.
6967 * @return A shell status integer (0 for success).
6969 static int rpc_printer_publish_publish(struct net_context *c, int argc,
6970 const char **argv)
6972 if (c->display_usage) {
6973 d_printf( "%s\n"
6974 "net rpc printer publish publish\n"
6975 " %s\n",
6976 _("Usage:"),
6977 _("Publish printer in ADS via MSRPC"));
6978 return 0;
6981 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6982 rpc_printer_publish_publish_internals,
6983 argc, argv);
6987 * Update printer in ADS via MSRPC.
6989 * @param c A net_context structure.
6990 * @param argc Standard main() style argc.
6991 * @param argv Standard main() style argv. Initial components are already
6992 * stripped.
6994 * @return A shell status integer (0 for success).
6996 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
6998 if (c->display_usage) {
6999 d_printf( "%s\n"
7000 "net rpc printer publish update\n"
7001 " %s\n",
7002 _("Usage:"),
7003 _("Update printer in ADS via MSRPC"));
7004 return 0;
7007 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7008 rpc_printer_publish_update_internals,
7009 argc, argv);
7013 * UnPublish printer in ADS via MSRPC.
7015 * @param c A net_context structure.
7016 * @param argc Standard main() style argc.
7017 * @param argv Standard main() style argv. Initial components are already
7018 * stripped.
7020 * @return A shell status integer (0 for success).
7022 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7023 const char **argv)
7025 if (c->display_usage) {
7026 d_printf( "%s\n"
7027 "net rpc printer publish unpublish\n"
7028 " %s\n",
7029 _("Usage:\n"),
7030 _("UnPublish printer in ADS via MSRPC"));
7031 return 0;
7034 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7035 rpc_printer_publish_unpublish_internals,
7036 argc, argv);
7040 * List published printers via MSRPC.
7042 * @param c A net_context structure.
7043 * @param argc Standard main() style argc.
7044 * @param argv Standard main() style argv. Initial components are already
7045 * stripped.
7047 * @return A shell status integer (0 for success).
7049 static int rpc_printer_publish_list(struct net_context *c, int argc,
7050 const char **argv)
7052 if (c->display_usage) {
7053 d_printf( "%s\n"
7054 "net rpc printer publish list\n"
7055 " %s\n",
7056 _("Usage:"),
7057 _("List published printers via MSRPC"));
7058 return 0;
7061 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7062 rpc_printer_publish_list_internals,
7063 argc, argv);
7068 * Publish printer in ADS.
7070 * @param c A net_context structure.
7071 * @param argc Standard main() style argc.
7072 * @param argv Standard main() style argv. Initial components are already
7073 * stripped.
7075 * @return A shell status integer (0 for success).
7077 static int rpc_printer_publish(struct net_context *c, int argc,
7078 const char **argv)
7081 struct functable func[] = {
7083 "publish",
7084 rpc_printer_publish_publish,
7085 NET_TRANSPORT_RPC,
7086 N_("Publish printer in AD"),
7087 N_("net rpc printer publish publish\n"
7088 " Publish printer in AD")
7091 "update",
7092 rpc_printer_publish_update,
7093 NET_TRANSPORT_RPC,
7094 N_("Update printer in AD"),
7095 N_("net rpc printer publish update\n"
7096 " Update printer in AD")
7099 "unpublish",
7100 rpc_printer_publish_unpublish,
7101 NET_TRANSPORT_RPC,
7102 N_("Unpublish printer"),
7103 N_("net rpc printer publish unpublish\n"
7104 " Unpublish printer")
7107 "list",
7108 rpc_printer_publish_list,
7109 NET_TRANSPORT_RPC,
7110 N_("List published printers"),
7111 N_("net rpc printer publish list\n"
7112 " List published printers")
7114 {NULL, NULL, 0, NULL, NULL}
7117 if (argc == 0) {
7118 if (c->display_usage) {
7119 d_printf(_("Usage:\n"));
7120 d_printf(_("net rpc printer publish\n"
7121 " List published printers\n"
7122 " Alias of net rpc printer publish "
7123 "list\n"));
7124 net_display_usage_from_functable(func);
7125 return 0;
7127 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7128 rpc_printer_publish_list_internals,
7129 argc, argv);
7132 return net_run_function(c, argc, argv, "net rpc printer publish",func);
7138 * Display rpc printer help page.
7140 * @param c A net_context structure.
7141 * @param argc Standard main() style argc.
7142 * @param argv Standard main() style argv. Initial components are already
7143 * stripped.
7145 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
7147 d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
7148 "\tlists all printers on print-server\n\n"));
7149 d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
7150 "\tlists all printer-drivers on print-server\n\n"));
7151 d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
7152 "\tpublishes printer settings in Active Directory\n"
7153 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
7154 d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
7155 "\n\tmigrates printers from remote to local server\n\n"));
7156 d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
7157 "\n\tmigrates printer-settings from remote to local server\n\n"));
7158 d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
7159 "\n\tmigrates printer-drivers from remote to local server\n\n"));
7160 d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
7161 "\n\tmigrates printer-forms from remote to local server\n\n"));
7162 d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
7163 "\n\tmigrates printer-ACLs from remote to local server\n\n"));
7164 d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
7165 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
7166 "\tremote to local print-server\n\n"));
7167 net_common_methods_usage(c, argc, argv);
7168 net_common_flags_usage(c, argc, argv);
7169 d_printf(_(
7170 "\t-v or --verbose\t\t\tgive verbose output\n"
7171 "\t --destination\t\tmigration target server (default: localhost)\n"));
7173 return -1;
7177 * 'net rpc printer' entrypoint.
7179 * @param c A net_context structure.
7180 * @param argc Standard main() style argc.
7181 * @param argv Standard main() style argv. Initial components are already
7182 * stripped.
7184 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7186 struct functable func[] = {
7188 "list",
7189 rpc_printer_list,
7190 NET_TRANSPORT_RPC,
7191 N_("List all printers on print server"),
7192 N_("net rpc printer list\n"
7193 " List all printers on print server")
7196 "migrate",
7197 rpc_printer_migrate,
7198 NET_TRANSPORT_RPC,
7199 N_("Migrate printer to local server"),
7200 N_("net rpc printer migrate\n"
7201 " Migrate printer to local server")
7204 "driver",
7205 rpc_printer_driver_list,
7206 NET_TRANSPORT_RPC,
7207 N_("List printer drivers"),
7208 N_("net rpc printer driver\n"
7209 " List printer drivers")
7212 "publish",
7213 rpc_printer_publish,
7214 NET_TRANSPORT_RPC,
7215 N_("Publish printer in AD"),
7216 N_("net rpc printer publish\n"
7217 " Publish printer in AD")
7219 {NULL, NULL, 0, NULL, NULL}
7222 if (argc == 0) {
7223 if (c->display_usage) {
7224 d_printf(_("Usage:\n"));
7225 d_printf(_("net rpc printer\n"
7226 " List printers\n"));
7227 net_display_usage_from_functable(func);
7228 return 0;
7230 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7231 rpc_printer_list_internals,
7232 argc, argv);
7235 return net_run_function(c, argc, argv, "net rpc printer", func);
7239 * 'net rpc' entrypoint.
7241 * @param c A net_context structure.
7242 * @param argc Standard main() style argc.
7243 * @param argv Standard main() style argv. Initial components are already
7244 * stripped.
7247 int net_rpc(struct net_context *c, int argc, const char **argv)
7249 NET_API_STATUS status;
7251 struct functable func[] = {
7253 "audit",
7254 net_rpc_audit,
7255 NET_TRANSPORT_RPC,
7256 N_("Modify global audit settings"),
7257 N_("net rpc audit\n"
7258 " Modify global audit settings")
7261 "info",
7262 net_rpc_info,
7263 NET_TRANSPORT_RPC,
7264 N_("Show basic info about a domain"),
7265 N_("net rpc info\n"
7266 " Show basic info about a domain")
7269 "join",
7270 net_rpc_join,
7271 NET_TRANSPORT_RPC,
7272 N_("Join a domain"),
7273 N_("net rpc join\n"
7274 " Join a domain")
7277 "oldjoin",
7278 net_rpc_oldjoin,
7279 NET_TRANSPORT_RPC,
7280 N_("Join a domain created in server manager"),
7281 N_("net rpc oldjoin\n"
7282 " Join a domain created in server manager")
7285 "testjoin",
7286 net_rpc_testjoin,
7287 NET_TRANSPORT_RPC,
7288 N_("Test that a join is valid"),
7289 N_("net rpc testjoin\n"
7290 " Test that a join is valid")
7293 "user",
7294 net_rpc_user,
7295 NET_TRANSPORT_RPC,
7296 N_("List/modify users"),
7297 N_("net rpc user\n"
7298 " List/modify users")
7301 "password",
7302 rpc_user_password,
7303 NET_TRANSPORT_RPC,
7304 N_("Change a user password"),
7305 N_("net rpc password\n"
7306 " Change a user password\n"
7307 " Alias for net rpc user password")
7310 "group",
7311 net_rpc_group,
7312 NET_TRANSPORT_RPC,
7313 N_("List/modify groups"),
7314 N_("net rpc group\n"
7315 " List/modify groups")
7318 "share",
7319 net_rpc_share,
7320 NET_TRANSPORT_RPC,
7321 N_("List/modify shares"),
7322 N_("net rpc share\n"
7323 " List/modify shares")
7326 "file",
7327 net_rpc_file,
7328 NET_TRANSPORT_RPC,
7329 N_("List open files"),
7330 N_("net rpc file\n"
7331 " List open files")
7334 "printer",
7335 net_rpc_printer,
7336 NET_TRANSPORT_RPC,
7337 N_("List/modify printers"),
7338 N_("net rpc printer\n"
7339 " List/modify printers")
7342 "changetrustpw",
7343 net_rpc_changetrustpw,
7344 NET_TRANSPORT_RPC,
7345 N_("Change trust account password"),
7346 N_("net rpc changetrustpw\n"
7347 " Change trust account password")
7350 "trustdom",
7351 rpc_trustdom,
7352 NET_TRANSPORT_RPC,
7353 N_("Modify domain trusts"),
7354 N_("net rpc trustdom\n"
7355 " Modify domain trusts")
7358 "abortshutdown",
7359 rpc_shutdown_abort,
7360 NET_TRANSPORT_RPC,
7361 N_("Abort a remote shutdown"),
7362 N_("net rpc abortshutdown\n"
7363 " Abort a remote shutdown")
7366 "shutdown",
7367 rpc_shutdown,
7368 NET_TRANSPORT_RPC,
7369 N_("Shutdown a remote server"),
7370 N_("net rpc shutdown\n"
7371 " Shutdown a remote server")
7374 "samdump",
7375 rpc_samdump,
7376 NET_TRANSPORT_RPC,
7377 N_("Dump SAM data of remote NT PDC"),
7378 N_("net rpc samdump\n"
7379 " Dump SAM data of remote NT PDC")
7382 "vampire",
7383 rpc_vampire,
7384 NET_TRANSPORT_RPC,
7385 N_("Sync a remote NT PDC's data into local passdb"),
7386 N_("net rpc vampire\n"
7387 " Sync a remote NT PDC's data into local passdb")
7390 "getsid",
7391 net_rpc_getsid,
7392 NET_TRANSPORT_RPC,
7393 N_("Fetch the domain sid into local secrets.tdb"),
7394 N_("net rpc getsid\n"
7395 " Fetch the domain sid into local secrets.tdb")
7398 "rights",
7399 net_rpc_rights,
7400 NET_TRANSPORT_RPC,
7401 N_("Manage privileges assigned to SID"),
7402 N_("net rpc rights\n"
7403 " Manage privileges assigned to SID")
7406 "service",
7407 net_rpc_service,
7408 NET_TRANSPORT_RPC,
7409 N_("Start/stop/query remote services"),
7410 N_("net rpc service\n"
7411 " Start/stop/query remote services")
7414 "registry",
7415 net_rpc_registry,
7416 NET_TRANSPORT_RPC,
7417 N_("Manage registry hives"),
7418 N_("net rpc registry\n"
7419 " Manage registry hives")
7422 "shell",
7423 net_rpc_shell,
7424 NET_TRANSPORT_RPC,
7425 N_("Open interactive shell on remote server"),
7426 N_("net rpc shell\n"
7427 " Open interactive shell on remote server")
7429 {NULL, NULL, 0, NULL, NULL}
7432 status = libnetapi_net_init(&c->netapi_ctx);
7433 if (status != 0) {
7434 return -1;
7436 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
7437 libnetapi_set_password(c->netapi_ctx, c->opt_password);
7438 if (c->opt_kerberos) {
7439 libnetapi_set_use_kerberos(c->netapi_ctx);
7441 if (c->opt_ccache) {
7442 libnetapi_set_use_ccache(c->netapi_ctx);
7445 return net_run_function(c, argc, argv, "net rpc", func);