ѕ3: fix domain trust documentation confusion
[Samba/fernandojvsilva.git] / source3 / utils / net_rpc.c
blobc3d002c1b104c8675800bdabeb2dd0e8de602267
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"
27 static int net_mode_share;
28 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask);
30 /**
31 * @file net_rpc.c
33 * @brief RPC based subcommands for the 'net' utility.
35 * This file should contain much of the functionality that used to
36 * be found in rpcclient, execpt that the commands should change
37 * less often, and the fucntionality should be sane (the user is not
38 * expected to know a rid/sid before they conduct an operation etc.)
40 * @todo Perhaps eventually these should be split out into a number
41 * of files, as this could get quite big.
42 **/
45 /**
46 * Many of the RPC functions need the domain sid. This function gets
47 * it at the start of every run
49 * @param cli A cli_state already connected to the remote machine
51 * @return The Domain SID of the remote machine.
52 **/
54 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
55 DOM_SID **domain_sid,
56 const char **domain_name)
58 struct rpc_pipe_client *lsa_pipe = NULL;
59 struct policy_handle pol;
60 NTSTATUS result = NT_STATUS_OK;
61 union lsa_PolicyInformation *info = NULL;
63 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
64 &lsa_pipe);
65 if (!NT_STATUS_IS_OK(result)) {
66 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
67 return result;
70 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
71 SEC_FLAG_MAXIMUM_ALLOWED,
72 &pol);
73 if (!NT_STATUS_IS_OK(result)) {
74 d_fprintf(stderr, _("open_policy failed: %s\n"),
75 nt_errstr(result));
76 return result;
79 result = rpccli_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx,
80 &pol,
81 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
82 &info);
83 if (!NT_STATUS_IS_OK(result)) {
84 d_fprintf(stderr, _("lsaquery failed: %s\n"),
85 nt_errstr(result));
86 return result;
89 *domain_name = info->account_domain.name.string;
90 *domain_sid = info->account_domain.sid;
92 rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
93 TALLOC_FREE(lsa_pipe);
95 return NT_STATUS_OK;
98 /**
99 * Run a single RPC command, from start to finish.
101 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
102 * @param conn_flag a NET_FLAG_ combination. Passed to
103 * net_make_ipc_connection.
104 * @param argc Standard main() style argc.
105 * @param argv Standard main() style argv. Initial components are already
106 * stripped.
107 * @return A shell status integer (0 for success).
110 int run_rpc_command(struct net_context *c,
111 struct cli_state *cli_arg,
112 const struct ndr_syntax_id *interface,
113 int conn_flags,
114 rpc_command_fn fn,
115 int argc,
116 const char **argv)
118 struct cli_state *cli = NULL;
119 struct rpc_pipe_client *pipe_hnd = NULL;
120 TALLOC_CTX *mem_ctx;
121 NTSTATUS nt_status;
122 DOM_SID *domain_sid;
123 const char *domain_name;
124 int ret = -1;
126 /* make use of cli_state handed over as an argument, if possible */
127 if (!cli_arg) {
128 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
129 if (!NT_STATUS_IS_OK(nt_status)) {
130 DEBUG(1, ("failed to make ipc connection: %s\n",
131 nt_errstr(nt_status)));
132 return -1;
134 } else {
135 cli = cli_arg;
138 if (!cli) {
139 return -1;
142 /* Create mem_ctx */
144 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
145 DEBUG(0, ("talloc_init() failed\n"));
146 goto fail;
149 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
150 &domain_name);
151 if (!NT_STATUS_IS_OK(nt_status)) {
152 goto fail;
155 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
156 if (lp_client_schannel()
157 && (ndr_syntax_id_equal(interface,
158 &ndr_table_netlogon.syntax_id))) {
159 /* Always try and create an schannel netlogon pipe. */
160 nt_status = cli_rpc_pipe_open_schannel(
161 cli, interface, NCACN_NP,
162 DCERPC_AUTH_LEVEL_PRIVACY, domain_name,
163 &pipe_hnd);
164 if (!NT_STATUS_IS_OK(nt_status)) {
165 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
166 nt_errstr(nt_status) ));
167 goto fail;
169 } else {
170 if (conn_flags & NET_FLAGS_SEAL) {
171 nt_status = cli_rpc_pipe_open_ntlmssp(
172 cli, interface,
173 (conn_flags & NET_FLAGS_TCP) ?
174 NCACN_IP_TCP : NCACN_NP,
175 DCERPC_AUTH_LEVEL_PRIVACY,
176 lp_workgroup(), c->opt_user_name,
177 c->opt_password, &pipe_hnd);
178 } else {
179 nt_status = cli_rpc_pipe_open_noauth(
180 cli, interface,
181 &pipe_hnd);
183 if (!NT_STATUS_IS_OK(nt_status)) {
184 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
185 get_pipe_name_from_iface(interface),
186 nt_errstr(nt_status) ));
187 goto fail;
192 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
194 if (!NT_STATUS_IS_OK(nt_status)) {
195 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
196 } else {
197 ret = 0;
198 DEBUG(5, ("rpc command function succedded\n"));
201 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
202 if (pipe_hnd) {
203 TALLOC_FREE(pipe_hnd);
207 fail:
208 /* close the connection only if it was opened here */
209 if (!cli_arg) {
210 cli_shutdown(cli);
213 talloc_destroy(mem_ctx);
214 return ret;
218 * Force a change of the trust acccount password.
220 * All parameters are provided by the run_rpc_command function, except for
221 * argc, argv which are passed through.
223 * @param domain_sid The domain sid acquired from the remote server.
224 * @param cli A cli_state connected to the server.
225 * @param mem_ctx Talloc context, destroyed on completion of the function.
226 * @param argc Standard main() style argc.
227 * @param argv Standard main() style argv. Initial components are already
228 * stripped.
230 * @return Normal NTSTATUS return.
233 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
234 const DOM_SID *domain_sid,
235 const char *domain_name,
236 struct cli_state *cli,
237 struct rpc_pipe_client *pipe_hnd,
238 TALLOC_CTX *mem_ctx,
239 int argc,
240 const char **argv)
242 NTSTATUS status;
244 status = trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
245 if (!NT_STATUS_IS_OK(status)) {
246 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
247 nt_errstr(status));
248 return status;
251 return NT_STATUS_OK;
255 * Force a change of the trust acccount password.
257 * @param argc Standard main() style argc.
258 * @param argv Standard main() style argv. Initial components are already
259 * stripped.
261 * @return A shell status integer (0 for success).
264 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
266 if (c->display_usage) {
267 d_printf(_("Usage:\n"
268 "net rpc changetrustpw\n"
269 " Change the machine trust password\n"));
270 return 0;
273 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
274 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
275 rpc_changetrustpw_internals,
276 argc, argv);
280 * Join a domain, the old way.
282 * This uses 'machinename' as the inital password, and changes it.
284 * The password should be created with 'server manager' or equiv first.
286 * All parameters are provided by the run_rpc_command function, except for
287 * argc, argv which are passed through.
289 * @param domain_sid The domain sid acquired from the remote server.
290 * @param cli A cli_state connected to the server.
291 * @param mem_ctx Talloc context, destroyed on completion of the function.
292 * @param argc Standard main() style argc.
293 * @param argv Standard main() style argv. Initial components are already
294 * stripped.
296 * @return Normal NTSTATUS return.
299 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
300 const DOM_SID *domain_sid,
301 const char *domain_name,
302 struct cli_state *cli,
303 struct rpc_pipe_client *pipe_hnd,
304 TALLOC_CTX *mem_ctx,
305 int argc,
306 const char **argv)
309 fstring trust_passwd;
310 unsigned char orig_trust_passwd_hash[16];
311 NTSTATUS result;
312 uint32 sec_channel_type;
314 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
315 &pipe_hnd);
316 if (!NT_STATUS_IS_OK(result)) {
317 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
318 "error was %s\n",
319 cli->desthost,
320 nt_errstr(result) ));
321 return result;
325 check what type of join - if the user want's to join as
326 a BDC, the server must agree that we are a BDC.
328 if (argc >= 0) {
329 sec_channel_type = get_sec_channel_type(argv[0]);
330 } else {
331 sec_channel_type = get_sec_channel_type(NULL);
334 fstrcpy(trust_passwd, global_myname());
335 strlower_m(trust_passwd);
338 * Machine names can be 15 characters, but the max length on
339 * a password is 14. --jerry
342 trust_passwd[14] = '\0';
344 E_md4hash(trust_passwd, orig_trust_passwd_hash);
346 result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
347 orig_trust_passwd_hash,
348 sec_channel_type);
350 if (NT_STATUS_IS_OK(result))
351 printf(_("Joined domain %s.\n"), c->opt_target_workgroup);
354 if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
355 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
356 result = NT_STATUS_UNSUCCESSFUL;
359 return result;
363 * Join a domain, the old way.
365 * @param argc Standard main() style argc.
366 * @param argv Standard main() style argv. Initial components are already
367 * stripped.
369 * @return A shell status integer (0 for success).
372 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
374 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
375 NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
376 rpc_oldjoin_internals,
377 argc, argv);
381 * Join a domain, the old way. This function exists to allow
382 * the message to be displayed when oldjoin was explicitly
383 * requested, but not when it was implied by "net rpc join".
385 * @param argc Standard main() style argc.
386 * @param argv Standard main() style argv. Initial components are already
387 * stripped.
389 * @return A shell status integer (0 for success).
392 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
394 int rc = -1;
396 if (c->display_usage) {
397 d_printf(_("Usage:\n"
398 "net rpc oldjoin\n"
399 " Join a domain the old way\n"));
400 return 0;
403 rc = net_rpc_perform_oldjoin(c, argc, argv);
405 if (rc) {
406 d_fprintf(stderr, _("Failed to join domain\n"));
409 return rc;
413 * 'net rpc join' entrypoint.
414 * @param argc Standard main() style argc.
415 * @param argv Standard main() style argv. Initial components are already
416 * stripped
418 * Main 'net_rpc_join()' (where the admin username/password is used) is
419 * in net_rpc_join.c.
420 * Try to just change the password, but if that doesn't work, use/prompt
421 * for a username/password.
424 int net_rpc_join(struct net_context *c, int argc, const char **argv)
426 if (c->display_usage) {
427 d_printf(_("Usage:\n"
428 "net rpc join -U <username>[%%password] <type>\n"
429 " Join a domain\n"
430 " username\tName of the admin user"
431 " password\tPassword of the admin user, will "
432 "prompt if not specified\n"
433 " type\tCan be one of the following:\n"
434 "\t\tMEMBER\tJoin as member server (default)\n"
435 "\t\tBDC\tJoin as BDC\n"
436 "\t\tPDC\tJoin as PDC\n"));
437 return 0;
440 if (lp_server_role() == ROLE_STANDALONE) {
441 d_printf(_("cannot join as standalone machine\n"));
442 return -1;
445 if (strlen(global_myname()) > 15) {
446 d_printf(_("Our netbios name can be at most 15 chars long, "
447 "\"%s\" is %u chars long\n"),
448 global_myname(), (unsigned int)strlen(global_myname()));
449 return -1;
452 if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
453 return 0;
455 return net_rpc_join_newstyle(c, argc, argv);
459 * display info about a rpc domain
461 * All parameters are provided by the run_rpc_command function, except for
462 * argc, argv which are passed through.
464 * @param domain_sid The domain sid acquired from the remote server
465 * @param cli A cli_state connected to the server.
466 * @param mem_ctx Talloc context, destroyed on completion of the function.
467 * @param argc Standard main() style argc.
468 * @param argv Standard main() style argv. Initial components are already
469 * stripped.
471 * @return Normal NTSTATUS return.
474 NTSTATUS rpc_info_internals(struct net_context *c,
475 const DOM_SID *domain_sid,
476 const char *domain_name,
477 struct cli_state *cli,
478 struct rpc_pipe_client *pipe_hnd,
479 TALLOC_CTX *mem_ctx,
480 int argc,
481 const char **argv)
483 struct policy_handle connect_pol, domain_pol;
484 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
485 union samr_DomainInfo *info = NULL;
486 fstring sid_str;
488 sid_to_fstring(sid_str, domain_sid);
490 /* Get sam policy handle */
491 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
492 pipe_hnd->desthost,
493 MAXIMUM_ALLOWED_ACCESS,
494 &connect_pol);
495 if (!NT_STATUS_IS_OK(result)) {
496 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
497 nt_errstr(result));
498 goto done;
501 /* Get domain policy handle */
502 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
503 &connect_pol,
504 MAXIMUM_ALLOWED_ACCESS,
505 CONST_DISCARD(struct dom_sid2 *, domain_sid),
506 &domain_pol);
507 if (!NT_STATUS_IS_OK(result)) {
508 d_fprintf(stderr, _("Could not open domain: %s\n"),
509 nt_errstr(result));
510 goto done;
513 result = rpccli_samr_QueryDomainInfo(pipe_hnd, mem_ctx,
514 &domain_pol,
516 &info);
517 if (NT_STATUS_IS_OK(result)) {
518 d_printf(_("Domain Name: %s\n"),
519 info->general.domain_name.string);
520 d_printf(_("Domain SID: %s\n"), sid_str);
521 d_printf(_("Sequence number: %llu\n"),
522 (unsigned long long)info->general.sequence_num);
523 d_printf(_("Num users: %u\n"), info->general.num_users);
524 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
525 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
528 done:
529 return result;
533 * 'net rpc info' entrypoint.
534 * @param argc Standard main() style argc.
535 * @param argv Standard main() style argv. Initial components are already
536 * stripped.
539 int net_rpc_info(struct net_context *c, int argc, const char **argv)
541 if (c->display_usage) {
542 d_printf(_("Usage:\n"
543 "net rpc info\n"
544 " Display information about the domain\n"));
545 return 0;
548 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
549 NET_FLAGS_PDC, rpc_info_internals,
550 argc, argv);
554 * Fetch domain SID into the local secrets.tdb.
556 * All parameters are provided by the run_rpc_command function, except for
557 * argc, argv which are passed through.
559 * @param domain_sid The domain sid acquired from the remote server.
560 * @param cli A cli_state connected to the server.
561 * @param mem_ctx Talloc context, destroyed on completion of the function.
562 * @param argc Standard main() style argc.
563 * @param argv Standard main() style argv. Initial components are already
564 * stripped.
566 * @return Normal NTSTATUS return.
569 static NTSTATUS rpc_getsid_internals(struct net_context *c,
570 const DOM_SID *domain_sid,
571 const char *domain_name,
572 struct cli_state *cli,
573 struct rpc_pipe_client *pipe_hnd,
574 TALLOC_CTX *mem_ctx,
575 int argc,
576 const char **argv)
578 fstring sid_str;
580 sid_to_fstring(sid_str, domain_sid);
581 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
582 sid_str, domain_name);
584 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
585 DEBUG(0,("Can't store domain SID\n"));
586 return NT_STATUS_UNSUCCESSFUL;
589 return NT_STATUS_OK;
593 * 'net rpc getsid' entrypoint.
594 * @param argc Standard main() style argc.
595 * @param argv Standard main() style argv. Initial components are already
596 * stripped.
599 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
601 if (c->display_usage) {
602 d_printf(_("Usage:\n"
603 "net rpc getsid\n"
604 " Fetch domain SID into local secrets.tdb\n"));
605 return 0;
608 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
609 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
610 rpc_getsid_internals,
611 argc, argv);
614 /****************************************************************************/
617 * Basic usage function for 'net rpc user'.
618 * @param argc Standard main() style argc.
619 * @param argv Standard main() style argv. Initial components are already
620 * stripped.
623 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
625 return net_user_usage(c, argc, argv);
629 * Add a new user to a remote RPC server.
631 * @param argc Standard main() style argc.
632 * @param argv Standard main() style argv. Initial components are already
633 * stripped.
635 * @return A shell status integer (0 for success).
638 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
640 NET_API_STATUS status;
641 struct USER_INFO_1 info1;
642 uint32_t parm_error = 0;
644 if (argc < 1 || c->display_usage) {
645 rpc_user_usage(c, argc, argv);
646 return 0;
649 ZERO_STRUCT(info1);
651 info1.usri1_name = argv[0];
652 if (argc == 2) {
653 info1.usri1_password = argv[1];
656 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
658 if (status != 0) {
659 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
660 argv[0], libnetapi_get_error_string(c->netapi_ctx,
661 status));
662 return -1;
663 } else {
664 d_printf(_("Added user '%s'.\n"), argv[0]);
667 return 0;
671 * Rename a user on a remote RPC server.
673 * @param argc Standard main() style argc.
674 * @param argv Standard main() style argv. Initial components are already
675 * stripped.
677 * @return A shell status integer (0 for success).
680 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
682 NET_API_STATUS status;
683 struct USER_INFO_0 u0;
684 uint32_t parm_err = 0;
686 if (argc != 2 || c->display_usage) {
687 rpc_user_usage(c, argc, argv);
688 return 0;
691 u0.usri0_name = argv[1];
693 status = NetUserSetInfo(c->opt_host, argv[0],
694 0, (uint8_t *)&u0, &parm_err);
695 if (status) {
696 d_fprintf(stderr,
697 _("Failed to rename user from %s to %s - %s\n"),
698 argv[0], argv[1],
699 libnetapi_get_error_string(c->netapi_ctx, status));
700 } else {
701 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
704 return status;
708 * Delete a user from a remote RPC server.
710 * @param argc Standard main() style argc.
711 * @param argv Standard main() style argv. Initial components are already
712 * stripped.
714 * @return A shell status integer (0 for success).
717 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
719 NET_API_STATUS status;
721 if (argc < 1 || c->display_usage) {
722 rpc_user_usage(c, argc, argv);
723 return 0;
726 status = NetUserDel(c->opt_host, argv[0]);
728 if (status != 0) {
729 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
730 argv[0],
731 libnetapi_get_error_string(c->netapi_ctx, status));
732 return -1;
733 } else {
734 d_printf(_("Deleted user '%s'.\n"), argv[0]);
737 return 0;
741 * Set a user's password on a remote RPC server.
743 * @param argc Standard main() style argc.
744 * @param argv Standard main() style argv. Initial components are already
745 * stripped.
747 * @return A shell status integer (0 for success).
750 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
752 NET_API_STATUS status;
753 char *prompt = NULL;
754 struct USER_INFO_1003 u1003;
755 uint32_t parm_err = 0;
756 int ret;
758 if (argc < 1 || c->display_usage) {
759 rpc_user_usage(c, argc, argv);
760 return 0;
763 if (argv[1]) {
764 u1003.usri1003_password = argv[1];
765 } else {
766 ret = asprintf(&prompt, _("Enter new password for %s:"),
767 argv[0]);
768 if (ret == -1) {
769 return -1;
771 u1003.usri1003_password = getpass(prompt);
772 SAFE_FREE(prompt);
775 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
777 /* Display results */
778 if (status != 0) {
779 d_fprintf(stderr,
780 _("Failed to set password for '%s' with error: %s.\n"),
781 argv[0], libnetapi_get_error_string(c->netapi_ctx,
782 status));
783 return -1;
786 return 0;
790 * List a user's groups from a remote RPC server.
792 * @param argc Standard main() style argc.
793 * @param argv Standard main() style argv. Initial components are already
794 * stripped.
796 * @return A shell status integer (0 for success)
799 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
802 NET_API_STATUS status;
803 struct GROUP_USERS_INFO_0 *u0 = NULL;
804 uint32_t entries_read = 0;
805 uint32_t total_entries = 0;
806 int i;
809 if (argc < 1 || c->display_usage) {
810 rpc_user_usage(c, argc, argv);
811 return 0;
814 status = NetUserGetGroups(c->opt_host,
815 argv[0],
817 (uint8_t **)(void *)&u0,
818 (uint32_t)-1,
819 &entries_read,
820 &total_entries);
821 if (status != 0) {
822 d_fprintf(stderr,
823 _("Failed to get groups for '%s' with error: %s.\n"),
824 argv[0], libnetapi_get_error_string(c->netapi_ctx,
825 status));
826 return -1;
829 for (i=0; i < entries_read; i++) {
830 printf("%s\n", u0->grui0_name);
831 u0++;
834 return 0;
838 * List users on a remote RPC server.
840 * All parameters are provided by the run_rpc_command function, except for
841 * argc, argv which are passed through.
843 * @param domain_sid The domain sid acquired from the remote server.
844 * @param cli A cli_state connected to the server.
845 * @param mem_ctx Talloc context, destroyed on completion of the function.
846 * @param argc Standard main() style argc.
847 * @param argv Standard main() style argv. Initial components are already
848 * stripped.
850 * @return Normal NTSTATUS return.
853 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
855 NET_API_STATUS status;
856 uint32_t start_idx=0, num_entries, i, loop_count = 0;
857 struct NET_DISPLAY_USER *info = NULL;
858 void *buffer = NULL;
860 /* Query domain users */
861 if (c->opt_long_list_entries)
862 d_printf(_("\nUser name Comment"
863 "\n-----------------------------\n"));
864 do {
865 uint32_t max_entries, max_size;
867 get_query_dispinfo_params(
868 loop_count, &max_entries, &max_size);
870 status = NetQueryDisplayInformation(c->opt_host,
872 start_idx,
873 max_entries,
874 max_size,
875 &num_entries,
876 &buffer);
877 if (status != 0 && status != ERROR_MORE_DATA) {
878 return status;
881 info = (struct NET_DISPLAY_USER *)buffer;
883 for (i = 0; i < num_entries; i++) {
885 if (c->opt_long_list_entries)
886 printf("%-21.21s %s\n", info->usri1_name,
887 info->usri1_comment);
888 else
889 printf("%s\n", info->usri1_name);
890 info++;
893 NetApiBufferFree(buffer);
895 loop_count++;
896 start_idx += num_entries;
898 } while (status == ERROR_MORE_DATA);
900 return status;
904 * 'net rpc user' entrypoint.
905 * @param argc Standard main() style argc.
906 * @param argv Standard main() style argv. Initial components are already
907 * stripped.
910 int net_rpc_user(struct net_context *c, int argc, const char **argv)
912 NET_API_STATUS status;
914 struct functable func[] = {
916 "add",
917 rpc_user_add,
918 NET_TRANSPORT_RPC,
919 N_("Add specified user"),
920 N_("net rpc user add\n"
921 " Add specified user")
924 "info",
925 rpc_user_info,
926 NET_TRANSPORT_RPC,
927 N_("List domain groups of user"),
928 N_("net rpc user info\n"
929 " Lis domain groups of user")
932 "delete",
933 rpc_user_delete,
934 NET_TRANSPORT_RPC,
935 N_("Remove specified user"),
936 N_("net rpc user delete\n"
937 " Remove specified user")
940 "password",
941 rpc_user_password,
942 NET_TRANSPORT_RPC,
943 N_("Change user password"),
944 N_("net rpc user password\n"
945 " Change user password")
948 "rename",
949 rpc_user_rename,
950 NET_TRANSPORT_RPC,
951 N_("Rename specified user"),
952 N_("net rpc user rename\n"
953 " Rename specified user")
955 {NULL, NULL, 0, NULL, NULL}
958 status = libnetapi_init(&c->netapi_ctx);
959 if (status != 0) {
960 return -1;
962 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
963 libnetapi_set_password(c->netapi_ctx, c->opt_password);
964 if (c->opt_kerberos) {
965 libnetapi_set_use_kerberos(c->netapi_ctx);
968 if (argc == 0) {
969 if (c->display_usage) {
970 d_printf(_("Usage:\n"));
971 d_printf(_("net rpc user\n"
972 " List all users\n"));
973 net_display_usage_from_functable(func);
974 return 0;
977 return rpc_user_list(c, argc, argv);
980 return net_run_function(c, argc, argv, "net rpc user", func);
983 static NTSTATUS rpc_sh_user_list(struct net_context *c,
984 TALLOC_CTX *mem_ctx,
985 struct rpc_sh_ctx *ctx,
986 struct rpc_pipe_client *pipe_hnd,
987 int argc, const char **argv)
989 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
992 static NTSTATUS rpc_sh_user_info(struct net_context *c,
993 TALLOC_CTX *mem_ctx,
994 struct rpc_sh_ctx *ctx,
995 struct rpc_pipe_client *pipe_hnd,
996 int argc, const char **argv)
998 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1001 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1002 TALLOC_CTX *mem_ctx,
1003 struct rpc_sh_ctx *ctx,
1004 struct rpc_pipe_client *pipe_hnd,
1005 int argc, const char **argv,
1006 NTSTATUS (*fn)(
1007 struct net_context *c,
1008 TALLOC_CTX *mem_ctx,
1009 struct rpc_sh_ctx *ctx,
1010 struct rpc_pipe_client *pipe_hnd,
1011 struct policy_handle *user_hnd,
1012 int argc, const char **argv))
1014 struct policy_handle connect_pol, domain_pol, user_pol;
1015 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1016 DOM_SID sid;
1017 uint32 rid;
1018 enum lsa_SidType type;
1020 if (argc == 0) {
1021 d_fprintf(stderr, _("usage: %s <username>\n"), ctx->whoami);
1022 return NT_STATUS_INVALID_PARAMETER;
1025 ZERO_STRUCT(connect_pol);
1026 ZERO_STRUCT(domain_pol);
1027 ZERO_STRUCT(user_pol);
1029 result = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1030 argv[0], NULL, NULL, &sid, &type);
1031 if (!NT_STATUS_IS_OK(result)) {
1032 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1033 nt_errstr(result));
1034 goto done;
1037 if (type != SID_NAME_USER) {
1038 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1039 sid_type_lookup(type));
1040 result = NT_STATUS_NO_SUCH_USER;
1041 goto done;
1044 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1045 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1046 result = NT_STATUS_NO_SUCH_USER;
1047 goto done;
1050 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1051 pipe_hnd->desthost,
1052 MAXIMUM_ALLOWED_ACCESS,
1053 &connect_pol);
1054 if (!NT_STATUS_IS_OK(result)) {
1055 goto done;
1058 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1059 &connect_pol,
1060 MAXIMUM_ALLOWED_ACCESS,
1061 ctx->domain_sid,
1062 &domain_pol);
1063 if (!NT_STATUS_IS_OK(result)) {
1064 goto done;
1067 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1068 &domain_pol,
1069 MAXIMUM_ALLOWED_ACCESS,
1070 rid,
1071 &user_pol);
1072 if (!NT_STATUS_IS_OK(result)) {
1073 goto done;
1076 result = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1078 done:
1079 if (is_valid_policy_hnd(&user_pol)) {
1080 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1082 if (is_valid_policy_hnd(&domain_pol)) {
1083 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
1085 if (is_valid_policy_hnd(&connect_pol)) {
1086 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1088 return result;
1091 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1092 TALLOC_CTX *mem_ctx,
1093 struct rpc_sh_ctx *ctx,
1094 struct rpc_pipe_client *pipe_hnd,
1095 struct policy_handle *user_hnd,
1096 int argc, const char **argv)
1098 NTSTATUS result;
1099 union samr_UserInfo *info = NULL;
1101 if (argc != 0) {
1102 d_fprintf(stderr, _("usage: %s show <username>\n"),ctx->whoami);
1103 return NT_STATUS_INVALID_PARAMETER;
1106 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1107 user_hnd,
1109 &info);
1110 if (!NT_STATUS_IS_OK(result)) {
1111 return result;
1114 d_printf(_("user rid: %d, group rid: %d\n"),
1115 info->info21.rid,
1116 info->info21.primary_gid);
1118 return result;
1121 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1122 TALLOC_CTX *mem_ctx,
1123 struct rpc_sh_ctx *ctx,
1124 struct rpc_pipe_client *pipe_hnd,
1125 int argc, const char **argv)
1127 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1128 rpc_sh_user_show_internals);
1131 #define FETCHSTR(name, rec) \
1132 do { if (strequal(ctx->thiscmd, name)) { \
1133 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1134 } while (0);
1136 #define SETSTR(name, rec, flag) \
1137 do { if (strequal(ctx->thiscmd, name)) { \
1138 init_lsa_String(&(info->info21.rec), argv[0]); \
1139 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1140 } while (0);
1142 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1143 TALLOC_CTX *mem_ctx,
1144 struct rpc_sh_ctx *ctx,
1145 struct rpc_pipe_client *pipe_hnd,
1146 struct policy_handle *user_hnd,
1147 int argc, const char **argv)
1149 NTSTATUS result;
1150 const char *username;
1151 const char *oldval = "";
1152 union samr_UserInfo *info = NULL;
1154 if (argc > 1) {
1155 d_fprintf(stderr, _("usage: %s <username> [new value|NULL]\n"),
1156 ctx->whoami);
1157 return NT_STATUS_INVALID_PARAMETER;
1160 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1161 user_hnd,
1163 &info);
1164 if (!NT_STATUS_IS_OK(result)) {
1165 return result;
1168 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1170 FETCHSTR("fullname", full_name);
1171 FETCHSTR("homedir", home_directory);
1172 FETCHSTR("homedrive", home_drive);
1173 FETCHSTR("logonscript", logon_script);
1174 FETCHSTR("profilepath", profile_path);
1175 FETCHSTR("description", description);
1177 if (argc == 0) {
1178 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1179 goto done;
1182 if (strcmp(argv[0], "NULL") == 0) {
1183 argv[0] = "";
1186 ZERO_STRUCT(info->info21);
1188 SETSTR("fullname", full_name, FULL_NAME);
1189 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1190 SETSTR("homedrive", home_drive, HOME_DRIVE);
1191 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1192 SETSTR("profilepath", profile_path, PROFILE_PATH);
1193 SETSTR("description", description, DESCRIPTION);
1195 result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1196 user_hnd,
1198 info);
1200 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1201 ctx->thiscmd, oldval, argv[0]);
1203 done:
1205 return result;
1208 #define HANDLEFLG(name, rec) \
1209 do { if (strequal(ctx->thiscmd, name)) { \
1210 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1211 if (newval) { \
1212 newflags = oldflags | ACB_##rec; \
1213 } else { \
1214 newflags = oldflags & ~ACB_##rec; \
1215 } } } while (0);
1217 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1218 TALLOC_CTX *mem_ctx,
1219 struct rpc_sh_ctx *ctx,
1220 struct rpc_pipe_client *pipe_hnd,
1221 int argc, const char **argv)
1223 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1224 rpc_sh_user_str_edit_internals);
1227 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1228 TALLOC_CTX *mem_ctx,
1229 struct rpc_sh_ctx *ctx,
1230 struct rpc_pipe_client *pipe_hnd,
1231 struct policy_handle *user_hnd,
1232 int argc, const char **argv)
1234 NTSTATUS result;
1235 const char *username;
1236 const char *oldval = "unknown";
1237 uint32 oldflags, newflags;
1238 bool newval;
1239 union samr_UserInfo *info = NULL;
1241 if ((argc > 1) ||
1242 ((argc == 1) && !strequal(argv[0], "yes") &&
1243 !strequal(argv[0], "no"))) {
1244 /* TRANSATORS: The yes|no here are program keywords. Please do
1245 not translate. */
1246 d_fprintf(stderr, _("usage: %s <username> [yes|no]\n"),
1247 ctx->whoami);
1248 return NT_STATUS_INVALID_PARAMETER;
1251 newval = strequal(argv[0], "yes");
1253 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1254 user_hnd,
1256 &info);
1257 if (!NT_STATUS_IS_OK(result)) {
1258 return result;
1261 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1262 oldflags = info->info21.acct_flags;
1263 newflags = info->info21.acct_flags;
1265 HANDLEFLG("disabled", DISABLED);
1266 HANDLEFLG("pwnotreq", PWNOTREQ);
1267 HANDLEFLG("autolock", AUTOLOCK);
1268 HANDLEFLG("pwnoexp", PWNOEXP);
1270 if (argc == 0) {
1271 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1272 oldval);
1273 goto done;
1276 ZERO_STRUCT(info->info21);
1278 info->info21.acct_flags = newflags;
1279 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1281 result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1282 user_hnd,
1284 info);
1286 if (NT_STATUS_IS_OK(result)) {
1287 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1288 ctx->thiscmd, oldval, argv[0]);
1291 done:
1293 return result;
1296 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1297 TALLOC_CTX *mem_ctx,
1298 struct rpc_sh_ctx *ctx,
1299 struct rpc_pipe_client *pipe_hnd,
1300 int argc, const char **argv)
1302 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1303 rpc_sh_user_flag_edit_internals);
1306 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1307 TALLOC_CTX *mem_ctx,
1308 struct rpc_sh_ctx *ctx)
1310 static struct rpc_sh_cmd cmds[] = {
1312 { "fullname", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1313 N_("Show/Set a user's full name") },
1315 { "homedir", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1316 N_("Show/Set a user's home directory") },
1318 { "homedrive", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1319 N_("Show/Set a user's home drive") },
1321 { "logonscript", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1322 N_("Show/Set a user's logon script") },
1324 { "profilepath", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1325 N_("Show/Set a user's profile path") },
1327 { "description", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1328 N_("Show/Set a user's description") },
1330 { "disabled", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1331 N_("Show/Set whether a user is disabled") },
1333 { "autolock", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1334 N_("Show/Set whether a user locked out") },
1336 { "pwnotreq", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1337 N_("Show/Set whether a user does not need a password") },
1339 { "pwnoexp", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1340 N_("Show/Set whether a user's password does not expire") },
1342 { NULL, NULL, 0, NULL, NULL }
1345 return cmds;
1348 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1349 TALLOC_CTX *mem_ctx,
1350 struct rpc_sh_ctx *ctx)
1352 static struct rpc_sh_cmd cmds[] = {
1354 { "list", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_list,
1355 N_("List available users") },
1357 { "info", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_info,
1358 N_("List the domain groups a user is member of") },
1360 { "show", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_show,
1361 N_("Show info about a user") },
1363 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1364 N_("Show/Modify a user's fields") },
1366 { NULL, NULL, 0, NULL, NULL }
1369 return cmds;
1372 /****************************************************************************/
1375 * Basic usage function for 'net rpc group'.
1376 * @param argc Standard main() style argc.
1377 * @param argv Standard main() style argv. Initial components are already
1378 * stripped.
1381 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1383 return net_group_usage(c, argc, argv);
1387 * Delete group on a remote RPC server.
1389 * All parameters are provided by the run_rpc_command function, except for
1390 * argc, argv which are passed through.
1392 * @param domain_sid The domain sid acquired from the remote server.
1393 * @param cli A cli_state connected to the server.
1394 * @param mem_ctx Talloc context, destroyed on completion of the function.
1395 * @param argc Standard main() style argc.
1396 * @param argv Standard main() style argv. Initial components are already
1397 * stripped.
1399 * @return Normal NTSTATUS return.
1402 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1403 const DOM_SID *domain_sid,
1404 const char *domain_name,
1405 struct cli_state *cli,
1406 struct rpc_pipe_client *pipe_hnd,
1407 TALLOC_CTX *mem_ctx,
1408 int argc,
1409 const char **argv)
1411 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1412 bool group_is_primary = false;
1413 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1414 uint32_t group_rid;
1415 struct samr_RidTypeArray *rids = NULL;
1416 /* char **names; */
1417 int i;
1418 /* struct samr_RidWithAttribute *user_gids; */
1420 struct samr_Ids group_rids, name_types;
1421 struct lsa_String lsa_acct_name;
1422 union samr_UserInfo *info = NULL;
1424 if (argc < 1 || c->display_usage) {
1425 rpc_group_usage(c, argc,argv);
1426 return NT_STATUS_OK; /* ok? */
1429 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1430 pipe_hnd->desthost,
1431 MAXIMUM_ALLOWED_ACCESS,
1432 &connect_pol);
1434 if (!NT_STATUS_IS_OK(result)) {
1435 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1436 goto done;
1439 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1440 &connect_pol,
1441 MAXIMUM_ALLOWED_ACCESS,
1442 CONST_DISCARD(struct dom_sid2 *, domain_sid),
1443 &domain_pol);
1445 if (!NT_STATUS_IS_OK(result)) {
1446 d_fprintf(stderr, _("Request open_domain failed\n"));
1447 goto done;
1450 init_lsa_String(&lsa_acct_name, argv[0]);
1452 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1453 &domain_pol,
1455 &lsa_acct_name,
1456 &group_rids,
1457 &name_types);
1458 if (!NT_STATUS_IS_OK(result)) {
1459 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1460 goto done;
1463 switch (name_types.ids[0])
1465 case SID_NAME_DOM_GRP:
1466 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1467 &domain_pol,
1468 MAXIMUM_ALLOWED_ACCESS,
1469 group_rids.ids[0],
1470 &group_pol);
1471 if (!NT_STATUS_IS_OK(result)) {
1472 d_fprintf(stderr, _("Request open_group failed"));
1473 goto done;
1476 group_rid = group_rids.ids[0];
1478 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
1479 &group_pol,
1480 &rids);
1482 if (!NT_STATUS_IS_OK(result)) {
1483 d_fprintf(stderr,
1484 _("Unable to query group members of %s"),
1485 argv[0]);
1486 goto done;
1489 if (c->opt_verbose) {
1490 d_printf(
1491 _("Domain Group %s (rid: %d) has %d members\n"),
1492 argv[0],group_rid, rids->count);
1495 /* Check if group is anyone's primary group */
1496 for (i = 0; i < rids->count; i++)
1498 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1499 &domain_pol,
1500 MAXIMUM_ALLOWED_ACCESS,
1501 rids->rids[i],
1502 &user_pol);
1504 if (!NT_STATUS_IS_OK(result)) {
1505 d_fprintf(stderr,
1506 _("Unable to open group member %d\n"),
1507 rids->rids[i]);
1508 goto done;
1511 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1512 &user_pol,
1514 &info);
1516 if (!NT_STATUS_IS_OK(result)) {
1517 d_fprintf(stderr,
1518 _("Unable to lookup userinfo for group "
1519 "member %d\n"),
1520 rids->rids[i]);
1521 goto done;
1524 if (info->info21.primary_gid == group_rid) {
1525 if (c->opt_verbose) {
1526 d_printf(_("Group is primary group "
1527 "of %s\n"),
1528 info->info21.account_name.string);
1530 group_is_primary = true;
1533 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1536 if (group_is_primary) {
1537 d_fprintf(stderr, _("Unable to delete group because "
1538 "some of it's members have it as primary "
1539 "group\n"));
1540 result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1541 goto done;
1544 /* remove all group members */
1545 for (i = 0; i < rids->count; i++)
1547 if (c->opt_verbose)
1548 d_printf(_("Remove group member %d..."),
1549 rids->rids[i]);
1550 result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
1551 &group_pol,
1552 rids->rids[i]);
1554 if (NT_STATUS_IS_OK(result)) {
1555 if (c->opt_verbose)
1556 d_printf(_("ok\n"));
1557 } else {
1558 if (c->opt_verbose)
1559 d_printf(_("failed\n"));
1560 goto done;
1564 result = rpccli_samr_DeleteDomainGroup(pipe_hnd, mem_ctx,
1565 &group_pol);
1567 break;
1568 /* removing a local group is easier... */
1569 case SID_NAME_ALIAS:
1570 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1571 &domain_pol,
1572 MAXIMUM_ALLOWED_ACCESS,
1573 group_rids.ids[0],
1574 &group_pol);
1576 if (!NT_STATUS_IS_OK(result)) {
1577 d_fprintf(stderr, _("Request open_alias failed\n"));
1578 goto done;
1581 result = rpccli_samr_DeleteDomAlias(pipe_hnd, mem_ctx,
1582 &group_pol);
1583 break;
1584 default:
1585 d_fprintf(stderr, _("%s is of type %s. This command is only "
1586 "for deleting local or global groups\n"),
1587 argv[0],sid_type_lookup(name_types.ids[0]));
1588 result = NT_STATUS_UNSUCCESSFUL;
1589 goto done;
1592 if (NT_STATUS_IS_OK(result)) {
1593 if (c->opt_verbose)
1594 d_printf(_("Deleted %s '%s'\n"),
1595 sid_type_lookup(name_types.ids[0]), argv[0]);
1596 } else {
1597 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
1598 get_friendly_nt_error_msg(result));
1601 done:
1602 return result;
1606 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1608 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1609 rpc_group_delete_internals, argc,argv);
1612 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1614 NET_API_STATUS status;
1615 struct GROUP_INFO_1 info1;
1616 uint32_t parm_error = 0;
1618 if (argc != 1 || c->display_usage) {
1619 rpc_group_usage(c, argc, argv);
1620 return 0;
1623 ZERO_STRUCT(info1);
1625 info1.grpi1_name = argv[0];
1626 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1627 info1.grpi1_comment = c->opt_comment;
1630 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1632 if (status != 0) {
1633 d_fprintf(stderr,
1634 _("Failed to add group '%s' with error: %s.\n"),
1635 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1636 status));
1637 return -1;
1638 } else {
1639 d_printf(_("Added group '%s'.\n"), argv[0]);
1642 return 0;
1645 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
1647 NET_API_STATUS status;
1648 struct LOCALGROUP_INFO_1 info1;
1649 uint32_t parm_error = 0;
1651 if (argc != 1 || c->display_usage) {
1652 rpc_group_usage(c, argc, argv);
1653 return 0;
1656 ZERO_STRUCT(info1);
1658 info1.lgrpi1_name = argv[0];
1659 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1660 info1.lgrpi1_comment = c->opt_comment;
1663 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1665 if (status != 0) {
1666 d_fprintf(stderr,
1667 _("Failed to add alias '%s' with error: %s.\n"),
1668 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1669 status));
1670 return -1;
1671 } else {
1672 d_printf(_("Added alias '%s'.\n"), argv[0]);
1675 return 0;
1678 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1680 if (c->opt_localgroup)
1681 return rpc_alias_add_internals(c, argc, argv);
1683 return rpc_group_add_internals(c, argc, argv);
1686 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1687 TALLOC_CTX *mem_ctx,
1688 const char *name,
1689 DOM_SID *sid,
1690 enum lsa_SidType *type)
1692 DOM_SID *sids = NULL;
1693 enum lsa_SidType *types = NULL;
1694 struct rpc_pipe_client *pipe_hnd = NULL;
1695 struct policy_handle lsa_pol;
1696 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1698 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1699 &pipe_hnd);
1700 if (!NT_STATUS_IS_OK(result)) {
1701 goto done;
1704 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1705 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1707 if (!NT_STATUS_IS_OK(result)) {
1708 goto done;
1711 result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1712 &name, NULL, 1, &sids, &types);
1714 if (NT_STATUS_IS_OK(result)) {
1715 sid_copy(sid, &sids[0]);
1716 *type = types[0];
1719 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
1721 done:
1722 if (pipe_hnd) {
1723 TALLOC_FREE(pipe_hnd);
1726 if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
1728 /* Try as S-1-5-whatever */
1730 DOM_SID tmp_sid;
1732 if (string_to_sid(&tmp_sid, name)) {
1733 sid_copy(sid, &tmp_sid);
1734 *type = SID_NAME_UNKNOWN;
1735 result = NT_STATUS_OK;
1739 return result;
1742 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
1743 TALLOC_CTX *mem_ctx,
1744 const DOM_SID *group_sid,
1745 const char *member)
1747 struct policy_handle connect_pol, domain_pol;
1748 NTSTATUS result;
1749 uint32 group_rid;
1750 struct policy_handle group_pol;
1752 struct samr_Ids rids, rid_types;
1753 struct lsa_String lsa_acct_name;
1755 DOM_SID sid;
1757 sid_copy(&sid, group_sid);
1759 if (!sid_split_rid(&sid, &group_rid)) {
1760 return NT_STATUS_UNSUCCESSFUL;
1763 /* Get sam policy handle */
1764 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1765 pipe_hnd->desthost,
1766 MAXIMUM_ALLOWED_ACCESS,
1767 &connect_pol);
1768 if (!NT_STATUS_IS_OK(result)) {
1769 return result;
1772 /* Get domain policy handle */
1773 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1774 &connect_pol,
1775 MAXIMUM_ALLOWED_ACCESS,
1776 &sid,
1777 &domain_pol);
1778 if (!NT_STATUS_IS_OK(result)) {
1779 return result;
1782 init_lsa_String(&lsa_acct_name, member);
1784 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1785 &domain_pol,
1787 &lsa_acct_name,
1788 &rids,
1789 &rid_types);
1791 if (!NT_STATUS_IS_OK(result)) {
1792 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
1793 member);
1794 goto done;
1797 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1798 &domain_pol,
1799 MAXIMUM_ALLOWED_ACCESS,
1800 group_rid,
1801 &group_pol);
1803 if (!NT_STATUS_IS_OK(result)) {
1804 goto done;
1807 result = rpccli_samr_AddGroupMember(pipe_hnd, mem_ctx,
1808 &group_pol,
1809 rids.ids[0],
1810 0x0005); /* unknown flags */
1812 done:
1813 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1814 return result;
1817 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
1818 TALLOC_CTX *mem_ctx,
1819 const DOM_SID *alias_sid,
1820 const char *member)
1822 struct policy_handle connect_pol, domain_pol;
1823 NTSTATUS result;
1824 uint32 alias_rid;
1825 struct policy_handle alias_pol;
1827 DOM_SID member_sid;
1828 enum lsa_SidType member_type;
1830 DOM_SID sid;
1832 sid_copy(&sid, alias_sid);
1834 if (!sid_split_rid(&sid, &alias_rid)) {
1835 return NT_STATUS_UNSUCCESSFUL;
1838 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
1839 member, &member_sid, &member_type);
1841 if (!NT_STATUS_IS_OK(result)) {
1842 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
1843 member);
1844 return result;
1847 /* Get sam policy handle */
1848 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1849 pipe_hnd->desthost,
1850 MAXIMUM_ALLOWED_ACCESS,
1851 &connect_pol);
1852 if (!NT_STATUS_IS_OK(result)) {
1853 goto done;
1856 /* Get domain policy handle */
1857 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1858 &connect_pol,
1859 MAXIMUM_ALLOWED_ACCESS,
1860 &sid,
1861 &domain_pol);
1862 if (!NT_STATUS_IS_OK(result)) {
1863 goto done;
1866 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1867 &domain_pol,
1868 MAXIMUM_ALLOWED_ACCESS,
1869 alias_rid,
1870 &alias_pol);
1872 if (!NT_STATUS_IS_OK(result)) {
1873 return result;
1876 result = rpccli_samr_AddAliasMember(pipe_hnd, mem_ctx,
1877 &alias_pol,
1878 &member_sid);
1880 if (!NT_STATUS_IS_OK(result)) {
1881 return result;
1884 done:
1885 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1886 return result;
1889 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
1890 const DOM_SID *domain_sid,
1891 const char *domain_name,
1892 struct cli_state *cli,
1893 struct rpc_pipe_client *pipe_hnd,
1894 TALLOC_CTX *mem_ctx,
1895 int argc,
1896 const char **argv)
1898 DOM_SID group_sid;
1899 enum lsa_SidType group_type;
1901 if (argc != 2 || c->display_usage) {
1902 d_printf(_("Usage:\n"
1903 "net rpc group addmem <group> <member>\n"
1904 " Add a member to a group\n"
1905 " group\tGroup to add member to\n"
1906 " member\tMember to add to group\n"));
1907 return NT_STATUS_UNSUCCESSFUL;
1910 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
1911 &group_sid, &group_type))) {
1912 d_fprintf(stderr, _("Could not lookup group name %s\n"),
1913 argv[0]);
1914 return NT_STATUS_UNSUCCESSFUL;
1917 if (group_type == SID_NAME_DOM_GRP) {
1918 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
1919 &group_sid, argv[1]);
1921 if (!NT_STATUS_IS_OK(result)) {
1922 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
1923 argv[1], argv[0], nt_errstr(result));
1925 return result;
1928 if (group_type == SID_NAME_ALIAS) {
1929 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
1930 &group_sid, argv[1]);
1932 if (!NT_STATUS_IS_OK(result)) {
1933 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
1934 argv[1], argv[0], nt_errstr(result));
1936 return result;
1939 d_fprintf(stderr, _("Can only add members to global or local groups "
1940 "which %s is not\n"), argv[0]);
1942 return NT_STATUS_UNSUCCESSFUL;
1945 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
1947 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1948 rpc_group_addmem_internals,
1949 argc, argv);
1952 static NTSTATUS rpc_del_groupmem(struct net_context *c,
1953 struct rpc_pipe_client *pipe_hnd,
1954 TALLOC_CTX *mem_ctx,
1955 const DOM_SID *group_sid,
1956 const char *member)
1958 struct policy_handle connect_pol, domain_pol;
1959 NTSTATUS result;
1960 uint32 group_rid;
1961 struct policy_handle group_pol;
1963 struct samr_Ids rids, rid_types;
1964 struct lsa_String lsa_acct_name;
1966 DOM_SID sid;
1968 sid_copy(&sid, group_sid);
1970 if (!sid_split_rid(&sid, &group_rid))
1971 return NT_STATUS_UNSUCCESSFUL;
1973 /* Get sam policy handle */
1974 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1975 pipe_hnd->desthost,
1976 MAXIMUM_ALLOWED_ACCESS,
1977 &connect_pol);
1978 if (!NT_STATUS_IS_OK(result))
1979 return result;
1981 /* Get domain policy handle */
1982 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1983 &connect_pol,
1984 MAXIMUM_ALLOWED_ACCESS,
1985 &sid,
1986 &domain_pol);
1987 if (!NT_STATUS_IS_OK(result))
1988 return result;
1990 init_lsa_String(&lsa_acct_name, member);
1992 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1993 &domain_pol,
1995 &lsa_acct_name,
1996 &rids,
1997 &rid_types);
1998 if (!NT_STATUS_IS_OK(result)) {
1999 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2000 member);
2001 goto done;
2004 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2005 &domain_pol,
2006 MAXIMUM_ALLOWED_ACCESS,
2007 group_rid,
2008 &group_pol);
2010 if (!NT_STATUS_IS_OK(result))
2011 goto done;
2013 result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
2014 &group_pol,
2015 rids.ids[0]);
2017 done:
2018 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2019 return result;
2022 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2023 TALLOC_CTX *mem_ctx,
2024 const DOM_SID *alias_sid,
2025 const char *member)
2027 struct policy_handle connect_pol, domain_pol;
2028 NTSTATUS result;
2029 uint32 alias_rid;
2030 struct policy_handle alias_pol;
2032 DOM_SID member_sid;
2033 enum lsa_SidType member_type;
2035 DOM_SID sid;
2037 sid_copy(&sid, alias_sid);
2039 if (!sid_split_rid(&sid, &alias_rid))
2040 return NT_STATUS_UNSUCCESSFUL;
2042 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2043 member, &member_sid, &member_type);
2045 if (!NT_STATUS_IS_OK(result)) {
2046 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2047 member);
2048 return result;
2051 /* Get sam policy handle */
2052 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2053 pipe_hnd->desthost,
2054 MAXIMUM_ALLOWED_ACCESS,
2055 &connect_pol);
2056 if (!NT_STATUS_IS_OK(result)) {
2057 goto done;
2060 /* Get domain policy handle */
2061 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2062 &connect_pol,
2063 MAXIMUM_ALLOWED_ACCESS,
2064 &sid,
2065 &domain_pol);
2066 if (!NT_STATUS_IS_OK(result)) {
2067 goto done;
2070 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2071 &domain_pol,
2072 MAXIMUM_ALLOWED_ACCESS,
2073 alias_rid,
2074 &alias_pol);
2076 if (!NT_STATUS_IS_OK(result))
2077 return result;
2079 result = rpccli_samr_DeleteAliasMember(pipe_hnd, mem_ctx,
2080 &alias_pol,
2081 &member_sid);
2083 if (!NT_STATUS_IS_OK(result))
2084 return result;
2086 done:
2087 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2088 return result;
2091 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2092 const DOM_SID *domain_sid,
2093 const char *domain_name,
2094 struct cli_state *cli,
2095 struct rpc_pipe_client *pipe_hnd,
2096 TALLOC_CTX *mem_ctx,
2097 int argc,
2098 const char **argv)
2100 DOM_SID group_sid;
2101 enum lsa_SidType group_type;
2103 if (argc != 2 || c->display_usage) {
2104 d_printf(_("Usage:\n"
2105 "net rpc group delmem <group> <member>\n"
2106 " Delete a member from a group\n"
2107 " group\tGroup to delete member from\n"
2108 " member\tMember to delete from group\n"));
2109 return NT_STATUS_UNSUCCESSFUL;
2112 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2113 &group_sid, &group_type))) {
2114 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2115 argv[0]);
2116 return NT_STATUS_UNSUCCESSFUL;
2119 if (group_type == SID_NAME_DOM_GRP) {
2120 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2121 &group_sid, argv[1]);
2123 if (!NT_STATUS_IS_OK(result)) {
2124 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2125 argv[1], argv[0], nt_errstr(result));
2127 return result;
2130 if (group_type == SID_NAME_ALIAS) {
2131 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2132 &group_sid, argv[1]);
2134 if (!NT_STATUS_IS_OK(result)) {
2135 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2136 argv[1], argv[0], nt_errstr(result));
2138 return result;
2141 d_fprintf(stderr, _("Can only delete members from global or local "
2142 "groups which %s is not\n"), argv[0]);
2144 return NT_STATUS_UNSUCCESSFUL;
2147 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2149 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2150 rpc_group_delmem_internals,
2151 argc, argv);
2155 * List groups on a remote RPC server.
2157 * All parameters are provided by the run_rpc_command function, except for
2158 * argc, argv which are passes through.
2160 * @param domain_sid The domain sid acquired from the remote server.
2161 * @param cli A cli_state connected to the server.
2162 * @param mem_ctx Talloc context, destroyed on completion of the function.
2163 * @param argc Standard main() style argc.
2164 * @param argv Standard main() style argv. Initial components are already
2165 * stripped.
2167 * @return Normal NTSTATUS return.
2170 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2171 const DOM_SID *domain_sid,
2172 const char *domain_name,
2173 struct cli_state *cli,
2174 struct rpc_pipe_client *pipe_hnd,
2175 TALLOC_CTX *mem_ctx,
2176 int argc,
2177 const char **argv)
2179 struct policy_handle connect_pol, domain_pol;
2180 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2181 uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2182 struct samr_SamArray *groups = NULL;
2183 bool global = false;
2184 bool local = false;
2185 bool builtin = false;
2187 if (c->display_usage) {
2188 d_printf(_("Usage:\n"
2189 "net rpc group list [global] [local] [builtin]\n"
2190 " List groups on RPC server\n"
2191 " global\tList global groups\n"
2192 " local\tList local groups\n"
2193 " builtin\tList builtin groups\n"
2194 " If none of global, local or builtin is "
2195 "specified, all three options are considered "
2196 "set\n"));
2197 return NT_STATUS_OK;
2200 if (argc == 0) {
2201 global = true;
2202 local = true;
2203 builtin = true;
2206 for (i=0; i<argc; i++) {
2207 if (strequal(argv[i], "global"))
2208 global = true;
2210 if (strequal(argv[i], "local"))
2211 local = true;
2213 if (strequal(argv[i], "builtin"))
2214 builtin = true;
2217 /* Get sam policy handle */
2219 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2220 pipe_hnd->desthost,
2221 MAXIMUM_ALLOWED_ACCESS,
2222 &connect_pol);
2223 if (!NT_STATUS_IS_OK(result)) {
2224 goto done;
2227 /* Get domain policy handle */
2229 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2230 &connect_pol,
2231 MAXIMUM_ALLOWED_ACCESS,
2232 CONST_DISCARD(struct dom_sid2 *, domain_sid),
2233 &domain_pol);
2234 if (!NT_STATUS_IS_OK(result)) {
2235 goto done;
2238 /* Query domain groups */
2239 if (c->opt_long_list_entries)
2240 d_printf(_("\nGroup name Comment"
2241 "\n-----------------------------\n"));
2242 do {
2243 uint32_t max_size, total_size, returned_size;
2244 union samr_DispInfo info;
2246 if (!global) break;
2248 get_query_dispinfo_params(
2249 loop_count, &max_entries, &max_size);
2251 result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
2252 &domain_pol,
2254 start_idx,
2255 max_entries,
2256 max_size,
2257 &total_size,
2258 &returned_size,
2259 &info);
2260 num_entries = info.info3.count;
2261 start_idx += info.info3.count;
2263 if (!NT_STATUS_IS_OK(result) &&
2264 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2265 break;
2267 for (i = 0; i < num_entries; i++) {
2269 const char *group = NULL;
2270 const char *desc = NULL;
2272 group = info.info3.entries[i].account_name.string;
2273 desc = info.info3.entries[i].description.string;
2275 if (c->opt_long_list_entries)
2276 printf("%-21.21s %-50.50s\n",
2277 group, desc);
2278 else
2279 printf("%s\n", group);
2281 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2282 /* query domain aliases */
2283 start_idx = 0;
2284 do {
2285 if (!local) break;
2287 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2288 &domain_pol,
2289 &start_idx,
2290 &groups,
2291 0xffff,
2292 &num_entries);
2293 if (!NT_STATUS_IS_OK(result) &&
2294 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2295 break;
2297 for (i = 0; i < num_entries; i++) {
2299 const char *description = NULL;
2301 if (c->opt_long_list_entries) {
2303 struct policy_handle alias_pol;
2304 union samr_AliasInfo *info = NULL;
2306 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2307 &domain_pol,
2308 0x8,
2309 groups->entries[i].idx,
2310 &alias_pol))) &&
2311 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2312 &alias_pol,
2314 &info))) &&
2315 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2316 &alias_pol)))) {
2317 description = info->description.string;
2321 if (description != NULL) {
2322 printf("%-21.21s %-50.50s\n",
2323 groups->entries[i].name.string,
2324 description);
2325 } else {
2326 printf("%s\n", groups->entries[i].name.string);
2329 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2330 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2331 /* Get builtin policy handle */
2333 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2334 &connect_pol,
2335 MAXIMUM_ALLOWED_ACCESS,
2336 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2337 &domain_pol);
2338 if (!NT_STATUS_IS_OK(result)) {
2339 goto done;
2341 /* query builtin aliases */
2342 start_idx = 0;
2343 do {
2344 if (!builtin) break;
2346 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2347 &domain_pol,
2348 &start_idx,
2349 &groups,
2350 max_entries,
2351 &num_entries);
2352 if (!NT_STATUS_IS_OK(result) &&
2353 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2354 break;
2356 for (i = 0; i < num_entries; i++) {
2358 const char *description = NULL;
2360 if (c->opt_long_list_entries) {
2362 struct policy_handle alias_pol;
2363 union samr_AliasInfo *info = NULL;
2365 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2366 &domain_pol,
2367 0x8,
2368 groups->entries[i].idx,
2369 &alias_pol))) &&
2370 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2371 &alias_pol,
2373 &info))) &&
2374 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2375 &alias_pol)))) {
2376 description = info->description.string;
2380 if (description != NULL) {
2381 printf("%-21.21s %-50.50s\n",
2382 groups->entries[i].name.string,
2383 description);
2384 } else {
2385 printf("%s\n", groups->entries[i].name.string);
2388 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2390 done:
2391 return result;
2394 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2396 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2397 rpc_group_list_internals,
2398 argc, argv);
2401 static NTSTATUS rpc_list_group_members(struct net_context *c,
2402 struct rpc_pipe_client *pipe_hnd,
2403 TALLOC_CTX *mem_ctx,
2404 const char *domain_name,
2405 const DOM_SID *domain_sid,
2406 struct policy_handle *domain_pol,
2407 uint32 rid)
2409 NTSTATUS result;
2410 struct policy_handle group_pol;
2411 uint32 num_members, *group_rids;
2412 int i;
2413 struct samr_RidTypeArray *rids = NULL;
2414 struct lsa_Strings names;
2415 struct samr_Ids types;
2417 fstring sid_str;
2418 sid_to_fstring(sid_str, domain_sid);
2420 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2421 domain_pol,
2422 MAXIMUM_ALLOWED_ACCESS,
2423 rid,
2424 &group_pol);
2426 if (!NT_STATUS_IS_OK(result))
2427 return result;
2429 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
2430 &group_pol,
2431 &rids);
2433 if (!NT_STATUS_IS_OK(result))
2434 return result;
2436 num_members = rids->count;
2437 group_rids = rids->rids;
2439 while (num_members > 0) {
2440 int this_time = 512;
2442 if (num_members < this_time)
2443 this_time = num_members;
2445 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
2446 domain_pol,
2447 this_time,
2448 group_rids,
2449 &names,
2450 &types);
2452 if (!NT_STATUS_IS_OK(result))
2453 return result;
2455 /* We only have users as members, but make the output
2456 the same as the output of alias members */
2458 for (i = 0; i < this_time; i++) {
2460 if (c->opt_long_list_entries) {
2461 printf("%s-%d %s\\%s %d\n", sid_str,
2462 group_rids[i], domain_name,
2463 names.names[i].string,
2464 SID_NAME_USER);
2465 } else {
2466 printf("%s\\%s\n", domain_name,
2467 names.names[i].string);
2471 num_members -= this_time;
2472 group_rids += 512;
2475 return NT_STATUS_OK;
2478 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2479 struct rpc_pipe_client *pipe_hnd,
2480 TALLOC_CTX *mem_ctx,
2481 struct policy_handle *domain_pol,
2482 uint32 rid)
2484 NTSTATUS result;
2485 struct rpc_pipe_client *lsa_pipe;
2486 struct policy_handle alias_pol, lsa_pol;
2487 uint32 num_members;
2488 DOM_SID *alias_sids;
2489 char **domains;
2490 char **names;
2491 enum lsa_SidType *types;
2492 int i;
2493 struct lsa_SidArray sid_array;
2495 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2496 domain_pol,
2497 MAXIMUM_ALLOWED_ACCESS,
2498 rid,
2499 &alias_pol);
2501 if (!NT_STATUS_IS_OK(result))
2502 return result;
2504 result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
2505 &alias_pol,
2506 &sid_array);
2508 if (!NT_STATUS_IS_OK(result)) {
2509 d_fprintf(stderr, _("Couldn't list alias members\n"));
2510 return result;
2513 num_members = sid_array.num_sids;
2515 if (num_members == 0) {
2516 return NT_STATUS_OK;
2519 result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2520 &ndr_table_lsarpc.syntax_id,
2521 &lsa_pipe);
2522 if (!NT_STATUS_IS_OK(result)) {
2523 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
2524 nt_errstr(result) );
2525 return result;
2528 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2529 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2531 if (!NT_STATUS_IS_OK(result)) {
2532 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
2533 TALLOC_FREE(lsa_pipe);
2534 return result;
2537 alias_sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_members);
2538 if (!alias_sids) {
2539 d_fprintf(stderr, _("Out of memory\n"));
2540 TALLOC_FREE(lsa_pipe);
2541 return NT_STATUS_NO_MEMORY;
2544 for (i=0; i<num_members; i++) {
2545 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2548 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
2549 num_members, alias_sids,
2550 &domains, &names, &types);
2552 if (!NT_STATUS_IS_OK(result) &&
2553 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2554 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
2555 TALLOC_FREE(lsa_pipe);
2556 return result;
2559 for (i = 0; i < num_members; i++) {
2560 fstring sid_str;
2561 sid_to_fstring(sid_str, &alias_sids[i]);
2563 if (c->opt_long_list_entries) {
2564 printf("%s %s\\%s %d\n", sid_str,
2565 domains[i] ? domains[i] : _("*unknown*"),
2566 names[i] ? names[i] : _("*unknown*"), types[i]);
2567 } else {
2568 if (domains[i])
2569 printf("%s\\%s\n", domains[i], names[i]);
2570 else
2571 printf("%s\n", sid_str);
2575 TALLOC_FREE(lsa_pipe);
2576 return NT_STATUS_OK;
2579 static NTSTATUS rpc_group_members_internals(struct net_context *c,
2580 const DOM_SID *domain_sid,
2581 const char *domain_name,
2582 struct cli_state *cli,
2583 struct rpc_pipe_client *pipe_hnd,
2584 TALLOC_CTX *mem_ctx,
2585 int argc,
2586 const char **argv)
2588 NTSTATUS result;
2589 struct policy_handle connect_pol, domain_pol;
2590 struct samr_Ids rids, rid_types;
2591 struct lsa_String lsa_acct_name;
2593 /* Get sam policy handle */
2595 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2596 pipe_hnd->desthost,
2597 MAXIMUM_ALLOWED_ACCESS,
2598 &connect_pol);
2600 if (!NT_STATUS_IS_OK(result))
2601 return result;
2603 /* Get domain policy handle */
2605 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2606 &connect_pol,
2607 MAXIMUM_ALLOWED_ACCESS,
2608 CONST_DISCARD(struct dom_sid2 *, domain_sid),
2609 &domain_pol);
2611 if (!NT_STATUS_IS_OK(result))
2612 return result;
2614 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
2616 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2617 &domain_pol,
2619 &lsa_acct_name,
2620 &rids,
2621 &rid_types);
2623 if (!NT_STATUS_IS_OK(result)) {
2625 /* Ok, did not find it in the global sam, try with builtin */
2627 DOM_SID sid_Builtin;
2629 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2631 sid_copy(&sid_Builtin, &global_sid_Builtin);
2633 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2634 &connect_pol,
2635 MAXIMUM_ALLOWED_ACCESS,
2636 &sid_Builtin,
2637 &domain_pol);
2639 if (!NT_STATUS_IS_OK(result)) {
2640 d_fprintf(stderr, _("Couldn't find group %s\n"),
2641 argv[0]);
2642 return result;
2645 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2646 &domain_pol,
2648 &lsa_acct_name,
2649 &rids,
2650 &rid_types);
2652 if (!NT_STATUS_IS_OK(result)) {
2653 d_fprintf(stderr, _("Couldn't find group %s\n"),
2654 argv[0]);
2655 return result;
2659 if (rids.count != 1) {
2660 d_fprintf(stderr, _("Couldn't find group %s\n"),
2661 argv[0]);
2662 return result;
2665 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
2666 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
2667 domain_sid, &domain_pol,
2668 rids.ids[0]);
2671 if (rid_types.ids[0] == SID_NAME_ALIAS) {
2672 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
2673 rids.ids[0]);
2676 return NT_STATUS_NO_SUCH_GROUP;
2679 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
2681 if (argc != 1 || c->display_usage) {
2682 return rpc_group_usage(c, argc, argv);
2685 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2686 rpc_group_members_internals,
2687 argc, argv);
2690 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
2692 NET_API_STATUS status;
2693 struct GROUP_INFO_0 g0;
2694 uint32_t parm_err;
2696 if (argc != 2) {
2697 d_printf(_("Usage: 'net rpc group rename group newname'\n"));
2698 return -1;
2701 g0.grpi0_name = argv[1];
2703 status = NetGroupSetInfo(c->opt_host,
2704 argv[0],
2706 (uint8_t *)&g0,
2707 &parm_err);
2709 if (status != 0) {
2710 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
2711 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2712 status));
2713 return -1;
2716 return 0;
2719 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
2721 if (argc != 2 || c->display_usage) {
2722 return rpc_group_usage(c, argc, argv);
2725 return rpc_group_rename_internals(c, argc, argv);
2729 * 'net rpc group' entrypoint.
2730 * @param argc Standard main() style argc.
2731 * @param argv Standard main() style argv. Initial components are already
2732 * stripped.
2735 int net_rpc_group(struct net_context *c, int argc, const char **argv)
2737 NET_API_STATUS status;
2739 struct functable func[] = {
2741 "add",
2742 rpc_group_add,
2743 NET_TRANSPORT_RPC,
2744 N_("Create specified group"),
2745 N_("net rpc group add\n"
2746 " Create specified group")
2749 "delete",
2750 rpc_group_delete,
2751 NET_TRANSPORT_RPC,
2752 N_("Delete specified group"),
2753 N_("net rpc group delete\n"
2754 " Delete specified group")
2757 "addmem",
2758 rpc_group_addmem,
2759 NET_TRANSPORT_RPC,
2760 N_("Add member to group"),
2761 N_("net rpc group addmem\n"
2762 " Add member to group")
2765 "delmem",
2766 rpc_group_delmem,
2767 NET_TRANSPORT_RPC,
2768 N_("Remove member from group"),
2769 N_("net rpc group delmem\n"
2770 " Remove member from group")
2773 "list",
2774 rpc_group_list,
2775 NET_TRANSPORT_RPC,
2776 N_("List groups"),
2777 N_("net rpc group list\n"
2778 " List groups")
2781 "members",
2782 rpc_group_members,
2783 NET_TRANSPORT_RPC,
2784 N_("List group members"),
2785 N_("net rpc group members\n"
2786 " List group members")
2789 "rename",
2790 rpc_group_rename,
2791 NET_TRANSPORT_RPC,
2792 N_("Rename group"),
2793 N_("net rpc group rename\n"
2794 " Rename group")
2796 {NULL, NULL, 0, NULL, NULL}
2799 status = libnetapi_init(&c->netapi_ctx);
2800 if (status != 0) {
2801 return -1;
2803 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
2804 libnetapi_set_password(c->netapi_ctx, c->opt_password);
2805 if (c->opt_kerberos) {
2806 libnetapi_set_use_kerberos(c->netapi_ctx);
2809 if (argc == 0) {
2810 if (c->display_usage) {
2811 d_printf(_("Usage:\n"));
2812 d_printf(_("net rpc group\n"
2813 " Alias for net rpc group list global "
2814 "local builtin\n"));
2815 net_display_usage_from_functable(func);
2816 return 0;
2819 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2820 rpc_group_list_internals,
2821 argc, argv);
2824 return net_run_function(c, argc, argv, "net rpc group", func);
2827 /****************************************************************************/
2829 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
2831 return net_share_usage(c, argc, argv);
2835 * Add a share on a remote RPC server.
2837 * @param argc Standard main() style argc.
2838 * @param argv Standard main() style argv. Initial components are already
2839 * stripped.
2841 * @return A shell status integer (0 for success).
2844 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
2846 NET_API_STATUS status;
2847 char *sharename;
2848 char *path;
2849 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
2850 uint32 num_users=0, perms=0;
2851 char *password=NULL; /* don't allow a share password */
2852 struct SHARE_INFO_2 i2;
2853 uint32_t parm_error = 0;
2855 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
2856 return rpc_share_usage(c, argc, argv);
2859 if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
2860 return -1;
2863 path = strchr(sharename, '=');
2864 if (!path) {
2865 return -1;
2868 *path++ = '\0';
2870 i2.shi2_netname = sharename;
2871 i2.shi2_type = type;
2872 i2.shi2_remark = c->opt_comment;
2873 i2.shi2_permissions = perms;
2874 i2.shi2_max_uses = c->opt_maxusers;
2875 i2.shi2_current_uses = num_users;
2876 i2.shi2_path = path;
2877 i2.shi2_passwd = password;
2879 status = NetShareAdd(c->opt_host,
2881 (uint8_t *)&i2,
2882 &parm_error);
2883 if (status != 0) {
2884 printf(_("NetShareAdd failed with: %s\n"),
2885 libnetapi_get_error_string(c->netapi_ctx, status));
2888 return status;
2892 * Delete a share on a remote RPC server.
2894 * @param domain_sid The domain sid acquired from the remote server.
2895 * @param argc Standard main() style argc.
2896 * @param argv Standard main() style argv. Initial components are already
2897 * stripped.
2899 * @return A shell status integer (0 for success).
2901 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
2903 if (argc < 1 || c->display_usage) {
2904 return rpc_share_usage(c, argc, argv);
2907 return NetShareDel(c->opt_host, argv[0], 0);
2911 * Formatted print of share info
2913 * @param r pointer to SHARE_INFO_1 to format
2916 static void display_share_info_1(struct net_context *c,
2917 struct SHARE_INFO_1 *r)
2919 if (c->opt_long_list_entries) {
2920 d_printf("%-12s %-8.8s %-50s\n",
2921 r->shi1_netname,
2922 net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
2923 r->shi1_remark);
2924 } else {
2925 d_printf("%s\n", r->shi1_netname);
2929 static WERROR get_share_info(struct net_context *c,
2930 struct rpc_pipe_client *pipe_hnd,
2931 TALLOC_CTX *mem_ctx,
2932 uint32 level,
2933 int argc,
2934 const char **argv,
2935 struct srvsvc_NetShareInfoCtr *info_ctr)
2937 WERROR result;
2938 NTSTATUS status;
2939 union srvsvc_NetShareInfo info;
2941 /* no specific share requested, enumerate all */
2942 if (argc == 0) {
2944 uint32_t preferred_len = 0xffffffff;
2945 uint32_t total_entries = 0;
2946 uint32_t resume_handle = 0;
2948 info_ctr->level = level;
2950 status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, mem_ctx,
2951 pipe_hnd->desthost,
2952 info_ctr,
2953 preferred_len,
2954 &total_entries,
2955 &resume_handle,
2956 &result);
2957 return result;
2960 /* request just one share */
2961 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
2962 pipe_hnd->desthost,
2963 argv[0],
2964 level,
2965 &info,
2966 &result);
2968 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
2969 goto done;
2972 /* construct ctr */
2973 ZERO_STRUCTP(info_ctr);
2975 info_ctr->level = level;
2977 switch (level) {
2978 case 1:
2980 struct srvsvc_NetShareCtr1 *ctr1;
2982 ctr1 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr1);
2983 W_ERROR_HAVE_NO_MEMORY(ctr1);
2985 ctr1->count = 1;
2986 ctr1->array = info.info1;
2988 info_ctr->ctr.ctr1 = ctr1;
2990 case 2:
2992 struct srvsvc_NetShareCtr2 *ctr2;
2994 ctr2 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr2);
2995 W_ERROR_HAVE_NO_MEMORY(ctr2);
2997 ctr2->count = 1;
2998 ctr2->array = info.info2;
3000 info_ctr->ctr.ctr2 = ctr2;
3002 case 502:
3004 struct srvsvc_NetShareCtr502 *ctr502;
3006 ctr502 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr502);
3007 W_ERROR_HAVE_NO_MEMORY(ctr502);
3009 ctr502->count = 1;
3010 ctr502->array = info.info502;
3012 info_ctr->ctr.ctr502 = ctr502;
3014 } /* switch */
3015 done:
3016 return result;
3019 /***
3020 * 'net rpc share list' entrypoint.
3021 * @param argc Standard main() style argc.
3022 * @param argv Standard main() style argv. Initial components are already
3023 * stripped.
3025 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3027 NET_API_STATUS status;
3028 struct SHARE_INFO_1 *i1 = NULL;
3029 uint32_t entries_read = 0;
3030 uint32_t total_entries = 0;
3031 uint32_t resume_handle = 0;
3032 uint32_t i, level = 1;
3034 if (c->display_usage) {
3035 d_printf(_("Usage\n"
3036 "net rpc share list\n"
3037 " List shares on remote server\n"));
3038 return 0;
3041 status = NetShareEnum(c->opt_host,
3042 level,
3043 (uint8_t **)(void *)&i1,
3044 (uint32_t)-1,
3045 &entries_read,
3046 &total_entries,
3047 &resume_handle);
3048 if (status != 0) {
3049 goto done;
3052 /* Display results */
3054 if (c->opt_long_list_entries) {
3055 d_printf(_(
3056 "\nEnumerating shared resources (exports) on remote server:\n\n"
3057 "\nShare name Type Description\n"
3058 "---------- ---- -----------\n"));
3060 for (i = 0; i < entries_read; i++)
3061 display_share_info_1(c, &i1[i]);
3062 done:
3063 return status;
3066 static bool check_share_availability(struct cli_state *cli, const char *netname)
3068 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
3069 d_printf(_("skipping [%s]: not a file share.\n"), netname);
3070 return false;
3073 if (!cli_tdis(cli))
3074 return false;
3076 return true;
3079 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3080 const char *netname, uint32 type)
3082 /* only support disk shares */
3083 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3084 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3085 type);
3086 return false;
3089 /* skip builtin shares */
3090 /* FIXME: should print$ be added too ? */
3091 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3092 strequal(netname,"global"))
3093 return false;
3095 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3096 printf(_("excluding [%s]\n"), netname);
3097 return false;
3100 return check_share_availability(cli, netname);
3104 * Migrate shares from a remote RPC server to the local RPC server.
3106 * All parameters are provided by the run_rpc_command function, except for
3107 * argc, argv which are passed through.
3109 * @param domain_sid The domain sid acquired from the remote server.
3110 * @param cli A cli_state connected to the server.
3111 * @param mem_ctx Talloc context, destroyed on completion of the function.
3112 * @param argc Standard main() style argc.
3113 * @param argv Standard main() style argv. Initial components are already
3114 * stripped.
3116 * @return Normal NTSTATUS return.
3119 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3120 const DOM_SID *domain_sid,
3121 const char *domain_name,
3122 struct cli_state *cli,
3123 struct rpc_pipe_client *pipe_hnd,
3124 TALLOC_CTX *mem_ctx,
3125 int argc,
3126 const char **argv)
3128 WERROR result;
3129 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3130 struct srvsvc_NetShareInfoCtr ctr_src;
3131 uint32 i;
3132 struct rpc_pipe_client *srvsvc_pipe = NULL;
3133 struct cli_state *cli_dst = NULL;
3134 uint32 level = 502; /* includes secdesc */
3135 uint32_t parm_error = 0;
3137 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3138 &ctr_src);
3139 if (!W_ERROR_IS_OK(result))
3140 goto done;
3142 /* connect destination PI_SRVSVC */
3143 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3144 &ndr_table_srvsvc.syntax_id);
3145 if (!NT_STATUS_IS_OK(nt_status))
3146 return nt_status;
3149 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3151 union srvsvc_NetShareInfo info;
3152 struct srvsvc_NetShareInfo502 info502 =
3153 ctr_src.ctr.ctr502->array[i];
3155 /* reset error-code */
3156 nt_status = NT_STATUS_UNSUCCESSFUL;
3158 if (!check_share_sanity(c, cli, info502.name, info502.type))
3159 continue;
3161 /* finally add the share on the dst server */
3163 printf(_("migrating: [%s], path: %s, comment: %s, without "
3164 "share-ACLs\n"),
3165 info502.name, info502.path, info502.comment);
3167 info.info502 = &info502;
3169 nt_status = rpccli_srvsvc_NetShareAdd(srvsvc_pipe, mem_ctx,
3170 srvsvc_pipe->desthost,
3171 502,
3172 &info,
3173 &parm_error,
3174 &result);
3176 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3177 printf(_(" [%s] does already exist\n"),
3178 info502.name);
3179 continue;
3182 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3183 printf(_("cannot add share: %s\n"), win_errstr(result));
3184 goto done;
3189 nt_status = NT_STATUS_OK;
3191 done:
3192 if (cli_dst) {
3193 cli_shutdown(cli_dst);
3196 return nt_status;
3201 * Migrate shares from a RPC server to another.
3203 * @param argc Standard main() style argc.
3204 * @param argv Standard main() style argv. Initial components are already
3205 * stripped.
3207 * @return A shell status integer (0 for success).
3209 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3210 const char **argv)
3212 if (c->display_usage) {
3213 d_printf(_("Usage:\n"
3214 "net rpc share migrate shares\n"
3215 " Migrate shares to local server\n"));
3216 return 0;
3219 if (!c->opt_host) {
3220 printf(_("no server to migrate\n"));
3221 return -1;
3224 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3225 rpc_share_migrate_shares_internals,
3226 argc, argv);
3230 * Copy a file/dir
3232 * @param f file_info
3233 * @param mask current search mask
3234 * @param state arg-pointer
3237 static void copy_fn(const char *mnt, file_info *f,
3238 const char *mask, void *state)
3240 static NTSTATUS nt_status;
3241 static struct copy_clistate *local_state;
3242 static fstring filename, new_mask;
3243 fstring dir;
3244 char *old_dir;
3245 struct net_context *c;
3247 local_state = (struct copy_clistate *)state;
3248 nt_status = NT_STATUS_UNSUCCESSFUL;
3250 c = local_state->c;
3252 if (strequal(f->name, ".") || strequal(f->name, ".."))
3253 return;
3255 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3257 /* DIRECTORY */
3258 if (f->mode & aDIR) {
3260 DEBUG(3,("got dir: %s\n", f->name));
3262 fstrcpy(dir, local_state->cwd);
3263 fstrcat(dir, "\\");
3264 fstrcat(dir, f->name);
3266 switch (net_mode_share)
3268 case NET_MODE_SHARE_MIGRATE:
3269 /* create that directory */
3270 nt_status = net_copy_file(c, local_state->mem_ctx,
3271 local_state->cli_share_src,
3272 local_state->cli_share_dst,
3273 dir, dir,
3274 c->opt_acls? true : false,
3275 c->opt_attrs? true : false,
3276 c->opt_timestamps? true:false,
3277 false);
3278 break;
3279 default:
3280 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3281 return;
3284 if (!NT_STATUS_IS_OK(nt_status))
3285 printf(_("could not handle dir %s: %s\n"),
3286 dir, nt_errstr(nt_status));
3288 /* search below that directory */
3289 fstrcpy(new_mask, dir);
3290 fstrcat(new_mask, "\\*");
3292 old_dir = local_state->cwd;
3293 local_state->cwd = dir;
3294 if (!sync_files(local_state, new_mask))
3295 printf(_("could not handle files\n"));
3296 local_state->cwd = old_dir;
3298 return;
3302 /* FILE */
3303 fstrcpy(filename, local_state->cwd);
3304 fstrcat(filename, "\\");
3305 fstrcat(filename, f->name);
3307 DEBUG(3,("got file: %s\n", filename));
3309 switch (net_mode_share)
3311 case NET_MODE_SHARE_MIGRATE:
3312 nt_status = net_copy_file(c, local_state->mem_ctx,
3313 local_state->cli_share_src,
3314 local_state->cli_share_dst,
3315 filename, filename,
3316 c->opt_acls? true : false,
3317 c->opt_attrs? true : false,
3318 c->opt_timestamps? true: false,
3319 true);
3320 break;
3321 default:
3322 d_fprintf(stderr, _("Unsupported file mode %d\n"),
3323 net_mode_share);
3324 return;
3327 if (!NT_STATUS_IS_OK(nt_status))
3328 printf(_("could not handle file %s: %s\n"),
3329 filename, nt_errstr(nt_status));
3334 * sync files, can be called recursivly to list files
3335 * and then call copy_fn for each file
3337 * @param cp_clistate pointer to the copy_clistate we work with
3338 * @param mask the current search mask
3340 * @return Boolean result
3342 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask)
3344 struct cli_state *targetcli;
3345 char *targetpath = NULL;
3347 DEBUG(3,("calling cli_list with mask: %s\n", mask));
3349 if ( !cli_resolve_path(talloc_tos(), "", NULL, cp_clistate->cli_share_src,
3350 mask, &targetcli, &targetpath ) ) {
3351 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
3352 "%s\n"),
3353 mask, cli_errstr(cp_clistate->cli_share_src));
3354 return false;
3357 if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3358 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
3359 mask, cli_errstr(targetcli));
3360 return false;
3363 return true;
3368 * Set the top level directory permissions before we do any further copies.
3369 * Should set up ACL inheritance.
3372 bool copy_top_level_perms(struct net_context *c,
3373 struct copy_clistate *cp_clistate,
3374 const char *sharename)
3376 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3378 switch (net_mode_share) {
3379 case NET_MODE_SHARE_MIGRATE:
3380 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3381 nt_status = net_copy_fileattr(c,
3382 cp_clistate->mem_ctx,
3383 cp_clistate->cli_share_src,
3384 cp_clistate->cli_share_dst,
3385 "\\", "\\",
3386 c->opt_acls? true : false,
3387 c->opt_attrs? true : false,
3388 c->opt_timestamps? true: false,
3389 false);
3390 break;
3391 default:
3392 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3393 break;
3396 if (!NT_STATUS_IS_OK(nt_status)) {
3397 printf(_("Could handle directory attributes for top level "
3398 "directory of share %s. Error %s\n"),
3399 sharename, nt_errstr(nt_status));
3400 return false;
3403 return true;
3407 * Sync all files inside a remote share to another share (over smb).
3409 * All parameters are provided by the run_rpc_command function, except for
3410 * argc, argv which are passed through.
3412 * @param domain_sid The domain sid acquired from the remote server.
3413 * @param cli A cli_state connected to the server.
3414 * @param mem_ctx Talloc context, destroyed on completion of the function.
3415 * @param argc Standard main() style argc.
3416 * @param argv Standard main() style argv. Initial components are already
3417 * stripped.
3419 * @return Normal NTSTATUS return.
3422 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
3423 const DOM_SID *domain_sid,
3424 const char *domain_name,
3425 struct cli_state *cli,
3426 struct rpc_pipe_client *pipe_hnd,
3427 TALLOC_CTX *mem_ctx,
3428 int argc,
3429 const char **argv)
3431 WERROR result;
3432 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3433 struct srvsvc_NetShareInfoCtr ctr_src;
3434 uint32 i;
3435 uint32 level = 502;
3436 struct copy_clistate cp_clistate;
3437 bool got_src_share = false;
3438 bool got_dst_share = false;
3439 const char *mask = "\\*";
3440 char *dst = NULL;
3442 dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3443 if (dst == NULL) {
3444 nt_status = NT_STATUS_NO_MEMORY;
3445 goto done;
3448 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3449 &ctr_src);
3451 if (!W_ERROR_IS_OK(result))
3452 goto done;
3454 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3456 struct srvsvc_NetShareInfo502 info502 =
3457 ctr_src.ctr.ctr502->array[i];
3459 if (!check_share_sanity(c, cli, info502.name, info502.type))
3460 continue;
3462 /* one might not want to mirror whole discs :) */
3463 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3464 d_printf(_("skipping [%s]: builtin/hidden share\n"),
3465 info502.name);
3466 continue;
3469 switch (net_mode_share)
3471 case NET_MODE_SHARE_MIGRATE:
3472 printf("syncing");
3473 break;
3474 default:
3475 d_fprintf(stderr, _("Unsupported mode %d\n"),
3476 net_mode_share);
3477 break;
3479 printf(_(" [%s] files and directories %s ACLs, %s DOS "
3480 "Attributes %s\n"),
3481 info502.name,
3482 c->opt_acls ? _("including") : _("without"),
3483 c->opt_attrs ? _("including") : _("without"),
3484 c->opt_timestamps ? _("(preserving timestamps)") : "");
3486 cp_clistate.mem_ctx = mem_ctx;
3487 cp_clistate.cli_share_src = NULL;
3488 cp_clistate.cli_share_dst = NULL;
3489 cp_clistate.cwd = NULL;
3490 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3491 cp_clistate.c = c;
3493 /* open share source */
3494 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
3495 &cli->dest_ss, cli->desthost,
3496 info502.name, "A:");
3497 if (!NT_STATUS_IS_OK(nt_status))
3498 goto done;
3500 got_src_share = true;
3502 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3503 /* open share destination */
3504 nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
3505 NULL, dst, info502.name, "A:");
3506 if (!NT_STATUS_IS_OK(nt_status))
3507 goto done;
3509 got_dst_share = true;
3512 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
3513 d_fprintf(stderr, _("Could not handle the top level "
3514 "directory permissions for the "
3515 "share: %s\n"), info502.name);
3516 nt_status = NT_STATUS_UNSUCCESSFUL;
3517 goto done;
3520 if (!sync_files(&cp_clistate, mask)) {
3521 d_fprintf(stderr, _("could not handle files for share: "
3522 "%s\n"), info502.name);
3523 nt_status = NT_STATUS_UNSUCCESSFUL;
3524 goto done;
3528 nt_status = NT_STATUS_OK;
3530 done:
3532 if (got_src_share)
3533 cli_shutdown(cp_clistate.cli_share_src);
3535 if (got_dst_share)
3536 cli_shutdown(cp_clistate.cli_share_dst);
3538 SAFE_FREE(dst);
3539 return nt_status;
3543 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
3545 if (c->display_usage) {
3546 d_printf(_("Usage:\n"
3547 "net share migrate files\n"
3548 " Migrate files to local server\n"));
3549 return 0;
3552 if (!c->opt_host) {
3553 d_printf(_("no server to migrate\n"));
3554 return -1;
3557 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3558 rpc_share_migrate_files_internals,
3559 argc, argv);
3563 * Migrate share-ACLs from a remote RPC server to the local RPC server.
3565 * All parameters are provided by the run_rpc_command function, except for
3566 * argc, argv which are passed through.
3568 * @param domain_sid The domain sid acquired from the remote server.
3569 * @param cli A cli_state connected to the server.
3570 * @param mem_ctx Talloc context, destroyed on completion of the function.
3571 * @param argc Standard main() style argc.
3572 * @param argv Standard main() style argv. Initial components are already
3573 * stripped.
3575 * @return Normal NTSTATUS return.
3578 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
3579 const DOM_SID *domain_sid,
3580 const char *domain_name,
3581 struct cli_state *cli,
3582 struct rpc_pipe_client *pipe_hnd,
3583 TALLOC_CTX *mem_ctx,
3584 int argc,
3585 const char **argv)
3587 WERROR result;
3588 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3589 struct srvsvc_NetShareInfoCtr ctr_src;
3590 union srvsvc_NetShareInfo info;
3591 uint32 i;
3592 struct rpc_pipe_client *srvsvc_pipe = NULL;
3593 struct cli_state *cli_dst = NULL;
3594 uint32 level = 502; /* includes secdesc */
3595 uint32_t parm_error = 0;
3597 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3598 &ctr_src);
3600 if (!W_ERROR_IS_OK(result))
3601 goto done;
3603 /* connect destination PI_SRVSVC */
3604 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3605 &ndr_table_srvsvc.syntax_id);
3606 if (!NT_STATUS_IS_OK(nt_status))
3607 return nt_status;
3610 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3612 struct srvsvc_NetShareInfo502 info502 =
3613 ctr_src.ctr.ctr502->array[i];
3615 /* reset error-code */
3616 nt_status = NT_STATUS_UNSUCCESSFUL;
3618 if (!check_share_sanity(c, cli, info502.name, info502.type))
3619 continue;
3621 printf(_("migrating: [%s], path: %s, comment: %s, including "
3622 "share-ACLs\n"),
3623 info502.name, info502.path, info502.comment);
3625 if (c->opt_verbose)
3626 display_sec_desc(info502.sd_buf.sd);
3628 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3629 info.info502 = &info502;
3631 /* finally modify the share on the dst server */
3632 nt_status = rpccli_srvsvc_NetShareSetInfo(srvsvc_pipe, mem_ctx,
3633 srvsvc_pipe->desthost,
3634 info502.name,
3635 level,
3636 &info,
3637 &parm_error,
3638 &result);
3639 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3640 printf(_("cannot set share-acl: %s\n"),
3641 win_errstr(result));
3642 goto done;
3647 nt_status = NT_STATUS_OK;
3649 done:
3650 if (cli_dst) {
3651 cli_shutdown(cli_dst);
3654 return nt_status;
3659 * Migrate share-acls from a RPC server to another.
3661 * @param argc Standard main() style argc.
3662 * @param argv Standard main() style argv. Initial components are already
3663 * stripped.
3665 * @return A shell status integer (0 for success).
3667 static int rpc_share_migrate_security(struct net_context *c, int argc,
3668 const char **argv)
3670 if (c->display_usage) {
3671 d_printf(_("Usage:\n"
3672 "net rpc share migrate security\n"
3673 " Migrate share-acls to local server\n"));
3674 return 0;
3677 if (!c->opt_host) {
3678 d_printf(_("no server to migrate\n"));
3679 return -1;
3682 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3683 rpc_share_migrate_security_internals,
3684 argc, argv);
3688 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3689 * from one server to another.
3691 * @param argc Standard main() style argc.
3692 * @param argv Standard main() style argv. Initial components are already
3693 * stripped.
3695 * @return A shell status integer (0 for success).
3698 static int rpc_share_migrate_all(struct net_context *c, int argc,
3699 const char **argv)
3701 int ret;
3703 if (c->display_usage) {
3704 d_printf(_("Usage:\n"
3705 "net rpc share migrate all\n"
3706 " Migrates shares including all share settings\n"));
3707 return 0;
3710 if (!c->opt_host) {
3711 d_printf(_("no server to migrate\n"));
3712 return -1;
3715 /* order is important. we don't want to be locked out by the share-acl
3716 * before copying files - gd */
3718 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3719 rpc_share_migrate_shares_internals, argc, argv);
3720 if (ret)
3721 return ret;
3723 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3724 rpc_share_migrate_files_internals, argc, argv);
3725 if (ret)
3726 return ret;
3728 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3729 rpc_share_migrate_security_internals, argc,
3730 argv);
3735 * 'net rpc share migrate' entrypoint.
3736 * @param argc Standard main() style argc.
3737 * @param argv Standard main() style argv. Initial components are already
3738 * stripped.
3740 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
3743 struct functable func[] = {
3745 "all",
3746 rpc_share_migrate_all,
3747 NET_TRANSPORT_RPC,
3748 N_("Migrate shares from remote to local server"),
3749 N_("net rpc share migrate all\n"
3750 " Migrate shares from remote to local server")
3753 "files",
3754 rpc_share_migrate_files,
3755 NET_TRANSPORT_RPC,
3756 N_("Migrate files from remote to local server"),
3757 N_("net rpc share migrate files\n"
3758 " Migrate files from remote to local server")
3761 "security",
3762 rpc_share_migrate_security,
3763 NET_TRANSPORT_RPC,
3764 N_("Migrate share-ACLs from remote to local server"),
3765 N_("net rpc share migrate security\n"
3766 " Migrate share-ACLs from remote to local server")
3769 "shares",
3770 rpc_share_migrate_shares,
3771 NET_TRANSPORT_RPC,
3772 N_("Migrate shares from remote to local server"),
3773 N_("net rpc share migrate shares\n"
3774 " Migrate shares from remote to local server")
3776 {NULL, NULL, 0, NULL, NULL}
3779 net_mode_share = NET_MODE_SHARE_MIGRATE;
3781 return net_run_function(c, argc, argv, "net rpc share migrate", func);
3784 struct full_alias {
3785 DOM_SID sid;
3786 uint32 num_members;
3787 DOM_SID *members;
3790 static int num_server_aliases;
3791 static struct full_alias *server_aliases;
3794 * Add an alias to the static list.
3796 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
3798 if (server_aliases == NULL)
3799 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
3801 server_aliases[num_server_aliases] = *alias;
3802 num_server_aliases += 1;
3806 * For a specific domain on the server, fetch all the aliases
3807 * and their members. Add all of them to the server_aliases.
3810 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
3811 TALLOC_CTX *mem_ctx,
3812 struct policy_handle *connect_pol,
3813 const DOM_SID *domain_sid)
3815 uint32 start_idx, max_entries, num_entries, i;
3816 struct samr_SamArray *groups = NULL;
3817 NTSTATUS result;
3818 struct policy_handle domain_pol;
3820 /* Get domain policy handle */
3822 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
3823 connect_pol,
3824 MAXIMUM_ALLOWED_ACCESS,
3825 CONST_DISCARD(struct dom_sid2 *, domain_sid),
3826 &domain_pol);
3827 if (!NT_STATUS_IS_OK(result))
3828 return result;
3830 start_idx = 0;
3831 max_entries = 250;
3833 do {
3834 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
3835 &domain_pol,
3836 &start_idx,
3837 &groups,
3838 max_entries,
3839 &num_entries);
3840 for (i = 0; i < num_entries; i++) {
3842 struct policy_handle alias_pol;
3843 struct full_alias alias;
3844 struct lsa_SidArray sid_array;
3845 int j;
3847 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
3848 &domain_pol,
3849 MAXIMUM_ALLOWED_ACCESS,
3850 groups->entries[i].idx,
3851 &alias_pol);
3852 if (!NT_STATUS_IS_OK(result))
3853 goto done;
3855 result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
3856 &alias_pol,
3857 &sid_array);
3858 if (!NT_STATUS_IS_OK(result))
3859 goto done;
3861 alias.num_members = sid_array.num_sids;
3863 result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
3864 if (!NT_STATUS_IS_OK(result))
3865 goto done;
3867 alias.members = NULL;
3869 if (alias.num_members > 0) {
3870 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
3872 for (j = 0; j < alias.num_members; j++)
3873 sid_copy(&alias.members[j],
3874 sid_array.sids[j].sid);
3877 sid_copy(&alias.sid, domain_sid);
3878 sid_append_rid(&alias.sid, groups->entries[i].idx);
3880 push_alias(mem_ctx, &alias);
3882 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3884 result = NT_STATUS_OK;
3886 done:
3887 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
3889 return result;
3893 * Dump server_aliases as names for debugging purposes.
3896 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
3897 const DOM_SID *domain_sid,
3898 const char *domain_name,
3899 struct cli_state *cli,
3900 struct rpc_pipe_client *pipe_hnd,
3901 TALLOC_CTX *mem_ctx,
3902 int argc,
3903 const char **argv)
3905 int i;
3906 NTSTATUS result;
3907 struct policy_handle lsa_pol;
3909 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
3910 SEC_FLAG_MAXIMUM_ALLOWED,
3911 &lsa_pol);
3912 if (!NT_STATUS_IS_OK(result))
3913 return result;
3915 for (i=0; i<num_server_aliases; i++) {
3916 char **names;
3917 char **domains;
3918 enum lsa_SidType *types;
3919 int j;
3921 struct full_alias *alias = &server_aliases[i];
3923 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
3924 &alias->sid,
3925 &domains, &names, &types);
3926 if (!NT_STATUS_IS_OK(result))
3927 continue;
3929 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
3931 if (alias->num_members == 0) {
3932 DEBUG(1, ("\n"));
3933 continue;
3936 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
3937 alias->num_members,
3938 alias->members,
3939 &domains, &names, &types);
3941 if (!NT_STATUS_IS_OK(result) &&
3942 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
3943 continue;
3945 for (j=0; j<alias->num_members; j++)
3946 DEBUG(1, ("%s\\%s (%d); ",
3947 domains[j] ? domains[j] : "*unknown*",
3948 names[j] ? names[j] : "*unknown*",types[j]));
3949 DEBUG(1, ("\n"));
3952 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
3954 return NT_STATUS_OK;
3958 * Fetch a list of all server aliases and their members into
3959 * server_aliases.
3962 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
3963 const DOM_SID *domain_sid,
3964 const char *domain_name,
3965 struct cli_state *cli,
3966 struct rpc_pipe_client *pipe_hnd,
3967 TALLOC_CTX *mem_ctx,
3968 int argc,
3969 const char **argv)
3971 NTSTATUS result;
3972 struct policy_handle connect_pol;
3974 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
3975 pipe_hnd->desthost,
3976 MAXIMUM_ALLOWED_ACCESS,
3977 &connect_pol);
3979 if (!NT_STATUS_IS_OK(result))
3980 goto done;
3982 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
3983 &global_sid_Builtin);
3985 if (!NT_STATUS_IS_OK(result))
3986 goto done;
3988 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
3989 domain_sid);
3991 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
3992 done:
3993 return result;
3996 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
3998 token->num_sids = 4;
4000 if (!(token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4))) {
4001 d_fprintf(stderr, _("malloc failed\n"));
4002 token->num_sids = 0;
4003 return;
4006 token->user_sids[0] = *user_sid;
4007 sid_copy(&token->user_sids[1], &global_sid_World);
4008 sid_copy(&token->user_sids[2], &global_sid_Network);
4009 sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
4012 static void free_user_token(NT_USER_TOKEN *token)
4014 SAFE_FREE(token->user_sids);
4017 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
4019 if (is_sid_in_token(token, sid))
4020 return;
4022 token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
4023 if (!token->user_sids) {
4024 return;
4027 sid_copy(&token->user_sids[token->num_sids], sid);
4029 token->num_sids += 1;
4032 struct user_token {
4033 fstring name;
4034 NT_USER_TOKEN token;
4037 static void dump_user_token(struct user_token *token)
4039 int i;
4041 d_printf("%s\n", token->name);
4043 for (i=0; i<token->token.num_sids; i++) {
4044 d_printf(" %s\n", sid_string_tos(&token->token.user_sids[i]));
4048 static bool is_alias_member(DOM_SID *sid, struct full_alias *alias)
4050 int i;
4052 for (i=0; i<alias->num_members; i++) {
4053 if (sid_compare(sid, &alias->members[i]) == 0)
4054 return true;
4057 return false;
4060 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
4062 int i;
4064 for (i=0; i<num_server_aliases; i++) {
4065 if (is_alias_member(&sid, &server_aliases[i]))
4066 add_sid_to_token(token, &server_aliases[i].sid);
4071 * We got a user token with all the SIDs we can know about without asking the
4072 * server directly. These are the user and domain group sids. All of these can
4073 * be members of aliases. So scan the list of aliases for each of the SIDs and
4074 * add them to the token.
4077 static void collect_alias_memberships(NT_USER_TOKEN *token)
4079 int num_global_sids = token->num_sids;
4080 int i;
4082 for (i=0; i<num_global_sids; i++) {
4083 collect_sid_memberships(token, token->user_sids[i]);
4087 static bool get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
4089 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4090 enum wbcSidType type;
4091 fstring full_name;
4092 struct wbcDomainSid wsid;
4093 char *sid_str = NULL;
4094 DOM_SID user_sid;
4095 uint32_t num_groups;
4096 gid_t *groups = NULL;
4097 uint32_t i;
4099 fstr_sprintf(full_name, "%s%c%s",
4100 domain, *lp_winbind_separator(), user);
4102 /* First let's find out the user sid */
4104 wbc_status = wbcLookupName(domain, user, &wsid, &type);
4106 if (!WBC_ERROR_IS_OK(wbc_status)) {
4107 DEBUG(1, ("winbind could not find %s: %s\n",
4108 full_name, wbcErrorString(wbc_status)));
4109 return false;
4112 wbc_status = wbcSidToString(&wsid, &sid_str);
4113 if (!WBC_ERROR_IS_OK(wbc_status)) {
4114 return false;
4117 if (type != SID_NAME_USER) {
4118 wbcFreeMemory(sid_str);
4119 DEBUG(1, ("%s is not a user\n", full_name));
4120 return false;
4123 if (!string_to_sid(&user_sid, sid_str)) {
4124 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4125 return false;
4128 wbcFreeMemory(sid_str);
4129 sid_str = NULL;
4131 init_user_token(token, &user_sid);
4133 /* And now the groups winbind knows about */
4135 wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4136 if (!WBC_ERROR_IS_OK(wbc_status)) {
4137 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4138 full_name, wbcErrorString(wbc_status)));
4139 return false;
4142 for (i = 0; i < num_groups; i++) {
4143 gid_t gid = groups[i];
4144 DOM_SID sid;
4146 wbc_status = wbcGidToSid(gid, &wsid);
4147 if (!WBC_ERROR_IS_OK(wbc_status)) {
4148 DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4149 (unsigned int)gid, wbcErrorString(wbc_status)));
4150 wbcFreeMemory(groups);
4151 return false;
4154 wbc_status = wbcSidToString(&wsid, &sid_str);
4155 if (!WBC_ERROR_IS_OK(wbc_status)) {
4156 wbcFreeMemory(groups);
4157 return false;
4160 DEBUG(3, (" %s\n", sid_str));
4162 string_to_sid(&sid, sid_str);
4163 wbcFreeMemory(sid_str);
4164 sid_str = NULL;
4166 add_sid_to_token(token, &sid);
4168 wbcFreeMemory(groups);
4170 return true;
4174 * Get a list of all user tokens we want to look at
4177 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4178 struct user_token **user_tokens)
4180 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4181 uint32_t i, num_users;
4182 const char **users;
4183 struct user_token *result;
4184 TALLOC_CTX *frame = NULL;
4186 if (lp_winbind_use_default_domain() &&
4187 (c->opt_target_workgroup == NULL)) {
4188 d_fprintf(stderr, _("winbind use default domain = yes set, "
4189 "please specify a workgroup\n"));
4190 return false;
4193 /* Send request to winbind daemon */
4195 wbc_status = wbcListUsers(NULL, &num_users, &users);
4196 if (!WBC_ERROR_IS_OK(wbc_status)) {
4197 DEBUG(1, (_("winbind could not list users: %s\n"),
4198 wbcErrorString(wbc_status)));
4199 return false;
4202 result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4204 if (result == NULL) {
4205 DEBUG(1, ("Could not malloc sid array\n"));
4206 wbcFreeMemory(users);
4207 return false;
4210 frame = talloc_stackframe();
4211 for (i=0; i < num_users; i++) {
4212 fstring domain, user;
4213 char *p;
4215 fstrcpy(result[i].name, users[i]);
4217 p = strchr(users[i], *lp_winbind_separator());
4219 DEBUG(3, ("%s\n", users[i]));
4221 if (p == NULL) {
4222 fstrcpy(domain, c->opt_target_workgroup);
4223 fstrcpy(user, users[i]);
4224 } else {
4225 *p++ = '\0';
4226 fstrcpy(domain, users[i]);
4227 strupper_m(domain);
4228 fstrcpy(user, p);
4231 get_user_sids(domain, user, &(result[i].token));
4232 i+=1;
4234 TALLOC_FREE(frame);
4235 wbcFreeMemory(users);
4237 *num_tokens = num_users;
4238 *user_tokens = result;
4240 return true;
4243 static bool get_user_tokens_from_file(FILE *f,
4244 int *num_tokens,
4245 struct user_token **tokens)
4247 struct user_token *token = NULL;
4249 while (!feof(f)) {
4250 fstring line;
4252 if (fgets(line, sizeof(line)-1, f) == NULL) {
4253 return true;
4256 if (line[strlen(line)-1] == '\n')
4257 line[strlen(line)-1] = '\0';
4259 if (line[0] == ' ') {
4260 /* We have a SID */
4262 DOM_SID sid;
4263 if(!string_to_sid(&sid, &line[1])) {
4264 DEBUG(1,("get_user_tokens_from_file: Could "
4265 "not convert sid %s \n",&line[1]));
4266 return false;
4269 if (token == NULL) {
4270 DEBUG(0, ("File does not begin with username"));
4271 return false;
4274 add_sid_to_token(&token->token, &sid);
4275 continue;
4278 /* And a new user... */
4280 *num_tokens += 1;
4281 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4282 if (*tokens == NULL) {
4283 DEBUG(0, ("Could not realloc tokens\n"));
4284 return false;
4287 token = &((*tokens)[*num_tokens-1]);
4289 fstrcpy(token->name, line);
4290 token->token.num_sids = 0;
4291 token->token.user_sids = NULL;
4292 continue;
4295 return false;
4300 * Show the list of all users that have access to a share
4303 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4304 TALLOC_CTX *mem_ctx,
4305 const char *netname,
4306 int num_tokens,
4307 struct user_token *tokens)
4309 uint16_t fnum;
4310 SEC_DESC *share_sd = NULL;
4311 SEC_DESC *root_sd = NULL;
4312 struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4313 int i;
4314 union srvsvc_NetShareInfo info;
4315 WERROR result;
4316 NTSTATUS status;
4317 uint16 cnum;
4319 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4320 pipe_hnd->desthost,
4321 netname,
4322 502,
4323 &info,
4324 &result);
4326 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4327 DEBUG(1, ("Coult not query secdesc for share %s\n",
4328 netname));
4329 return;
4332 share_sd = info.info502->sd_buf.sd;
4333 if (share_sd == NULL) {
4334 DEBUG(1, ("Got no secdesc for share %s\n",
4335 netname));
4338 cnum = cli->cnum;
4340 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
4341 return;
4344 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
4345 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
4346 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4349 for (i=0; i<num_tokens; i++) {
4350 uint32 acc_granted;
4352 if (share_sd != NULL) {
4353 status = se_access_check(share_sd, &tokens[i].token,
4354 1, &acc_granted);
4356 if (!NT_STATUS_IS_OK(status)) {
4357 DEBUG(1, ("Could not check share_sd for "
4358 "user %s\n",
4359 tokens[i].name));
4360 continue;
4364 if (root_sd == NULL) {
4365 d_printf(" %s\n", tokens[i].name);
4366 continue;
4369 status = se_access_check(root_sd, &tokens[i].token,
4370 1, &acc_granted);
4371 if (!NT_STATUS_IS_OK(status)) {
4372 DEBUG(1, ("Could not check root_sd for user %s\n",
4373 tokens[i].name));
4374 continue;
4376 d_printf(" %s\n", tokens[i].name);
4379 if (fnum != (uint16_t)-1)
4380 cli_close(cli, fnum);
4381 cli_tdis(cli);
4382 cli->cnum = cnum;
4384 return;
4387 struct share_list {
4388 int num_shares;
4389 char **shares;
4392 static void collect_share(const char *name, uint32 m,
4393 const char *comment, void *state)
4395 struct share_list *share_list = (struct share_list *)state;
4397 if (m != STYPE_DISKTREE)
4398 return;
4400 share_list->num_shares += 1;
4401 share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4402 if (!share_list->shares) {
4403 share_list->num_shares = 0;
4404 return;
4406 share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4410 * List shares on a remote RPC server, including the security descriptors.
4412 * All parameters are provided by the run_rpc_command function, except for
4413 * argc, argv which are passed through.
4415 * @param domain_sid The domain sid acquired from the remote server.
4416 * @param cli A cli_state connected to the server.
4417 * @param mem_ctx Talloc context, destroyed on completion of the function.
4418 * @param argc Standard main() style argc.
4419 * @param argv Standard main() style argv. Initial components are already
4420 * stripped.
4422 * @return Normal NTSTATUS return.
4425 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
4426 const DOM_SID *domain_sid,
4427 const char *domain_name,
4428 struct cli_state *cli,
4429 struct rpc_pipe_client *pipe_hnd,
4430 TALLOC_CTX *mem_ctx,
4431 int argc,
4432 const char **argv)
4434 int ret;
4435 bool r;
4436 uint32 i;
4437 FILE *f;
4439 struct user_token *tokens = NULL;
4440 int num_tokens = 0;
4442 struct share_list share_list;
4444 if (argc == 0) {
4445 f = stdin;
4446 } else {
4447 f = fopen(argv[0], "r");
4450 if (f == NULL) {
4451 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4452 return NT_STATUS_UNSUCCESSFUL;
4455 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4457 if (f != stdin)
4458 fclose(f);
4460 if (!r) {
4461 DEBUG(0, ("Could not read users from file\n"));
4462 return NT_STATUS_UNSUCCESSFUL;
4465 for (i=0; i<num_tokens; i++)
4466 collect_alias_memberships(&tokens[i].token);
4468 share_list.num_shares = 0;
4469 share_list.shares = NULL;
4471 ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4473 if (ret == -1) {
4474 DEBUG(0, ("Error returning browse list: %s\n",
4475 cli_errstr(cli)));
4476 goto done;
4479 for (i = 0; i < share_list.num_shares; i++) {
4480 char *netname = share_list.shares[i];
4482 if (netname[strlen(netname)-1] == '$')
4483 continue;
4485 d_printf("%s\n", netname);
4487 show_userlist(pipe_hnd, mem_ctx, netname,
4488 num_tokens, tokens);
4490 done:
4491 for (i=0; i<num_tokens; i++) {
4492 free_user_token(&tokens[i].token);
4494 SAFE_FREE(tokens);
4495 SAFE_FREE(share_list.shares);
4497 return NT_STATUS_OK;
4500 static int rpc_share_allowedusers(struct net_context *c, int argc,
4501 const char **argv)
4503 int result;
4505 if (c->display_usage) {
4506 d_printf(_("Usage:\n"
4507 "net rpc share allowedusers\n"
4508 " List allowed users\n"));
4509 return 0;
4512 result = run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
4513 rpc_aliaslist_internals,
4514 argc, argv);
4515 if (result != 0)
4516 return result;
4518 result = run_rpc_command(c, NULL, &ndr_table_lsarpc.syntax_id, 0,
4519 rpc_aliaslist_dump,
4520 argc, argv);
4521 if (result != 0)
4522 return result;
4524 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4525 rpc_share_allowedusers_internals,
4526 argc, argv);
4529 int net_usersidlist(struct net_context *c, int argc, const char **argv)
4531 int num_tokens = 0;
4532 struct user_token *tokens = NULL;
4533 int i;
4535 if (argc != 0) {
4536 net_usersidlist_usage(c, argc, argv);
4537 return 0;
4540 if (!get_user_tokens(c, &num_tokens, &tokens)) {
4541 DEBUG(0, ("Could not get the user/sid list\n"));
4542 return 0;
4545 for (i=0; i<num_tokens; i++) {
4546 dump_user_token(&tokens[i]);
4547 free_user_token(&tokens[i].token);
4550 SAFE_FREE(tokens);
4551 return 1;
4554 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
4556 d_printf(_("net usersidlist\n"
4557 "\tprints out a list of all users the running winbind knows\n"
4558 "\tabout, together with all their SIDs. This is used as\n"
4559 "\tinput to the 'net rpc share allowedusers' command.\n\n"));
4561 net_common_flags_usage(c, argc, argv);
4562 return -1;
4566 * 'net rpc share' entrypoint.
4567 * @param argc Standard main() style argc.
4568 * @param argv Standard main() style argv. Initial components are already
4569 * stripped.
4572 int net_rpc_share(struct net_context *c, int argc, const char **argv)
4574 NET_API_STATUS status;
4576 struct functable func[] = {
4578 "add",
4579 rpc_share_add,
4580 NET_TRANSPORT_RPC,
4581 N_("Add share"),
4582 N_("net rpc share add\n"
4583 " Add share")
4586 "delete",
4587 rpc_share_delete,
4588 NET_TRANSPORT_RPC,
4589 N_("Remove share"),
4590 N_("net rpc share delete\n"
4591 " Remove share")
4594 "allowedusers",
4595 rpc_share_allowedusers,
4596 NET_TRANSPORT_RPC,
4597 N_("Modify allowed users"),
4598 N_("net rpc share allowedusers\n"
4599 " Modify allowed users")
4602 "migrate",
4603 rpc_share_migrate,
4604 NET_TRANSPORT_RPC,
4605 N_("Migrate share to local server"),
4606 N_("net rpc share migrate\n"
4607 " Migrate share to local server")
4610 "list",
4611 rpc_share_list,
4612 NET_TRANSPORT_RPC,
4613 N_("List shares"),
4614 N_("net rpc share list\n"
4615 " List shares")
4617 {NULL, NULL, 0, NULL, NULL}
4620 status = libnetapi_init(&c->netapi_ctx);
4621 if (status != 0) {
4622 return -1;
4624 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
4625 libnetapi_set_password(c->netapi_ctx, c->opt_password);
4626 if (c->opt_kerberos) {
4627 libnetapi_set_use_kerberos(c->netapi_ctx);
4630 if (argc == 0) {
4631 if (c->display_usage) {
4632 d_printf(_("Usage:\n"
4633 "net rpc share\n"
4634 " List shares\n"
4635 " Alias for net rpc share list\n"));
4636 net_display_usage_from_functable(func);
4637 return 0;
4640 return rpc_share_list(c, argc, argv);
4643 return net_run_function(c, argc, argv, "net rpc share", func);
4646 static NTSTATUS rpc_sh_share_list(struct net_context *c,
4647 TALLOC_CTX *mem_ctx,
4648 struct rpc_sh_ctx *ctx,
4649 struct rpc_pipe_client *pipe_hnd,
4650 int argc, const char **argv)
4653 return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
4656 static NTSTATUS rpc_sh_share_add(struct net_context *c,
4657 TALLOC_CTX *mem_ctx,
4658 struct rpc_sh_ctx *ctx,
4659 struct rpc_pipe_client *pipe_hnd,
4660 int argc, const char **argv)
4662 NET_API_STATUS status;
4663 uint32_t parm_err = 0;
4664 struct SHARE_INFO_2 i2;
4666 if ((argc < 2) || (argc > 3)) {
4667 d_fprintf(stderr, _("usage: %s <share> <path> [comment]\n"),
4668 ctx->whoami);
4669 return NT_STATUS_INVALID_PARAMETER;
4672 i2.shi2_netname = argv[0];
4673 i2.shi2_type = STYPE_DISKTREE;
4674 i2.shi2_remark = (argc == 3) ? argv[2] : "";
4675 i2.shi2_permissions = 0;
4676 i2.shi2_max_uses = 0;
4677 i2.shi2_current_uses = 0;
4678 i2.shi2_path = argv[1];
4679 i2.shi2_passwd = NULL;
4681 status = NetShareAdd(pipe_hnd->desthost,
4683 (uint8_t *)&i2,
4684 &parm_err);
4686 return werror_to_ntstatus(W_ERROR(status));
4689 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
4690 TALLOC_CTX *mem_ctx,
4691 struct rpc_sh_ctx *ctx,
4692 struct rpc_pipe_client *pipe_hnd,
4693 int argc, const char **argv)
4695 if (argc != 1) {
4696 d_fprintf(stderr, _("usage: %s <share>\n"), ctx->whoami);
4697 return NT_STATUS_INVALID_PARAMETER;
4700 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
4703 static NTSTATUS rpc_sh_share_info(struct net_context *c,
4704 TALLOC_CTX *mem_ctx,
4705 struct rpc_sh_ctx *ctx,
4706 struct rpc_pipe_client *pipe_hnd,
4707 int argc, const char **argv)
4709 union srvsvc_NetShareInfo info;
4710 WERROR result;
4711 NTSTATUS status;
4713 if (argc != 1) {
4714 d_fprintf(stderr, _("usage: %s <share>\n"), ctx->whoami);
4715 return NT_STATUS_INVALID_PARAMETER;
4718 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4719 pipe_hnd->desthost,
4720 argv[0],
4722 &info,
4723 &result);
4724 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4725 goto done;
4728 d_printf(_("Name: %s\n"), info.info2->name);
4729 d_printf(_("Comment: %s\n"), info.info2->comment);
4730 d_printf(_("Path: %s\n"), info.info2->path);
4731 d_printf(_("Password: %s\n"), info.info2->password);
4733 done:
4734 return werror_to_ntstatus(result);
4737 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
4738 struct rpc_sh_ctx *ctx)
4740 static struct rpc_sh_cmd cmds[] = {
4742 { "list", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_list,
4743 N_("List available shares") },
4745 { "add", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_add,
4746 N_("Add a share") },
4748 { "delete", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_delete,
4749 N_("Delete a share") },
4751 { "info", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_info,
4752 N_("Get information about a share") },
4754 { NULL, NULL, 0, NULL, NULL }
4757 return cmds;
4760 /****************************************************************************/
4762 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
4764 return net_file_usage(c, argc, argv);
4768 * Close a file on a remote RPC server.
4770 * @param argc Standard main() style argc.
4771 * @param argv Standard main() style argv. Initial components are already
4772 * stripped.
4774 * @return A shell status integer (0 for success).
4776 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
4778 if (argc < 1 || c->display_usage) {
4779 return rpc_file_usage(c, argc, argv);
4782 return NetFileClose(c->opt_host, atoi(argv[0]));
4786 * Formatted print of open file info
4788 * @param r struct FILE_INFO_3 contents
4791 static void display_file_info_3(struct FILE_INFO_3 *r)
4793 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
4794 r->fi3_id, r->fi3_username, r->fi3_permissions,
4795 r->fi3_num_locks, r->fi3_pathname);
4799 * List files for a user on a remote RPC server.
4801 * @param argc Standard main() style argc.
4802 * @param argv Standard main() style argv. Initial components are already
4803 * stripped.
4805 * @return A shell status integer (0 for success)..
4808 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
4810 NET_API_STATUS status;
4811 uint32 preferred_len = 0xffffffff, i;
4812 const char *username=NULL;
4813 uint32_t total_entries = 0;
4814 uint32_t entries_read = 0;
4815 uint32_t resume_handle = 0;
4816 struct FILE_INFO_3 *i3 = NULL;
4818 if (c->display_usage) {
4819 return rpc_file_usage(c, argc, argv);
4822 /* if argc > 0, must be user command */
4823 if (argc > 0) {
4824 username = smb_xstrdup(argv[0]);
4827 status = NetFileEnum(c->opt_host,
4828 NULL,
4829 username,
4831 (uint8_t **)(void *)&i3,
4832 preferred_len,
4833 &entries_read,
4834 &total_entries,
4835 &resume_handle);
4837 if (status != 0) {
4838 goto done;
4841 /* Display results */
4843 d_printf(_(
4844 "\nEnumerating open files on remote server:\n\n"
4845 "\nFileId Opened by Perms Locks Path"
4846 "\n------ --------- ----- ----- ---- \n"));
4847 for (i = 0; i < entries_read; i++) {
4848 display_file_info_3(&i3[i]);
4850 done:
4851 return status;
4855 * 'net rpc file' entrypoint.
4856 * @param argc Standard main() style argc.
4857 * @param argv Standard main() style argv. Initial components are already
4858 * stripped.
4861 int net_rpc_file(struct net_context *c, int argc, const char **argv)
4863 NET_API_STATUS status;
4865 struct functable func[] = {
4867 "close",
4868 rpc_file_close,
4869 NET_TRANSPORT_RPC,
4870 N_("Close opened file"),
4871 N_("net rpc file close\n"
4872 " Close opened file")
4875 "user",
4876 rpc_file_user,
4877 NET_TRANSPORT_RPC,
4878 N_("List files opened by user"),
4879 N_("net rpc file user\n"
4880 " List files opened by user")
4882 #if 0
4884 "info",
4885 rpc_file_info,
4886 NET_TRANSPORT_RPC,
4887 N_("Display information about opened file"),
4888 N_("net rpc file info\n"
4889 " Display information about opened file")
4891 #endif
4892 {NULL, NULL, 0, NULL, NULL}
4895 status = libnetapi_init(&c->netapi_ctx);
4896 if (status != 0) {
4897 return -1;
4899 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
4900 libnetapi_set_password(c->netapi_ctx, c->opt_password);
4901 if (c->opt_kerberos) {
4902 libnetapi_set_use_kerberos(c->netapi_ctx);
4905 if (argc == 0) {
4906 if (c->display_usage) {
4907 d_printf(_("Usage:\n"));
4908 d_printf(_("net rpc file\n"
4909 " List opened files\n"));
4910 net_display_usage_from_functable(func);
4911 return 0;
4914 return rpc_file_user(c, argc, argv);
4917 return net_run_function(c, argc, argv, "net rpc file", func);
4921 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
4923 * All parameters are provided by the run_rpc_command function, except for
4924 * argc, argv which are passed through.
4926 * @param c A net_context structure.
4927 * @param domain_sid The domain sid acquired from the remote server.
4928 * @param cli A cli_state connected to the server.
4929 * @param mem_ctx Talloc context, destroyed on completion of the function.
4930 * @param argc Standard main() style argc.
4931 * @param argv Standard main() style argv. Initial components are already
4932 * stripped.
4934 * @return Normal NTSTATUS return.
4937 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
4938 const DOM_SID *domain_sid,
4939 const char *domain_name,
4940 struct cli_state *cli,
4941 struct rpc_pipe_client *pipe_hnd,
4942 TALLOC_CTX *mem_ctx,
4943 int argc,
4944 const char **argv)
4946 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4948 result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
4950 if (NT_STATUS_IS_OK(result)) {
4951 d_printf(_("\nShutdown successfully aborted\n"));
4952 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
4953 } else
4954 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
4956 return result;
4960 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
4962 * All parameters are provided by the run_rpc_command function, except for
4963 * argc, argv which are passed through.
4965 * @param c A net_context structure.
4966 * @param domain_sid The domain sid acquired from the remote server.
4967 * @param cli A cli_state connected to the server.
4968 * @param mem_ctx Talloc context, destroyed on completion of the function.
4969 * @param argc Standard main() style argc.
4970 * @param argv Standard main() style argv. Initial components are already
4971 * stripped.
4973 * @return Normal NTSTATUS return.
4976 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
4977 const DOM_SID *domain_sid,
4978 const char *domain_name,
4979 struct cli_state *cli,
4980 struct rpc_pipe_client *pipe_hnd,
4981 TALLOC_CTX *mem_ctx,
4982 int argc,
4983 const char **argv)
4985 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4987 result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
4989 if (NT_STATUS_IS_OK(result)) {
4990 d_printf(_("\nShutdown successfully aborted\n"));
4991 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
4992 } else
4993 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
4995 return result;
4999 * ABORT the shutdown of a remote RPC server.
5001 * @param argc Standard main() style argc.
5002 * @param argv Standard main() style argv. Initial components are already
5003 * stripped.
5005 * @return A shell status integer (0 for success).
5008 static int rpc_shutdown_abort(struct net_context *c, int argc,
5009 const char **argv)
5011 int rc = -1;
5013 if (c->display_usage) {
5014 d_printf(_("Usage:\n"
5015 "net rpc abortshutdown\n"
5016 " Abort a scheduled shutdown\n"));
5017 return 0;
5020 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5021 rpc_shutdown_abort_internals, argc, argv);
5023 if (rc == 0)
5024 return rc;
5026 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5028 return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5029 rpc_reg_shutdown_abort_internals,
5030 argc, argv);
5034 * Shut down a remote RPC Server via initshutdown pipe.
5036 * All parameters are provided by the run_rpc_command function, except for
5037 * argc, argv which are passed through.
5039 * @param c A net_context structure.
5040 * @param domain_sid The domain sid acquired from the remote server.
5041 * @param cli A cli_state connected to the server.
5042 * @param mem_ctx Talloc context, destroyed on completion of the function.
5043 * @param argc Standard main() style argc.
5044 * @param argv Standard main() style argv. Initial components are already
5045 * stripped.
5047 * @return Normal NTSTATUS return.
5050 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5051 const DOM_SID *domain_sid,
5052 const char *domain_name,
5053 struct cli_state *cli,
5054 struct rpc_pipe_client *pipe_hnd,
5055 TALLOC_CTX *mem_ctx,
5056 int argc,
5057 const char **argv)
5059 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5060 const char *msg = N_("This machine will be shutdown shortly");
5061 uint32 timeout = 20;
5062 struct lsa_StringLarge msg_string;
5064 if (c->opt_comment) {
5065 msg = c->opt_comment;
5067 if (c->opt_timeout) {
5068 timeout = c->opt_timeout;
5071 msg_string.string = msg;
5073 /* create an entry */
5074 result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5075 &msg_string, timeout, c->opt_force, c->opt_reboot,
5076 NULL);
5078 if (NT_STATUS_IS_OK(result)) {
5079 d_printf(_("\nShutdown of remote machine succeeded\n"));
5080 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5081 } else {
5082 DEBUG(1,("Shutdown of remote machine failed!\n"));
5084 return result;
5088 * Shut down a remote RPC Server via winreg pipe.
5090 * All parameters are provided by the run_rpc_command function, except for
5091 * argc, argv which are passed through.
5093 * @param c A net_context structure.
5094 * @param domain_sid The domain sid acquired from the remote server.
5095 * @param cli A cli_state connected to the server.
5096 * @param mem_ctx Talloc context, destroyed on completion of the function.
5097 * @param argc Standard main() style argc.
5098 * @param argv Standard main() style argv. Initial components are already
5099 * stripped.
5101 * @return Normal NTSTATUS return.
5104 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5105 const DOM_SID *domain_sid,
5106 const char *domain_name,
5107 struct cli_state *cli,
5108 struct rpc_pipe_client *pipe_hnd,
5109 TALLOC_CTX *mem_ctx,
5110 int argc,
5111 const char **argv)
5113 const char *msg = N_("This machine will be shutdown shortly");
5114 uint32 timeout = 20;
5115 struct lsa_StringLarge msg_string;
5116 NTSTATUS result;
5117 WERROR werr;
5119 if (c->opt_comment) {
5120 msg = c->opt_comment;
5122 msg_string.string = msg;
5124 if (c->opt_timeout) {
5125 timeout = c->opt_timeout;
5128 /* create an entry */
5129 result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5130 &msg_string, timeout, c->opt_force, c->opt_reboot,
5131 &werr);
5133 if (NT_STATUS_IS_OK(result)) {
5134 d_printf(_("\nShutdown of remote machine succeeded\n"));
5135 } else {
5136 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5137 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5138 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5139 else
5140 d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5143 return result;
5147 * Shut down a remote RPC server.
5149 * @param argc Standard main() style argc.
5150 * @param argv Standard main() style argv. Initial components are already
5151 * stripped.
5153 * @return A shell status integer (0 for success).
5156 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5158 int rc = -1;
5160 if (c->display_usage) {
5161 d_printf(_("Usage:\n"
5162 "net rpc shutdown\n"
5163 " Shut down a remote RPC server\n"));
5164 return 0;
5167 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5168 rpc_init_shutdown_internals, argc, argv);
5170 if (rc) {
5171 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5172 rc = run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5173 rpc_reg_shutdown_internals, argc, argv);
5176 return rc;
5179 /***************************************************************************
5180 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5181 ***************************************************************************/
5184 * Add interdomain trust account to the RPC server.
5185 * All parameters (except for argc and argv) are passed by run_rpc_command
5186 * function.
5188 * @param c A net_context structure.
5189 * @param domain_sid The domain sid acquired from the server.
5190 * @param cli A cli_state connected to the server.
5191 * @param mem_ctx Talloc context, destroyed on completion of the function.
5192 * @param argc Standard main() style argc.
5193 * @param argv Standard main() style argv. Initial components are already
5194 * stripped.
5196 * @return normal NTSTATUS return code.
5199 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
5200 const DOM_SID *domain_sid,
5201 const char *domain_name,
5202 struct cli_state *cli,
5203 struct rpc_pipe_client *pipe_hnd,
5204 TALLOC_CTX *mem_ctx,
5205 int argc,
5206 const char **argv)
5208 struct policy_handle connect_pol, domain_pol, user_pol;
5209 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5210 char *acct_name;
5211 struct lsa_String lsa_acct_name;
5212 uint32 acb_info;
5213 uint32 acct_flags=0;
5214 uint32 user_rid;
5215 uint32_t access_granted = 0;
5216 union samr_UserInfo info;
5217 unsigned int orig_timeout;
5219 if (argc != 2) {
5220 d_printf(_("Usage: net rpc trustdom add <domain_name> "
5221 "<trust password>\n"));
5222 return NT_STATUS_INVALID_PARAMETER;
5226 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5229 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5230 return NT_STATUS_NO_MEMORY;
5233 strupper_m(acct_name);
5235 init_lsa_String(&lsa_acct_name, acct_name);
5237 /* Get samr policy handle */
5238 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5239 pipe_hnd->desthost,
5240 MAXIMUM_ALLOWED_ACCESS,
5241 &connect_pol);
5242 if (!NT_STATUS_IS_OK(result)) {
5243 goto done;
5246 /* Get domain policy handle */
5247 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5248 &connect_pol,
5249 MAXIMUM_ALLOWED_ACCESS,
5250 CONST_DISCARD(struct dom_sid2 *, domain_sid),
5251 &domain_pol);
5252 if (!NT_STATUS_IS_OK(result)) {
5253 goto done;
5256 /* This call can take a long time - allow the server to time out.
5257 * 35 seconds should do it. */
5259 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5261 /* Create trusting domain's account */
5262 acb_info = ACB_NORMAL;
5263 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5264 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5265 SAMR_USER_ACCESS_SET_PASSWORD |
5266 SAMR_USER_ACCESS_GET_ATTRIBUTES |
5267 SAMR_USER_ACCESS_SET_ATTRIBUTES;
5269 result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5270 &domain_pol,
5271 &lsa_acct_name,
5272 acb_info,
5273 acct_flags,
5274 &user_pol,
5275 &access_granted,
5276 &user_rid);
5278 /* And restore our original timeout. */
5279 rpccli_set_timeout(pipe_hnd, orig_timeout);
5281 if (!NT_STATUS_IS_OK(result)) {
5282 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
5283 acct_name, nt_errstr(result));
5284 goto done;
5288 struct samr_CryptPassword crypt_pwd;
5290 ZERO_STRUCT(info.info23);
5292 init_samr_CryptPassword(argv[1],
5293 &cli->user_session_key,
5294 &crypt_pwd);
5296 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
5297 SAMR_FIELD_NT_PASSWORD_PRESENT;
5298 info.info23.info.acct_flags = ACB_DOMTRUST;
5299 info.info23.password = crypt_pwd;
5301 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5302 &user_pol,
5304 &info);
5306 if (!NT_STATUS_IS_OK(result)) {
5307 DEBUG(0,("Could not set trust account password: %s\n",
5308 nt_errstr(result)));
5309 goto done;
5313 done:
5314 SAFE_FREE(acct_name);
5315 return result;
5319 * Create interdomain trust account for a remote domain.
5321 * @param argc Standard argc.
5322 * @param argv Standard argv without initial components.
5324 * @return Integer status (0 means success).
5327 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5329 if (argc > 0 && !c->display_usage) {
5330 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5331 rpc_trustdom_add_internals, argc, argv);
5332 } else {
5333 d_printf(_("Usage:\n"
5334 "net rpc trustdom add <domain_name> <trust "
5335 "password>\n"));
5336 return -1;
5342 * Remove interdomain trust account from the RPC server.
5343 * All parameters (except for argc and argv) are passed by run_rpc_command
5344 * function.
5346 * @param c A net_context structure.
5347 * @param domain_sid The domain sid acquired from the server.
5348 * @param cli A cli_state connected to the server.
5349 * @param mem_ctx Talloc context, destroyed on completion of the function.
5350 * @param argc Standard main() style argc.
5351 * @param argv Standard main() style argv. Initial components are already
5352 * stripped.
5354 * @return normal NTSTATUS return code.
5357 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
5358 const DOM_SID *domain_sid,
5359 const char *domain_name,
5360 struct cli_state *cli,
5361 struct rpc_pipe_client *pipe_hnd,
5362 TALLOC_CTX *mem_ctx,
5363 int argc,
5364 const char **argv)
5366 struct policy_handle connect_pol, domain_pol, user_pol;
5367 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5368 char *acct_name;
5369 DOM_SID trust_acct_sid;
5370 struct samr_Ids user_rids, name_types;
5371 struct lsa_String lsa_acct_name;
5373 if (argc != 1) {
5374 d_printf(_("Usage: net rpc trustdom del <domain_name>\n"));
5375 return NT_STATUS_INVALID_PARAMETER;
5379 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5381 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5383 if (acct_name == NULL)
5384 return NT_STATUS_NO_MEMORY;
5386 strupper_m(acct_name);
5388 /* Get samr policy handle */
5389 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5390 pipe_hnd->desthost,
5391 MAXIMUM_ALLOWED_ACCESS,
5392 &connect_pol);
5393 if (!NT_STATUS_IS_OK(result)) {
5394 goto done;
5397 /* Get domain policy handle */
5398 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5399 &connect_pol,
5400 MAXIMUM_ALLOWED_ACCESS,
5401 CONST_DISCARD(struct dom_sid2 *, domain_sid),
5402 &domain_pol);
5403 if (!NT_STATUS_IS_OK(result)) {
5404 goto done;
5407 init_lsa_String(&lsa_acct_name, acct_name);
5409 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5410 &domain_pol,
5412 &lsa_acct_name,
5413 &user_rids,
5414 &name_types);
5416 if (!NT_STATUS_IS_OK(result)) {
5417 d_printf(_("net rpc trustdom del: LookupNames on user %s "
5418 "failed %s\n"),
5419 acct_name, nt_errstr(result) );
5420 goto done;
5423 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5424 &domain_pol,
5425 MAXIMUM_ALLOWED_ACCESS,
5426 user_rids.ids[0],
5427 &user_pol);
5429 if (!NT_STATUS_IS_OK(result)) {
5430 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
5431 "%s\n"),
5432 acct_name, nt_errstr(result) );
5433 goto done;
5436 /* append the rid to the domain sid */
5437 sid_copy(&trust_acct_sid, domain_sid);
5438 if (!sid_append_rid(&trust_acct_sid, user_rids.ids[0])) {
5439 goto done;
5442 /* remove the sid */
5444 result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5445 &user_pol,
5446 &trust_acct_sid);
5447 if (!NT_STATUS_IS_OK(result)) {
5448 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
5449 " on user %s failed %s\n"),
5450 acct_name, nt_errstr(result) );
5451 goto done;
5454 /* Delete user */
5456 result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5457 &user_pol);
5459 if (!NT_STATUS_IS_OK(result)) {
5460 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
5461 "%s\n"),
5462 acct_name, nt_errstr(result) );
5463 goto done;
5466 if (!NT_STATUS_IS_OK(result)) {
5467 d_printf(_("Could not set trust account password: %s\n"),
5468 nt_errstr(result));
5469 goto done;
5472 done:
5473 return result;
5477 * Delete interdomain trust account for a remote domain.
5479 * @param argc Standard argc.
5480 * @param argv Standard argv without initial components.
5482 * @return Integer status (0 means success).
5485 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
5487 if (argc > 0 && !c->display_usage) {
5488 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5489 rpc_trustdom_del_internals, argc, argv);
5490 } else {
5491 d_printf(_("Usage:\n"
5492 "net rpc trustdom del <domain>\n"));
5493 return -1;
5497 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
5498 struct cli_state *cli,
5499 TALLOC_CTX *mem_ctx,
5500 const char *domain_name)
5502 char *dc_name = NULL;
5503 const char *buffer = NULL;
5504 struct rpc_pipe_client *netr;
5505 NTSTATUS status;
5507 /* Use NetServerEnum2 */
5509 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
5510 SAFE_FREE(dc_name);
5511 return NT_STATUS_OK;
5514 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
5515 for domain %s\n", domain_name));
5517 /* Try netr_GetDcName */
5519 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
5520 &netr);
5521 if (!NT_STATUS_IS_OK(status)) {
5522 return status;
5525 status = rpccli_netr_GetDcName(netr, mem_ctx,
5526 cli->desthost,
5527 domain_name,
5528 &buffer,
5529 NULL);
5530 TALLOC_FREE(netr);
5532 if (NT_STATUS_IS_OK(status)) {
5533 return status;
5536 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
5537 for domain %s\n", domain_name));
5539 return status;
5543 * Establish trust relationship to a trusting domain.
5544 * Interdomain account must already be created on remote PDC.
5546 * @param c A net_context structure.
5547 * @param argc Standard argc.
5548 * @param argv Standard argv without initial components.
5550 * @return Integer status (0 means success).
5553 static int rpc_trustdom_establish(struct net_context *c, int argc,
5554 const char **argv)
5556 struct cli_state *cli = NULL;
5557 struct sockaddr_storage server_ss;
5558 struct rpc_pipe_client *pipe_hnd = NULL;
5559 struct policy_handle connect_hnd;
5560 TALLOC_CTX *mem_ctx;
5561 NTSTATUS nt_status;
5562 DOM_SID *domain_sid;
5564 char* domain_name;
5565 char* acct_name;
5566 fstring pdc_name;
5567 union lsa_PolicyInformation *info = NULL;
5570 * Connect to \\server\ipc$ as 'our domain' account with password
5573 if (argc != 1 || c->display_usage) {
5574 d_printf(_("Usage:\n"
5575 "net rpc trustdom establish <domain_name>\n"));
5576 return -1;
5579 domain_name = smb_xstrdup(argv[0]);
5580 strupper_m(domain_name);
5582 /* account name used at first is our domain's name with '$' */
5583 if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
5584 return -1;
5586 strupper_m(acct_name);
5589 * opt_workgroup will be used by connection functions further,
5590 * hence it should be set to remote domain name instead of ours
5592 if (c->opt_workgroup) {
5593 c->opt_workgroup = smb_xstrdup(domain_name);
5596 c->opt_user_name = acct_name;
5598 /* find the domain controller */
5599 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5600 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5601 return -1;
5604 /* connect to ipc$ as username/password */
5605 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
5606 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5608 /* Is it trusting domain account for sure ? */
5609 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5610 nt_errstr(nt_status)));
5611 return -1;
5614 /* store who we connected to */
5616 saf_store( domain_name, pdc_name );
5619 * Connect to \\server\ipc$ again (this time anonymously)
5622 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
5623 (char*)pdc_name);
5625 if (NT_STATUS_IS_ERR(nt_status)) {
5626 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5627 domain_name, nt_errstr(nt_status)));
5628 return -1;
5631 if (!(mem_ctx = talloc_init("establishing trust relationship to "
5632 "domain %s", domain_name))) {
5633 DEBUG(0, ("talloc_init() failed\n"));
5634 cli_shutdown(cli);
5635 return -1;
5638 /* Make sure we're talking to a proper server */
5640 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
5641 if (!NT_STATUS_IS_OK(nt_status)) {
5642 cli_shutdown(cli);
5643 talloc_destroy(mem_ctx);
5644 return -1;
5648 * Call LsaOpenPolicy and LsaQueryInfo
5651 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5652 &pipe_hnd);
5653 if (!NT_STATUS_IS_OK(nt_status)) {
5654 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5655 cli_shutdown(cli);
5656 talloc_destroy(mem_ctx);
5657 return -1;
5660 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
5661 &connect_hnd);
5662 if (NT_STATUS_IS_ERR(nt_status)) {
5663 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5664 nt_errstr(nt_status)));
5665 cli_shutdown(cli);
5666 talloc_destroy(mem_ctx);
5667 return -1;
5670 /* Querying info level 5 */
5672 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5673 &connect_hnd,
5674 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5675 &info);
5676 if (NT_STATUS_IS_ERR(nt_status)) {
5677 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5678 nt_errstr(nt_status)));
5679 cli_shutdown(cli);
5680 talloc_destroy(mem_ctx);
5681 return -1;
5684 domain_sid = info->account_domain.sid;
5686 /* There should be actually query info level 3 (following nt serv behaviour),
5687 but I still don't know if it's _really_ necessary */
5690 * Store the password in secrets db
5693 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
5694 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5695 cli_shutdown(cli);
5696 talloc_destroy(mem_ctx);
5697 return -1;
5701 * Close the pipes and clean up
5704 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5705 if (NT_STATUS_IS_ERR(nt_status)) {
5706 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5707 nt_errstr(nt_status)));
5708 cli_shutdown(cli);
5709 talloc_destroy(mem_ctx);
5710 return -1;
5713 cli_shutdown(cli);
5715 talloc_destroy(mem_ctx);
5717 d_printf(_("Trust to domain %s established\n"), domain_name);
5718 return 0;
5722 * Revoke trust relationship to the remote domain.
5724 * @param c A net_context structure.
5725 * @param argc Standard argc.
5726 * @param argv Standard argv without initial components.
5728 * @return Integer status (0 means success).
5731 static int rpc_trustdom_revoke(struct net_context *c, int argc,
5732 const char **argv)
5734 char* domain_name;
5735 int rc = -1;
5737 if (argc < 1 || c->display_usage) {
5738 d_printf(_("Usage:\n"
5739 "net rpc trustdom revoke <domain_name>\n"
5740 " Revoke trust relationship\n"
5741 " domain_name\tName of domain to revoke trust\n"));
5742 return -1;
5745 /* generate upper cased domain name */
5746 domain_name = smb_xstrdup(argv[0]);
5747 strupper_m(domain_name);
5749 /* delete password of the trust */
5750 if (!pdb_del_trusteddom_pw(domain_name)) {
5751 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
5752 domain_name));
5753 goto done;
5756 rc = 0;
5757 done:
5758 SAFE_FREE(domain_name);
5759 return rc;
5762 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
5763 const DOM_SID *domain_sid,
5764 const char *domain_name,
5765 struct cli_state *cli,
5766 struct rpc_pipe_client *pipe_hnd,
5767 TALLOC_CTX *mem_ctx,
5768 int argc,
5769 const char **argv)
5771 fstring str_sid;
5772 sid_to_fstring(str_sid, domain_sid);
5773 d_printf("%s\n", str_sid);
5774 return NT_STATUS_OK;
5777 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
5779 fstring ascii_sid, padding;
5780 int pad_len, col_len = 20;
5782 /* convert sid into ascii string */
5783 sid_to_fstring(ascii_sid, dom_sid);
5785 /* calculate padding space for d_printf to look nicer */
5786 pad_len = col_len - strlen(trusted_dom_name);
5787 padding[pad_len] = 0;
5788 do padding[--pad_len] = ' '; while (pad_len);
5790 d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
5793 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
5794 TALLOC_CTX *mem_ctx,
5795 struct policy_handle *pol,
5796 DOM_SID dom_sid,
5797 const char *trusted_dom_name)
5799 NTSTATUS nt_status;
5800 union lsa_TrustedDomainInfo *info = NULL;
5801 char *cleartextpwd = NULL;
5802 uint8_t session_key[16];
5803 DATA_BLOB session_key_blob;
5804 DATA_BLOB data = data_blob_null;
5806 nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
5807 pol,
5808 &dom_sid,
5809 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
5810 &info);
5811 if (NT_STATUS_IS_ERR(nt_status)) {
5812 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5813 nt_errstr(nt_status)));
5814 goto done;
5817 data = data_blob(info->password.password->data,
5818 info->password.password->length);
5820 if (!rpccli_get_pwd_hash(pipe_hnd, session_key)) {
5821 DEBUG(0, ("Could not retrieve password hash\n"));
5822 goto done;
5825 session_key_blob = data_blob_const(session_key, sizeof(session_key));
5826 cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key_blob);
5828 if (cleartextpwd == NULL) {
5829 DEBUG(0,("retrieved NULL password\n"));
5830 nt_status = NT_STATUS_UNSUCCESSFUL;
5831 goto done;
5834 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
5835 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5836 nt_status = NT_STATUS_UNSUCCESSFUL;
5837 goto done;
5840 #ifdef DEBUG_PASSWORD
5841 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
5842 "password: [%s]\n", trusted_dom_name,
5843 sid_string_dbg(&dom_sid), cleartextpwd));
5844 #endif
5846 done:
5847 SAFE_FREE(cleartextpwd);
5848 data_blob_free(&data);
5850 return nt_status;
5853 static int rpc_trustdom_vampire(struct net_context *c, int argc,
5854 const char **argv)
5856 /* common variables */
5857 TALLOC_CTX* mem_ctx;
5858 struct cli_state *cli = NULL;
5859 struct rpc_pipe_client *pipe_hnd = NULL;
5860 NTSTATUS nt_status;
5861 const char *domain_name = NULL;
5862 DOM_SID *queried_dom_sid;
5863 struct policy_handle connect_hnd;
5864 union lsa_PolicyInformation *info = NULL;
5866 /* trusted domains listing variables */
5867 unsigned int enum_ctx = 0;
5868 int i;
5869 struct lsa_DomainList dom_list;
5870 fstring pdc_name;
5872 if (c->display_usage) {
5873 d_printf(_("Usage:\n"
5874 "net rpc trustdom vampire\n"
5875 " Vampire trust relationship from remote server\n"));
5876 return 0;
5880 * Listing trusted domains (stored in secrets.tdb, if local)
5883 mem_ctx = talloc_init("trust relationships vampire");
5886 * set domain and pdc name to local samba server (default)
5887 * or to remote one given in command line
5890 if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
5891 domain_name = c->opt_workgroup;
5892 c->opt_target_workgroup = c->opt_workgroup;
5893 } else {
5894 fstrcpy(pdc_name, global_myname());
5895 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5896 c->opt_target_workgroup = domain_name;
5899 /* open \PIPE\lsarpc and open policy handle */
5900 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
5901 if (!NT_STATUS_IS_OK(nt_status)) {
5902 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
5903 nt_errstr(nt_status)));
5904 talloc_destroy(mem_ctx);
5905 return -1;
5908 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5909 &pipe_hnd);
5910 if (!NT_STATUS_IS_OK(nt_status)) {
5911 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
5912 nt_errstr(nt_status) ));
5913 cli_shutdown(cli);
5914 talloc_destroy(mem_ctx);
5915 return -1;
5918 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
5919 &connect_hnd);
5920 if (NT_STATUS_IS_ERR(nt_status)) {
5921 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5922 nt_errstr(nt_status)));
5923 cli_shutdown(cli);
5924 talloc_destroy(mem_ctx);
5925 return -1;
5928 /* query info level 5 to obtain sid of a domain being queried */
5929 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5930 &connect_hnd,
5931 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5932 &info);
5934 if (NT_STATUS_IS_ERR(nt_status)) {
5935 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5936 nt_errstr(nt_status)));
5937 cli_shutdown(cli);
5938 talloc_destroy(mem_ctx);
5939 return -1;
5942 queried_dom_sid = info->account_domain.sid;
5945 * Keep calling LsaEnumTrustdom over opened pipe until
5946 * the end of enumeration is reached
5949 d_printf(_("Vampire trusted domains:\n\n"));
5951 do {
5952 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
5953 &connect_hnd,
5954 &enum_ctx,
5955 &dom_list,
5956 (uint32_t)-1);
5957 if (NT_STATUS_IS_ERR(nt_status)) {
5958 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
5959 nt_errstr(nt_status)));
5960 cli_shutdown(cli);
5961 talloc_destroy(mem_ctx);
5962 return -1;
5965 for (i = 0; i < dom_list.count; i++) {
5967 print_trusted_domain(dom_list.domains[i].sid,
5968 dom_list.domains[i].name.string);
5970 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
5971 *dom_list.domains[i].sid,
5972 dom_list.domains[i].name.string);
5973 if (!NT_STATUS_IS_OK(nt_status)) {
5974 cli_shutdown(cli);
5975 talloc_destroy(mem_ctx);
5976 return -1;
5981 * in case of no trusted domains say something rather
5982 * than just display blank line
5984 if (!dom_list.count) d_printf(_("none\n"));
5986 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
5988 /* close this connection before doing next one */
5989 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5990 if (NT_STATUS_IS_ERR(nt_status)) {
5991 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
5992 nt_errstr(nt_status)));
5993 cli_shutdown(cli);
5994 talloc_destroy(mem_ctx);
5995 return -1;
5998 /* close lsarpc pipe and connection to IPC$ */
5999 cli_shutdown(cli);
6001 talloc_destroy(mem_ctx);
6002 return 0;
6005 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6007 /* common variables */
6008 TALLOC_CTX* mem_ctx;
6009 struct cli_state *cli = NULL, *remote_cli = NULL;
6010 struct rpc_pipe_client *pipe_hnd = NULL;
6011 NTSTATUS nt_status;
6012 const char *domain_name = NULL;
6013 DOM_SID *queried_dom_sid;
6014 fstring padding;
6015 int ascii_dom_name_len;
6016 struct policy_handle connect_hnd;
6017 union lsa_PolicyInformation *info = NULL;
6019 /* trusted domains listing variables */
6020 unsigned int num_domains, enum_ctx = 0;
6021 int i, pad_len, col_len = 20;
6022 struct lsa_DomainList dom_list;
6023 fstring pdc_name;
6025 /* trusting domains listing variables */
6026 struct policy_handle domain_hnd;
6027 struct samr_SamArray *trusts = NULL;
6029 if (c->display_usage) {
6030 d_printf(_("Usage:\n"
6031 "net rpc trustdom list\n"
6032 " List in- and outgoing trust relationships\n"));
6033 return 0;
6037 * Listing trusted domains (stored in secrets.tdb, if local)
6040 mem_ctx = talloc_init("trust relationships listing");
6043 * set domain and pdc name to local samba server (default)
6044 * or to remote one given in command line
6047 if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6048 domain_name = c->opt_workgroup;
6049 c->opt_target_workgroup = c->opt_workgroup;
6050 } else {
6051 fstrcpy(pdc_name, global_myname());
6052 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6053 c->opt_target_workgroup = domain_name;
6056 /* open \PIPE\lsarpc and open policy handle */
6057 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6058 if (!NT_STATUS_IS_OK(nt_status)) {
6059 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6060 nt_errstr(nt_status)));
6061 talloc_destroy(mem_ctx);
6062 return -1;
6065 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6066 &pipe_hnd);
6067 if (!NT_STATUS_IS_OK(nt_status)) {
6068 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6069 nt_errstr(nt_status) ));
6070 cli_shutdown(cli);
6071 talloc_destroy(mem_ctx);
6072 return -1;
6075 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6076 &connect_hnd);
6077 if (NT_STATUS_IS_ERR(nt_status)) {
6078 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6079 nt_errstr(nt_status)));
6080 cli_shutdown(cli);
6081 talloc_destroy(mem_ctx);
6082 return -1;
6085 /* query info level 5 to obtain sid of a domain being queried */
6086 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6087 &connect_hnd,
6088 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6089 &info);
6091 if (NT_STATUS_IS_ERR(nt_status)) {
6092 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6093 nt_errstr(nt_status)));
6094 cli_shutdown(cli);
6095 talloc_destroy(mem_ctx);
6096 return -1;
6099 queried_dom_sid = info->account_domain.sid;
6102 * Keep calling LsaEnumTrustdom over opened pipe until
6103 * the end of enumeration is reached
6106 d_printf(_("Trusted domains list:\n\n"));
6108 do {
6109 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6110 &connect_hnd,
6111 &enum_ctx,
6112 &dom_list,
6113 (uint32_t)-1);
6114 if (NT_STATUS_IS_ERR(nt_status)) {
6115 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6116 nt_errstr(nt_status)));
6117 cli_shutdown(cli);
6118 talloc_destroy(mem_ctx);
6119 return -1;
6122 for (i = 0; i < dom_list.count; i++) {
6123 print_trusted_domain(dom_list.domains[i].sid,
6124 dom_list.domains[i].name.string);
6128 * in case of no trusted domains say something rather
6129 * than just display blank line
6131 if (!dom_list.count) d_printf(_("none\n"));
6133 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6135 /* close this connection before doing next one */
6136 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6137 if (NT_STATUS_IS_ERR(nt_status)) {
6138 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6139 nt_errstr(nt_status)));
6140 cli_shutdown(cli);
6141 talloc_destroy(mem_ctx);
6142 return -1;
6145 TALLOC_FREE(pipe_hnd);
6148 * Listing trusting domains (stored in passdb backend, if local)
6151 d_printf(_("\nTrusting domains list:\n\n"));
6154 * Open \PIPE\samr and get needed policy handles
6156 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6157 &pipe_hnd);
6158 if (!NT_STATUS_IS_OK(nt_status)) {
6159 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6160 cli_shutdown(cli);
6161 talloc_destroy(mem_ctx);
6162 return -1;
6165 /* SamrConnect2 */
6166 nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6167 pipe_hnd->desthost,
6168 SAMR_ACCESS_LOOKUP_DOMAIN,
6169 &connect_hnd);
6170 if (!NT_STATUS_IS_OK(nt_status)) {
6171 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6172 nt_errstr(nt_status)));
6173 cli_shutdown(cli);
6174 talloc_destroy(mem_ctx);
6175 return -1;
6178 /* SamrOpenDomain - we have to open domain policy handle in order to be
6179 able to enumerate accounts*/
6180 nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6181 &connect_hnd,
6182 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6183 queried_dom_sid,
6184 &domain_hnd);
6185 if (!NT_STATUS_IS_OK(nt_status)) {
6186 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6187 nt_errstr(nt_status)));
6188 cli_shutdown(cli);
6189 talloc_destroy(mem_ctx);
6190 return -1;
6194 * perform actual enumeration
6197 enum_ctx = 0; /* reset enumeration context from last enumeration */
6198 do {
6200 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6201 &domain_hnd,
6202 &enum_ctx,
6203 ACB_DOMTRUST,
6204 &trusts,
6205 0xffff,
6206 &num_domains);
6207 if (NT_STATUS_IS_ERR(nt_status)) {
6208 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6209 nt_errstr(nt_status)));
6210 cli_shutdown(cli);
6211 talloc_destroy(mem_ctx);
6212 return -1;
6215 for (i = 0; i < num_domains; i++) {
6217 char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6220 * get each single domain's sid (do we _really_ need this ?):
6221 * 1) connect to domain's pdc
6222 * 2) query the pdc for domain's sid
6225 /* get rid of '$' tail */
6226 ascii_dom_name_len = strlen(str);
6227 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6228 str[ascii_dom_name_len - 1] = '\0';
6230 /* calculate padding space for d_printf to look nicer */
6231 pad_len = col_len - strlen(str);
6232 padding[pad_len] = 0;
6233 do padding[--pad_len] = ' '; while (pad_len);
6235 /* set opt_* variables to remote domain */
6236 strupper_m(str);
6237 c->opt_workgroup = talloc_strdup(mem_ctx, str);
6238 c->opt_target_workgroup = c->opt_workgroup;
6240 d_printf("%s%s", str, padding);
6242 /* connect to remote domain controller */
6243 nt_status = net_make_ipc_connection(c,
6244 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6245 &remote_cli);
6246 if (NT_STATUS_IS_OK(nt_status)) {
6247 /* query for domain's sid */
6248 if (run_rpc_command(
6249 c, remote_cli,
6250 &ndr_table_lsarpc.syntax_id, 0,
6251 rpc_query_domain_sid, argc,
6252 argv))
6253 d_fprintf(stderr,
6254 _("couldn't get domain's sid\n"));
6256 cli_shutdown(remote_cli);
6258 } else {
6259 d_fprintf(stderr, _("domain controller is not "
6260 "responding: %s\n"),
6261 nt_errstr(nt_status));
6265 if (!num_domains) d_printf("none\n");
6267 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6269 /* close opened samr and domain policy handles */
6270 nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6271 if (!NT_STATUS_IS_OK(nt_status)) {
6272 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6275 nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6276 if (!NT_STATUS_IS_OK(nt_status)) {
6277 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6280 /* close samr pipe and connection to IPC$ */
6281 cli_shutdown(cli);
6283 talloc_destroy(mem_ctx);
6284 return 0;
6288 * Entrypoint for 'net rpc trustdom' code.
6290 * @param argc Standard argc.
6291 * @param argv Standard argv without initial components.
6293 * @return Integer status (0 means success).
6296 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
6298 struct functable func[] = {
6300 "add",
6301 rpc_trustdom_add,
6302 NET_TRANSPORT_RPC,
6303 N_("Add trusting domain's account"),
6304 N_("net rpc trustdom add\n"
6305 " Add trusting domain's account")
6308 "del",
6309 rpc_trustdom_del,
6310 NET_TRANSPORT_RPC,
6311 N_("Remove trusting domain's account"),
6312 N_("net rpc trustdom del\n"
6313 " Remove trusting domain's account")
6316 "establish",
6317 rpc_trustdom_establish,
6318 NET_TRANSPORT_RPC,
6319 N_("Establish outgoing trust relationship"),
6320 N_("net rpc trustdom establish\n"
6321 " Establish outgoing trust relationship")
6324 "revoke",
6325 rpc_trustdom_revoke,
6326 NET_TRANSPORT_RPC,
6327 N_("Revoke outgoing trust relationship"),
6328 N_("net rpc trustdom revoke\n"
6329 " Revoke outgoing trust relationship")
6332 "list",
6333 rpc_trustdom_list,
6334 NET_TRANSPORT_RPC,
6335 N_("List in- and outgoing domain trusts"),
6336 N_("net rpc trustdom list\n"
6337 " List in- and outgoing domain trusts")
6340 "vampire",
6341 rpc_trustdom_vampire,
6342 NET_TRANSPORT_RPC,
6343 N_("Vampire trusts from remote server"),
6344 N_("net rpc trustdom vampire\n"
6345 " Vampire trusts from remote server")
6347 {NULL, NULL, 0, NULL, NULL}
6350 return net_run_function(c, argc, argv, "net rpc trustdom", func);
6354 * Check if a server will take rpc commands
6355 * @param flags Type of server to connect to (PDC, DMB, localhost)
6356 * if the host is not explicitly specified
6357 * @return bool (true means rpc supported)
6359 bool net_rpc_check(struct net_context *c, unsigned flags)
6361 struct cli_state *cli;
6362 bool ret = false;
6363 struct sockaddr_storage server_ss;
6364 char *server_name = NULL;
6365 NTSTATUS status;
6367 /* flags (i.e. server type) may depend on command */
6368 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
6369 return false;
6371 if ((cli = cli_initialise()) == NULL) {
6372 return false;
6375 status = cli_connect(cli, server_name, &server_ss);
6376 if (!NT_STATUS_IS_OK(status))
6377 goto done;
6378 if (!attempt_netbios_session_request(&cli, global_myname(),
6379 server_name, &server_ss))
6380 goto done;
6381 status = cli_negprot(cli);
6382 if (!NT_STATUS_IS_OK(status))
6383 goto done;
6384 if (cli->protocol < PROTOCOL_NT1)
6385 goto done;
6387 ret = true;
6388 done:
6389 cli_shutdown(cli);
6390 return ret;
6393 /* dump sam database via samsync rpc calls */
6394 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
6395 if (c->display_usage) {
6396 d_printf(_("Usage:\n"
6397 "net rpc samdump\n"
6398 " Dump remote SAM database\n"));
6399 return 0;
6402 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6403 NET_FLAGS_ANONYMOUS,
6404 rpc_samdump_internals, argc, argv);
6407 /* syncronise sam database via samsync rpc calls */
6408 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
6410 struct functable func[] = {
6412 "ldif",
6413 rpc_vampire_ldif,
6414 NET_TRANSPORT_RPC,
6415 N_("Dump remote SAM database to ldif"),
6416 N_("net rpc vampire ldif\n"
6417 " Dump remote SAM database to LDIF file or "
6418 "stdout")
6421 "keytab",
6422 rpc_vampire_keytab,
6423 NET_TRANSPORT_RPC,
6424 N_("Dump remote SAM database to Kerberos Keytab"),
6425 N_("net rpc vampire keytab\n"
6426 " Dump remote SAM database to Kerberos keytab "
6427 "file")
6430 "passdb",
6431 rpc_vampire_passdb,
6432 NET_TRANSPORT_RPC,
6433 N_("Dump remote SAM database to passdb"),
6434 N_("net rpc vampire passdb\n"
6435 " Dump remote SAM database to passdb")
6438 {NULL, NULL, 0, NULL, NULL}
6441 if (argc == 0) {
6442 if (c->display_usage) {
6443 d_printf(_("Usage:\n"
6444 "net rpc vampire\n"
6445 " Vampire remote SAM database\n"));
6446 return 0;
6449 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6450 NET_FLAGS_ANONYMOUS,
6451 rpc_vampire_internals,
6452 argc, argv);
6455 return net_run_function(c, argc, argv, "net rpc vampire", func);
6459 * Migrate everything from a print server.
6461 * @param c A net_context structure.
6462 * @param argc Standard main() style argc.
6463 * @param argv Standard main() style argv. Initial components are already
6464 * stripped.
6466 * @return A shell status integer (0 for success).
6468 * The order is important !
6469 * To successfully add drivers the print queues have to exist !
6470 * Applying ACLs should be the last step, because you're easily locked out.
6473 static int rpc_printer_migrate_all(struct net_context *c, int argc,
6474 const char **argv)
6476 int ret;
6478 if (c->display_usage) {
6479 d_printf(_("Usage:\n"
6480 "net rpc printer migrate all\n"
6481 " Migrate everything from a print server\n"));
6482 return 0;
6485 if (!c->opt_host) {
6486 d_printf(_("no server to migrate\n"));
6487 return -1;
6490 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6491 rpc_printer_migrate_printers_internals, argc,
6492 argv);
6493 if (ret)
6494 return ret;
6496 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6497 rpc_printer_migrate_drivers_internals, argc,
6498 argv);
6499 if (ret)
6500 return ret;
6502 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6503 rpc_printer_migrate_forms_internals, argc, argv);
6504 if (ret)
6505 return ret;
6507 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6508 rpc_printer_migrate_settings_internals, argc,
6509 argv);
6510 if (ret)
6511 return ret;
6513 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6514 rpc_printer_migrate_security_internals, argc,
6515 argv);
6520 * Migrate print drivers from a print server.
6522 * @param c A net_context structure.
6523 * @param argc Standard main() style argc.
6524 * @param argv Standard main() style argv. Initial components are already
6525 * stripped.
6527 * @return A shell status integer (0 for success).
6529 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
6530 const char **argv)
6532 if (c->display_usage) {
6533 d_printf(_("Usage:\n"
6534 "net rpc printer migrate drivers\n"
6535 " Migrate print-drivers from a print-server\n"));
6536 return 0;
6539 if (!c->opt_host) {
6540 d_printf(_("no server to migrate\n"));
6541 return -1;
6544 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6545 rpc_printer_migrate_drivers_internals,
6546 argc, argv);
6550 * Migrate print-forms from a print-server.
6552 * @param c A net_context structure.
6553 * @param argc Standard main() style argc.
6554 * @param argv Standard main() style argv. Initial components are already
6555 * stripped.
6557 * @return A shell status integer (0 for success).
6559 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
6560 const char **argv)
6562 if (c->display_usage) {
6563 d_printf(_("Usage:\n"
6564 "net rpc printer migrate forms\n"
6565 " Migrate print-forms from a print-server\n"));
6566 return 0;
6569 if (!c->opt_host) {
6570 d_printf(_("no server to migrate\n"));
6571 return -1;
6574 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6575 rpc_printer_migrate_forms_internals,
6576 argc, argv);
6580 * Migrate printers from a print-server.
6582 * @param c A net_context structure.
6583 * @param argc Standard main() style argc.
6584 * @param argv Standard main() style argv. Initial components are already
6585 * stripped.
6587 * @return A shell status integer (0 for success).
6589 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
6590 const char **argv)
6592 if (c->display_usage) {
6593 d_printf(_("Usage:\n"
6594 "net rpc printer migrate printers\n"
6595 " Migrate printers from a print-server\n"));
6596 return 0;
6599 if (!c->opt_host) {
6600 d_printf(_("no server to migrate\n"));
6601 return -1;
6604 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6605 rpc_printer_migrate_printers_internals,
6606 argc, argv);
6610 * Migrate printer-ACLs from a print-server
6612 * @param c A net_context structure.
6613 * @param argc Standard main() style argc.
6614 * @param argv Standard main() style argv. Initial components are already
6615 * stripped.
6617 * @return A shell status integer (0 for success).
6619 static int rpc_printer_migrate_security(struct net_context *c, int argc,
6620 const char **argv)
6622 if (c->display_usage) {
6623 d_printf(_("Usage:\n"
6624 "net rpc printer migrate security\n"
6625 " Migrate printer-ACLs from a print-server\n"));
6626 return 0;
6629 if (!c->opt_host) {
6630 d_printf(_("no server to migrate\n"));
6631 return -1;
6634 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6635 rpc_printer_migrate_security_internals,
6636 argc, argv);
6640 * Migrate printer-settings from a print-server.
6642 * @param c A net_context structure.
6643 * @param argc Standard main() style argc.
6644 * @param argv Standard main() style argv. Initial components are already
6645 * stripped.
6647 * @return A shell status integer (0 for success).
6649 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
6650 const char **argv)
6652 if (c->display_usage) {
6653 d_printf(_("Usage:\n"
6654 "net rpc printer migrate settings\n"
6655 " Migrate printer-settings from a "
6656 "print-server\n"));
6657 return 0;
6660 if (!c->opt_host) {
6661 d_printf(_("no server to migrate\n"));
6662 return -1;
6665 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6666 rpc_printer_migrate_settings_internals,
6667 argc, argv);
6671 * 'net rpc printer' entrypoint.
6673 * @param c A net_context structure.
6674 * @param argc Standard main() style argc.
6675 * @param argv Standard main() style argv. Initial components are already
6676 * stripped.
6679 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
6682 /* ouch: when addriver and setdriver are called from within
6683 rpc_printer_migrate_drivers_internals, the printer-queue already
6684 *has* to exist */
6686 struct functable func[] = {
6688 "all",
6689 rpc_printer_migrate_all,
6690 NET_TRANSPORT_RPC,
6691 N_("Migrate all from remote to local print server"),
6692 N_("net rpc printer migrate all\n"
6693 " Migrate all from remote to local print server")
6696 "drivers",
6697 rpc_printer_migrate_drivers,
6698 NET_TRANSPORT_RPC,
6699 N_("Migrate drivers to local server"),
6700 N_("net rpc printer migrate drivers\n"
6701 " Migrate drivers to local server")
6704 "forms",
6705 rpc_printer_migrate_forms,
6706 NET_TRANSPORT_RPC,
6707 N_("Migrate froms to local server"),
6708 N_("net rpc printer migrate forms\n"
6709 " Migrate froms to local server")
6712 "printers",
6713 rpc_printer_migrate_printers,
6714 NET_TRANSPORT_RPC,
6715 N_("Migrate printers to local server"),
6716 N_("net rpc printer migrate printers\n"
6717 " Migrate printers to local server")
6720 "security",
6721 rpc_printer_migrate_security,
6722 NET_TRANSPORT_RPC,
6723 N_("Mirgate printer ACLs to local server"),
6724 N_("net rpc printer migrate security\n"
6725 " Mirgate printer ACLs to local server")
6728 "settings",
6729 rpc_printer_migrate_settings,
6730 NET_TRANSPORT_RPC,
6731 N_("Migrate printer settings to local server"),
6732 N_("net rpc printer migrate settings\n"
6733 " Migrate printer settings to local server")
6735 {NULL, NULL, 0, NULL, NULL}
6738 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
6743 * List printers on a remote RPC server.
6745 * @param c A net_context structure.
6746 * @param argc Standard main() style argc.
6747 * @param argv Standard main() style argv. Initial components are already
6748 * stripped.
6750 * @return A shell status integer (0 for success).
6752 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
6754 if (c->display_usage) {
6755 d_printf(_("Usage:\n"
6756 "net rpc printer list\n"
6757 " List printers on a remote RPC server\n"));
6758 return 0;
6761 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6762 rpc_printer_list_internals,
6763 argc, argv);
6767 * List printer-drivers on a remote RPC server.
6769 * @param c A net_context structure.
6770 * @param argc Standard main() style argc.
6771 * @param argv Standard main() style argv. Initial components are already
6772 * stripped.
6774 * @return A shell status integer (0 for success).
6776 static int rpc_printer_driver_list(struct net_context *c, int argc,
6777 const char **argv)
6779 if (c->display_usage) {
6780 d_printf(_("Usage:\n"
6781 "net rpc printer driver\n"
6782 " List printer-drivers on a remote RPC server\n"));
6783 return 0;
6786 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6787 rpc_printer_driver_list_internals,
6788 argc, argv);
6792 * Publish printer in ADS via MSRPC.
6794 * @param c A net_context structure.
6795 * @param argc Standard main() style argc.
6796 * @param argv Standard main() style argv. Initial components are already
6797 * stripped.
6799 * @return A shell status integer (0 for success).
6801 static int rpc_printer_publish_publish(struct net_context *c, int argc,
6802 const char **argv)
6804 if (c->display_usage) {
6805 d_printf(_("Usage:\n"
6806 "net rpc printer publish publish\n"
6807 " Publish printer in ADS via MSRPC\n"));
6808 return 0;
6811 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6812 rpc_printer_publish_publish_internals,
6813 argc, argv);
6817 * Update printer in ADS via MSRPC.
6819 * @param c A net_context structure.
6820 * @param argc Standard main() style argc.
6821 * @param argv Standard main() style argv. Initial components are already
6822 * stripped.
6824 * @return A shell status integer (0 for success).
6826 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
6828 if (c->display_usage) {
6829 d_printf(_("Usage:\n"
6830 "net rpc printer publish update\n"
6831 " Update printer in ADS via MSRPC\n"));
6832 return 0;
6835 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6836 rpc_printer_publish_update_internals,
6837 argc, argv);
6841 * UnPublish printer in ADS via MSRPC.
6843 * @param c A net_context structure.
6844 * @param argc Standard main() style argc.
6845 * @param argv Standard main() style argv. Initial components are already
6846 * stripped.
6848 * @return A shell status integer (0 for success).
6850 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
6851 const char **argv)
6853 if (c->display_usage) {
6854 d_printf(_("Usage:\n"
6855 "net rpc printer publish unpublish\n"
6856 " UnPublish printer in ADS via MSRPC\n"));
6857 return 0;
6860 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6861 rpc_printer_publish_unpublish_internals,
6862 argc, argv);
6866 * List published printers via MSRPC.
6868 * @param c A net_context structure.
6869 * @param argc Standard main() style argc.
6870 * @param argv Standard main() style argv. Initial components are already
6871 * stripped.
6873 * @return A shell status integer (0 for success).
6875 static int rpc_printer_publish_list(struct net_context *c, int argc,
6876 const char **argv)
6878 if (c->display_usage) {
6879 d_printf(_("Usage:\n"
6880 "net rpc printer publish list\n"
6881 " List published printers via MSRPC\n"));
6882 return 0;
6885 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6886 rpc_printer_publish_list_internals,
6887 argc, argv);
6892 * Publish printer in ADS.
6894 * @param c A net_context structure.
6895 * @param argc Standard main() style argc.
6896 * @param argv Standard main() style argv. Initial components are already
6897 * stripped.
6899 * @return A shell status integer (0 for success).
6901 static int rpc_printer_publish(struct net_context *c, int argc,
6902 const char **argv)
6905 struct functable func[] = {
6907 "publish",
6908 rpc_printer_publish_publish,
6909 NET_TRANSPORT_RPC,
6910 N_("Publish printer in AD"),
6911 N_("net rpc printer publish publish\n"
6912 " Publish printer in AD")
6915 "update",
6916 rpc_printer_publish_update,
6917 NET_TRANSPORT_RPC,
6918 N_("Update printer in AD"),
6919 N_("net rpc printer publish update\n"
6920 " Update printer in AD")
6923 "unpublish",
6924 rpc_printer_publish_unpublish,
6925 NET_TRANSPORT_RPC,
6926 N_("Unpublish printer"),
6927 N_("net rpc printer publish unpublish\n"
6928 " Unpublish printer")
6931 "list",
6932 rpc_printer_publish_list,
6933 NET_TRANSPORT_RPC,
6934 N_("List published printers"),
6935 N_("net rpc printer publish list\n"
6936 " List published printers")
6938 {NULL, NULL, 0, NULL, NULL}
6941 if (argc == 0) {
6942 if (c->display_usage) {
6943 d_printf(_("Usage:\n"));
6944 d_printf(_("net rpc printer publish\n"
6945 " List published printers\n"
6946 " Alias of net rpc printer publish "
6947 "list\n"));
6948 net_display_usage_from_functable(func);
6949 return 0;
6951 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6952 rpc_printer_publish_list_internals,
6953 argc, argv);
6956 return net_run_function(c, argc, argv, "net rpc printer publish",func);
6962 * Display rpc printer help page.
6964 * @param c A net_context structure.
6965 * @param argc Standard main() style argc.
6966 * @param argv Standard main() style argv. Initial components are already
6967 * stripped.
6969 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
6971 d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
6972 "\tlists all printers on print-server\n\n"));
6973 d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
6974 "\tlists all printer-drivers on print-server\n\n"));
6975 d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
6976 "\tpublishes printer settings in Active Directory\n"
6977 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
6978 d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
6979 "\n\tmigrates printers from remote to local server\n\n"));
6980 d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
6981 "\n\tmigrates printer-settings from remote to local server\n\n"));
6982 d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
6983 "\n\tmigrates printer-drivers from remote to local server\n\n"));
6984 d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
6985 "\n\tmigrates printer-forms from remote to local server\n\n"));
6986 d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
6987 "\n\tmigrates printer-ACLs from remote to local server\n\n"));
6988 d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
6989 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
6990 "\tremote to local print-server\n\n"));
6991 net_common_methods_usage(c, argc, argv);
6992 net_common_flags_usage(c, argc, argv);
6993 d_printf(_(
6994 "\t-v or --verbose\t\t\tgive verbose output\n"
6995 "\t --destination\t\tmigration target server (default: localhost)\n"));
6997 return -1;
7001 * 'net rpc printer' entrypoint.
7003 * @param c A net_context structure.
7004 * @param argc Standard main() style argc.
7005 * @param argv Standard main() style argv. Initial components are already
7006 * stripped.
7008 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7010 struct functable func[] = {
7012 "list",
7013 rpc_printer_list,
7014 NET_TRANSPORT_RPC,
7015 N_("List all printers on print server"),
7016 N_("net rpc printer list\n"
7017 " List all printers on print server")
7020 "migrate",
7021 rpc_printer_migrate,
7022 NET_TRANSPORT_RPC,
7023 N_("Migrate printer to local server"),
7024 N_("net rpc printer migrate\n"
7025 " Migrate printer to local server")
7028 "driver",
7029 rpc_printer_driver_list,
7030 NET_TRANSPORT_RPC,
7031 N_("List printer drivers"),
7032 N_("net rpc printer driver\n"
7033 " List printer drivers")
7036 "publish",
7037 rpc_printer_publish,
7038 NET_TRANSPORT_RPC,
7039 N_("Publish printer in AD"),
7040 N_("net rpc printer publish\n"
7041 " Publish printer in AD")
7043 {NULL, NULL, 0, NULL, NULL}
7046 if (argc == 0) {
7047 if (c->display_usage) {
7048 d_printf(_("Usage:\n"));
7049 d_printf(_("net rpc printer\n"
7050 " List printers\n"));
7051 net_display_usage_from_functable(func);
7052 return 0;
7054 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7055 rpc_printer_list_internals,
7056 argc, argv);
7059 return net_run_function(c, argc, argv, "net rpc printer", func);
7063 * 'net rpc' entrypoint.
7065 * @param c A net_context structure.
7066 * @param argc Standard main() style argc.
7067 * @param argv Standard main() style argv. Initial components are already
7068 * stripped.
7071 int net_rpc(struct net_context *c, int argc, const char **argv)
7073 NET_API_STATUS status;
7075 struct functable func[] = {
7077 "audit",
7078 net_rpc_audit,
7079 NET_TRANSPORT_RPC,
7080 N_("Modify global audit settings"),
7081 N_("net rpc audit\n"
7082 " Modify global audit settings")
7085 "info",
7086 net_rpc_info,
7087 NET_TRANSPORT_RPC,
7088 N_("Show basic info about a domain"),
7089 N_("net rpc info\n"
7090 " Show basic info about a domain")
7093 "join",
7094 net_rpc_join,
7095 NET_TRANSPORT_RPC,
7096 N_("Join a domain"),
7097 N_("net rpc join\n"
7098 " Join a domain")
7101 "oldjoin",
7102 net_rpc_oldjoin,
7103 NET_TRANSPORT_RPC,
7104 N_("Join a domain created in server manager"),
7105 N_("net rpc oldjoin\n"
7106 " Join a domain created in server manager")
7109 "testjoin",
7110 net_rpc_testjoin,
7111 NET_TRANSPORT_RPC,
7112 N_("Test that a join is valid"),
7113 N_("net rpc testjoin\n"
7114 " Test that a join is valid")
7117 "user",
7118 net_rpc_user,
7119 NET_TRANSPORT_RPC,
7120 N_("List/modify users"),
7121 N_("net rpc user\n"
7122 " List/modify users")
7125 "password",
7126 rpc_user_password,
7127 NET_TRANSPORT_RPC,
7128 N_("Change a user password"),
7129 N_("net rpc password\n"
7130 " Change a user password\n"
7131 " Alias for net rpc user password")
7134 "group",
7135 net_rpc_group,
7136 NET_TRANSPORT_RPC,
7137 N_("List/modify groups"),
7138 N_("net rpc group\n"
7139 " List/modify groups")
7142 "share",
7143 net_rpc_share,
7144 NET_TRANSPORT_RPC,
7145 N_("List/modify shares"),
7146 N_("net rpc share\n"
7147 " List/modify shares")
7150 "file",
7151 net_rpc_file,
7152 NET_TRANSPORT_RPC,
7153 N_("List open files"),
7154 N_("net rpc file\n"
7155 " List open files")
7158 "printer",
7159 net_rpc_printer,
7160 NET_TRANSPORT_RPC,
7161 N_("List/modify printers"),
7162 N_("net rpc printer\n"
7163 " List/modify printers")
7166 "changetrustpw",
7167 net_rpc_changetrustpw,
7168 NET_TRANSPORT_RPC,
7169 N_("Change trust account password"),
7170 N_("net rpc changetrustpw\n"
7171 " Change trust account password")
7174 "trustdom",
7175 rpc_trustdom,
7176 NET_TRANSPORT_RPC,
7177 N_("Modify domain trusts"),
7178 N_("net rpc trustdom\n"
7179 " Modify domain trusts")
7182 "abortshutdown",
7183 rpc_shutdown_abort,
7184 NET_TRANSPORT_RPC,
7185 N_("Abort a remote shutdown"),
7186 N_("net rpc abortshutdown\n"
7187 " Abort a remote shutdown")
7190 "shutdown",
7191 rpc_shutdown,
7192 NET_TRANSPORT_RPC,
7193 N_("Shutdown a remote server"),
7194 N_("net rpc shutdown\n"
7195 " Shutdown a remote server")
7198 "samdump",
7199 rpc_samdump,
7200 NET_TRANSPORT_RPC,
7201 N_("Dump SAM data of remote NT PDC"),
7202 N_("net rpc samdump\n"
7203 " Dump SAM data of remote NT PDC")
7206 "vampire",
7207 rpc_vampire,
7208 NET_TRANSPORT_RPC,
7209 N_("Sync a remote NT PDC's data into local passdb"),
7210 N_("net rpc vampire\n"
7211 " Sync a remote NT PDC's data into local passdb")
7214 "getsid",
7215 net_rpc_getsid,
7216 NET_TRANSPORT_RPC,
7217 N_("Fetch the domain sid into local secrets.tdb"),
7218 N_("net rpc getsid\n"
7219 " Fetch the domain sid into local secrets.tdb")
7222 "rights",
7223 net_rpc_rights,
7224 NET_TRANSPORT_RPC,
7225 N_("Manage privileges assigned to SID"),
7226 N_("net rpc rights\n"
7227 " Manage privileges assigned to SID")
7230 "service",
7231 net_rpc_service,
7232 NET_TRANSPORT_RPC,
7233 N_("Start/stop/query remote services"),
7234 N_("net rpc service\n"
7235 " Start/stop/query remote services")
7238 "registry",
7239 net_rpc_registry,
7240 NET_TRANSPORT_RPC,
7241 N_("Manage registry hives"),
7242 N_("net rpc registry\n"
7243 " Manage registry hives")
7246 "shell",
7247 net_rpc_shell,
7248 NET_TRANSPORT_RPC,
7249 N_("Open interactive shell on remote server"),
7250 N_("net rpc shell\n"
7251 " Open interactive shell on remote server")
7253 {NULL, NULL, 0, NULL, NULL}
7256 status = libnetapi_init(&c->netapi_ctx);
7257 if (status != 0) {
7258 return -1;
7260 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
7261 libnetapi_set_password(c->netapi_ctx, c->opt_password);
7262 if (c->opt_kerberos) {
7263 libnetapi_set_use_kerberos(c->netapi_ctx);
7266 return net_run_function(c, argc, argv, "net rpc", func);