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/>. */
24 #include "utils/net.h"
25 #include "../libcli/auth/libcli_auth.h"
26 #include "../librpc/gen_ndr/ndr_samr_c.h"
27 #include "rpc_client/cli_samr.h"
28 #include "rpc_client/init_samr.h"
29 #include "../librpc/gen_ndr/cli_lsa.h"
30 #include "rpc_client/cli_lsarpc.h"
31 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
33 #include "../librpc/gen_ndr/ndr_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_initshutdown_c.h"
35 #include "../librpc/gen_ndr/ndr_winreg_c.h"
37 #include "lib/netapi/netapi.h"
38 #include "lib/netapi/netapi_net.h"
39 #include "rpc_client/init_lsa.h"
40 #include "../libcli/security/security.h"
42 static int net_mode_share;
43 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
48 * @brief RPC based subcommands for the 'net' utility.
50 * This file should contain much of the functionality that used to
51 * be found in rpcclient, execpt that the commands should change
52 * less often, and the fucntionality should be sane (the user is not
53 * expected to know a rid/sid before they conduct an operation etc.)
55 * @todo Perhaps eventually these should be split out into a number
56 * of files, as this could get quite big.
61 * Many of the RPC functions need the domain sid. This function gets
62 * it at the start of every run
64 * @param cli A cli_state already connected to the remote machine
66 * @return The Domain SID of the remote machine.
69 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
70 struct dom_sid **domain_sid,
71 const char **domain_name)
73 struct rpc_pipe_client *lsa_pipe = NULL;
74 struct policy_handle pol;
75 NTSTATUS result = NT_STATUS_OK;
76 union lsa_PolicyInformation *info = NULL;
78 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
80 if (!NT_STATUS_IS_OK(result)) {
81 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
85 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
86 SEC_FLAG_MAXIMUM_ALLOWED,
88 if (!NT_STATUS_IS_OK(result)) {
89 d_fprintf(stderr, "open_policy %s: %s\n",
95 result = rpccli_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx,
97 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
99 if (!NT_STATUS_IS_OK(result)) {
100 d_fprintf(stderr, "lsaquery %s: %s\n",
106 *domain_name = info->account_domain.name.string;
107 *domain_sid = info->account_domain.sid;
109 rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
110 TALLOC_FREE(lsa_pipe);
116 * Run a single RPC command, from start to finish.
118 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
119 * @param conn_flag a NET_FLAG_ combination. Passed to
120 * net_make_ipc_connection.
121 * @param argc Standard main() style argc.
122 * @param argv Standard main() style argv. Initial components are already
124 * @return A shell status integer (0 for success).
127 int run_rpc_command(struct net_context *c,
128 struct cli_state *cli_arg,
129 const struct ndr_syntax_id *interface,
135 struct cli_state *cli = NULL;
136 struct rpc_pipe_client *pipe_hnd = NULL;
139 struct dom_sid *domain_sid;
140 const char *domain_name;
143 /* make use of cli_state handed over as an argument, if possible */
145 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
146 if (!NT_STATUS_IS_OK(nt_status)) {
147 DEBUG(1, ("failed to make ipc connection: %s\n",
148 nt_errstr(nt_status)));
161 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
162 DEBUG(0, ("talloc_init() failed\n"));
166 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
168 if (!NT_STATUS_IS_OK(nt_status)) {
172 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
173 if (lp_client_schannel()
174 && (ndr_syntax_id_equal(interface,
175 &ndr_table_netlogon.syntax_id))) {
176 /* Always try and create an schannel netlogon pipe. */
177 nt_status = cli_rpc_pipe_open_schannel(
178 cli, interface, NCACN_NP,
179 DCERPC_AUTH_LEVEL_PRIVACY, domain_name,
181 if (!NT_STATUS_IS_OK(nt_status)) {
182 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
183 nt_errstr(nt_status) ));
187 if (conn_flags & NET_FLAGS_SEAL) {
188 nt_status = cli_rpc_pipe_open_ntlmssp(
190 (conn_flags & NET_FLAGS_TCP) ?
191 NCACN_IP_TCP : NCACN_NP,
192 DCERPC_AUTH_LEVEL_PRIVACY,
193 lp_workgroup(), c->opt_user_name,
194 c->opt_password, &pipe_hnd);
196 nt_status = cli_rpc_pipe_open_noauth(
200 if (!NT_STATUS_IS_OK(nt_status)) {
201 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
202 get_pipe_name_from_syntax(
203 talloc_tos(), interface),
204 nt_errstr(nt_status) ));
210 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
212 if (!NT_STATUS_IS_OK(nt_status)) {
213 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
216 DEBUG(5, ("rpc command function succedded\n"));
219 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
221 TALLOC_FREE(pipe_hnd);
226 /* close the connection only if it was opened here */
231 talloc_destroy(mem_ctx);
236 * Force a change of the trust acccount password.
238 * All parameters are provided by the run_rpc_command function, except for
239 * argc, argv which are passed through.
241 * @param domain_sid The domain sid acquired from the remote server.
242 * @param cli A cli_state connected to the server.
243 * @param mem_ctx Talloc context, destroyed on completion of the function.
244 * @param argc Standard main() style argc.
245 * @param argv Standard main() style argv. Initial components are already
248 * @return Normal NTSTATUS return.
251 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
252 const struct dom_sid *domain_sid,
253 const char *domain_name,
254 struct cli_state *cli,
255 struct rpc_pipe_client *pipe_hnd,
262 status = trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
263 if (!NT_STATUS_IS_OK(status)) {
264 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
273 * Force a change of the trust acccount password.
275 * @param argc Standard main() style argc.
276 * @param argv Standard main() style argv. Initial components are already
279 * @return A shell status integer (0 for success).
282 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
284 if (c->display_usage) {
286 "net rpc changetrustpw\n"
289 _("Change the machine trust password"));
293 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
294 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
295 rpc_changetrustpw_internals,
300 * Join a domain, the old way.
302 * This uses 'machinename' as the inital password, and changes it.
304 * The password should be created with 'server manager' or equiv first.
306 * All parameters are provided by the run_rpc_command function, except for
307 * argc, argv which are passed through.
309 * @param domain_sid The domain sid acquired from the remote server.
310 * @param cli A cli_state connected to the server.
311 * @param mem_ctx Talloc context, destroyed on completion of the function.
312 * @param argc Standard main() style argc.
313 * @param argv Standard main() style argv. Initial components are already
316 * @return Normal NTSTATUS return.
319 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
320 const struct dom_sid *domain_sid,
321 const char *domain_name,
322 struct cli_state *cli,
323 struct rpc_pipe_client *pipe_hnd,
329 fstring trust_passwd;
330 unsigned char orig_trust_passwd_hash[16];
332 enum netr_SchannelType sec_channel_type;
334 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
336 if (!NT_STATUS_IS_OK(result)) {
337 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
340 nt_errstr(result) ));
345 check what type of join - if the user want's to join as
346 a BDC, the server must agree that we are a BDC.
349 sec_channel_type = get_sec_channel_type(argv[0]);
351 sec_channel_type = get_sec_channel_type(NULL);
354 fstrcpy(trust_passwd, global_myname());
355 strlower_m(trust_passwd);
358 * Machine names can be 15 characters, but the max length on
359 * a password is 14. --jerry
362 trust_passwd[14] = '\0';
364 E_md4hash(trust_passwd, orig_trust_passwd_hash);
366 result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
368 orig_trust_passwd_hash,
371 if (NT_STATUS_IS_OK(result))
372 printf(_("Joined domain %s.\n"), c->opt_target_workgroup);
375 if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
376 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
377 result = NT_STATUS_UNSUCCESSFUL;
384 * Join a domain, the old way.
386 * @param argc Standard main() style argc.
387 * @param argv Standard main() style argv. Initial components are already
390 * @return A shell status integer (0 for success).
393 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
395 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
396 NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
397 rpc_oldjoin_internals,
402 * Join a domain, the old way. This function exists to allow
403 * the message to be displayed when oldjoin was explicitly
404 * requested, but not when it was implied by "net rpc join".
406 * @param argc Standard main() style argc.
407 * @param argv Standard main() style argv. Initial components are already
410 * @return A shell status integer (0 for success).
413 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
417 if (c->display_usage) {
422 _("Join a domain the old way"));
426 rc = net_rpc_perform_oldjoin(c, argc, argv);
429 d_fprintf(stderr, _("Failed to join domain\n"));
436 * 'net rpc join' entrypoint.
437 * @param argc Standard main() style argc.
438 * @param argv Standard main() style argv. Initial components are already
441 * Main 'net_rpc_join()' (where the admin username/password is used) is
443 * Try to just change the password, but if that doesn't work, use/prompt
444 * for a username/password.
447 int net_rpc_join(struct net_context *c, int argc, const char **argv)
449 if (c->display_usage) {
452 _("net rpc join -U <username>[%%password] <type>\n"
454 " username\tName of the admin user"
455 " password\tPassword of the admin user, will "
456 "prompt if not specified\n"
457 " type\tCan be one of the following:\n"
458 "\t\tMEMBER\tJoin as member server (default)\n"
459 "\t\tBDC\tJoin as BDC\n"
460 "\t\tPDC\tJoin as PDC\n"));
464 if (lp_server_role() == ROLE_STANDALONE) {
465 d_printf(_("cannot join as standalone machine\n"));
469 if (strlen(global_myname()) > 15) {
470 d_printf(_("Our netbios name can be at most 15 chars long, "
471 "\"%s\" is %u chars long\n"),
472 global_myname(), (unsigned int)strlen(global_myname()));
476 if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
479 return net_rpc_join_newstyle(c, argc, argv);
483 * display info about a rpc domain
485 * All parameters are provided by the run_rpc_command function, except for
486 * argc, argv which are passed through.
488 * @param domain_sid The domain sid acquired from the remote server
489 * @param cli A cli_state connected to the server.
490 * @param mem_ctx Talloc context, destroyed on completion of the function.
491 * @param argc Standard main() style argc.
492 * @param argv Standard main() style argv. Initial components are already
495 * @return Normal NTSTATUS return.
498 NTSTATUS rpc_info_internals(struct net_context *c,
499 const struct dom_sid *domain_sid,
500 const char *domain_name,
501 struct cli_state *cli,
502 struct rpc_pipe_client *pipe_hnd,
507 struct policy_handle connect_pol, domain_pol;
508 NTSTATUS status, result;
509 union samr_DomainInfo *info = NULL;
511 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
513 sid_to_fstring(sid_str, domain_sid);
515 /* Get sam policy handle */
516 status = dcerpc_samr_Connect2(b, mem_ctx,
518 MAXIMUM_ALLOWED_ACCESS,
521 if (!NT_STATUS_IS_OK(status)) {
522 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
527 if (!NT_STATUS_IS_OK(result)) {
529 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
534 /* Get domain policy handle */
535 status = dcerpc_samr_OpenDomain(b, mem_ctx,
537 MAXIMUM_ALLOWED_ACCESS,
538 CONST_DISCARD(struct dom_sid2 *, domain_sid),
541 if (!NT_STATUS_IS_OK(status)) {
542 d_fprintf(stderr, _("Could not open domain: %s\n"),
546 if (!NT_STATUS_IS_OK(result)) {
548 d_fprintf(stderr, _("Could not open domain: %s\n"),
553 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
558 if (!NT_STATUS_IS_OK(status)) {
562 if (NT_STATUS_IS_OK(result)) {
563 d_printf(_("Domain Name: %s\n"),
564 info->general.domain_name.string);
565 d_printf(_("Domain SID: %s\n"), sid_str);
566 d_printf(_("Sequence number: %llu\n"),
567 (unsigned long long)info->general.sequence_num);
568 d_printf(_("Num users: %u\n"), info->general.num_users);
569 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
570 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
578 * 'net rpc info' entrypoint.
579 * @param argc Standard main() style argc.
580 * @param argv Standard main() style argv. Initial components are already
584 int net_rpc_info(struct net_context *c, int argc, const char **argv)
586 if (c->display_usage) {
591 _("Display information about the domain"));
595 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
596 NET_FLAGS_PDC, rpc_info_internals,
601 * Fetch domain SID into the local secrets.tdb.
603 * All parameters are provided by the run_rpc_command function, except for
604 * argc, argv which are passed through.
606 * @param domain_sid The domain sid acquired from the remote server.
607 * @param cli A cli_state connected to the server.
608 * @param mem_ctx Talloc context, destroyed on completion of the function.
609 * @param argc Standard main() style argc.
610 * @param argv Standard main() style argv. Initial components are already
613 * @return Normal NTSTATUS return.
616 static NTSTATUS rpc_getsid_internals(struct net_context *c,
617 const struct dom_sid *domain_sid,
618 const char *domain_name,
619 struct cli_state *cli,
620 struct rpc_pipe_client *pipe_hnd,
627 sid_to_fstring(sid_str, domain_sid);
628 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
629 sid_str, domain_name);
631 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
632 DEBUG(0,("Can't store domain SID\n"));
633 return NT_STATUS_UNSUCCESSFUL;
640 * 'net rpc getsid' entrypoint.
641 * @param argc Standard main() style argc.
642 * @param argv Standard main() style argv. Initial components are already
646 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
648 int conn_flags = NET_FLAGS_PDC;
650 if (!c->opt_user_specified) {
651 conn_flags |= NET_FLAGS_ANONYMOUS;
654 if (c->display_usage) {
659 _("Fetch domain SID into local secrets.tdb"));
663 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
665 rpc_getsid_internals,
669 /****************************************************************************/
672 * Basic usage function for 'net rpc user'.
673 * @param argc Standard main() style argc.
674 * @param argv Standard main() style argv. Initial components are already
678 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
680 return net_user_usage(c, argc, argv);
684 * Add a new user to a remote RPC server.
686 * @param argc Standard main() style argc.
687 * @param argv Standard main() style argv. Initial components are already
690 * @return A shell status integer (0 for success).
693 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
695 NET_API_STATUS status;
696 struct USER_INFO_1 info1;
697 uint32_t parm_error = 0;
699 if (argc < 1 || c->display_usage) {
700 rpc_user_usage(c, argc, argv);
706 info1.usri1_name = argv[0];
708 info1.usri1_password = argv[1];
711 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
714 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
715 argv[0], libnetapi_get_error_string(c->netapi_ctx,
719 d_printf(_("Added user '%s'.\n"), argv[0]);
726 * Rename a user on a remote RPC server.
728 * @param argc Standard main() style argc.
729 * @param argv Standard main() style argv. Initial components are already
732 * @return A shell status integer (0 for success).
735 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
737 NET_API_STATUS status;
738 struct USER_INFO_0 u0;
739 uint32_t parm_err = 0;
741 if (argc != 2 || c->display_usage) {
742 rpc_user_usage(c, argc, argv);
746 u0.usri0_name = argv[1];
748 status = NetUserSetInfo(c->opt_host, argv[0],
749 0, (uint8_t *)&u0, &parm_err);
752 _("Failed to rename user from %s to %s - %s\n"),
754 libnetapi_get_error_string(c->netapi_ctx, status));
756 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
763 * Set a user's primary group
765 * @param argc Standard main() style argc.
766 * @param argv Standard main() style argv. Initial components are already
769 * @return A shell status integer (0 for success).
772 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
775 NET_API_STATUS status;
777 struct GROUP_INFO_2 *g2;
778 struct USER_INFO_1051 u1051;
779 uint32_t parm_err = 0;
781 if (argc != 2 || c->display_usage) {
782 rpc_user_usage(c, argc, argv);
786 status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
788 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
790 libnetapi_get_error_string(c->netapi_ctx, status));
793 g2 = (struct GROUP_INFO_2 *)buffer;
795 u1051.usri1051_primary_group_id = g2->grpi2_group_id;
797 NetApiBufferFree(buffer);
799 status = NetUserSetInfo(c->opt_host, argv[0], 1051,
800 (uint8_t *)&u1051, &parm_err);
803 _("Failed to set user's primary group %s to %s - "
804 "%s\n"), argv[0], argv[1],
805 libnetapi_get_error_string(c->netapi_ctx, status));
807 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
814 * Delete a user from a remote RPC server.
816 * @param argc Standard main() style argc.
817 * @param argv Standard main() style argv. Initial components are already
820 * @return A shell status integer (0 for success).
823 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
825 NET_API_STATUS status;
827 if (argc < 1 || c->display_usage) {
828 rpc_user_usage(c, argc, argv);
832 status = NetUserDel(c->opt_host, argv[0]);
835 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
837 libnetapi_get_error_string(c->netapi_ctx, status));
840 d_printf(_("Deleted user '%s'.\n"), argv[0]);
847 * Set a user's password on a remote RPC server.
849 * @param argc Standard main() style argc.
850 * @param argv Standard main() style argv. Initial components are already
853 * @return A shell status integer (0 for success).
856 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
858 NET_API_STATUS status;
860 struct USER_INFO_1003 u1003;
861 uint32_t parm_err = 0;
864 if (argc < 1 || c->display_usage) {
865 rpc_user_usage(c, argc, argv);
870 u1003.usri1003_password = argv[1];
872 ret = asprintf(&prompt, _("Enter new password for %s:"),
877 u1003.usri1003_password = talloc_strdup(c, getpass(prompt));
879 if (u1003.usri1003_password == NULL) {
884 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
886 /* Display results */
889 _("Failed to set password for '%s' with error: %s.\n"),
890 argv[0], libnetapi_get_error_string(c->netapi_ctx,
899 * List a user's groups from a remote RPC server.
901 * @param argc Standard main() style argc.
902 * @param argv Standard main() style argv. Initial components are already
905 * @return A shell status integer (0 for success)
908 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
911 NET_API_STATUS status;
912 struct GROUP_USERS_INFO_0 *u0 = NULL;
913 uint32_t entries_read = 0;
914 uint32_t total_entries = 0;
918 if (argc < 1 || c->display_usage) {
919 rpc_user_usage(c, argc, argv);
923 status = NetUserGetGroups(c->opt_host,
926 (uint8_t **)(void *)&u0,
932 _("Failed to get groups for '%s' with error: %s.\n"),
933 argv[0], libnetapi_get_error_string(c->netapi_ctx,
938 for (i=0; i < entries_read; i++) {
939 printf("%s\n", u0->grui0_name);
947 * List users on a remote RPC server.
949 * All parameters are provided by the run_rpc_command function, except for
950 * argc, argv which are passed through.
952 * @param domain_sid The domain sid acquired from the remote server.
953 * @param cli A cli_state connected to the server.
954 * @param mem_ctx Talloc context, destroyed on completion of the function.
955 * @param argc Standard main() style argc.
956 * @param argv Standard main() style argv. Initial components are already
959 * @return Normal NTSTATUS return.
962 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
964 NET_API_STATUS status;
965 uint32_t start_idx=0, num_entries, i, loop_count = 0;
966 struct NET_DISPLAY_USER *info = NULL;
969 /* Query domain users */
970 if (c->opt_long_list_entries)
971 d_printf(_("\nUser name Comment"
972 "\n-----------------------------\n"));
974 uint32_t max_entries, max_size;
976 dcerpc_get_query_dispinfo_params(
977 loop_count, &max_entries, &max_size);
979 status = NetQueryDisplayInformation(c->opt_host,
986 if (status != 0 && status != ERROR_MORE_DATA) {
990 info = (struct NET_DISPLAY_USER *)buffer;
992 for (i = 0; i < num_entries; i++) {
994 if (c->opt_long_list_entries)
995 printf("%-21.21s %s\n", info->usri1_name,
996 info->usri1_comment);
998 printf("%s\n", info->usri1_name);
1002 NetApiBufferFree(buffer);
1005 start_idx += num_entries;
1007 } while (status == ERROR_MORE_DATA);
1013 * 'net rpc user' entrypoint.
1014 * @param argc Standard main() style argc.
1015 * @param argv Standard main() style argv. Initial components are already
1019 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1021 NET_API_STATUS status;
1023 struct functable func[] = {
1028 N_("Add specified user"),
1029 N_("net rpc user add\n"
1030 " Add specified user")
1036 N_("List domain groups of user"),
1037 N_("net rpc user info\n"
1038 " List domain groups of user")
1044 N_("Remove specified user"),
1045 N_("net rpc user delete\n"
1046 " Remove specified user")
1052 N_("Change user password"),
1053 N_("net rpc user password\n"
1054 " Change user password")
1060 N_("Rename specified user"),
1061 N_("net rpc user rename\n"
1062 " Rename specified user")
1066 rpc_user_setprimarygroup,
1068 "Set a user's primary group",
1069 "net rpc user setprimarygroup\n"
1070 " Set a user's primary group"
1072 {NULL, NULL, 0, NULL, NULL}
1075 status = libnetapi_net_init(&c->netapi_ctx);
1079 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1080 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1081 if (c->opt_kerberos) {
1082 libnetapi_set_use_kerberos(c->netapi_ctx);
1086 if (c->display_usage) {
1091 _("List all users"));
1092 net_display_usage_from_functable(func);
1096 return rpc_user_list(c, argc, argv);
1099 return net_run_function(c, argc, argv, "net rpc user", func);
1102 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1103 TALLOC_CTX *mem_ctx,
1104 struct rpc_sh_ctx *ctx,
1105 struct rpc_pipe_client *pipe_hnd,
1106 int argc, const char **argv)
1108 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1111 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1112 TALLOC_CTX *mem_ctx,
1113 struct rpc_sh_ctx *ctx,
1114 struct rpc_pipe_client *pipe_hnd,
1115 int argc, const char **argv)
1117 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1120 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1121 TALLOC_CTX *mem_ctx,
1122 struct rpc_sh_ctx *ctx,
1123 struct rpc_pipe_client *pipe_hnd,
1124 int argc, const char **argv,
1126 struct net_context *c,
1127 TALLOC_CTX *mem_ctx,
1128 struct rpc_sh_ctx *ctx,
1129 struct rpc_pipe_client *pipe_hnd,
1130 struct policy_handle *user_hnd,
1131 int argc, const char **argv))
1133 struct policy_handle connect_pol, domain_pol, user_pol;
1134 NTSTATUS status, result;
1137 enum lsa_SidType type;
1138 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1141 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1143 return NT_STATUS_INVALID_PARAMETER;
1146 ZERO_STRUCT(connect_pol);
1147 ZERO_STRUCT(domain_pol);
1148 ZERO_STRUCT(user_pol);
1150 status = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1151 argv[0], NULL, NULL, &sid, &type);
1152 if (!NT_STATUS_IS_OK(status)) {
1153 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1158 if (type != SID_NAME_USER) {
1159 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1160 sid_type_lookup(type));
1161 status = NT_STATUS_NO_SUCH_USER;
1165 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1166 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1167 status = NT_STATUS_NO_SUCH_USER;
1171 status = dcerpc_samr_Connect2(b, mem_ctx,
1173 MAXIMUM_ALLOWED_ACCESS,
1176 if (!NT_STATUS_IS_OK(status)) {
1179 if (!NT_STATUS_IS_OK(result)) {
1184 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1186 MAXIMUM_ALLOWED_ACCESS,
1190 if (!NT_STATUS_IS_OK(status)) {
1193 if (!NT_STATUS_IS_OK(result)) {
1198 status = dcerpc_samr_OpenUser(b, mem_ctx,
1200 MAXIMUM_ALLOWED_ACCESS,
1204 if (!NT_STATUS_IS_OK(status)) {
1207 if (!NT_STATUS_IS_OK(result)) {
1212 status = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1215 if (is_valid_policy_hnd(&user_pol)) {
1216 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1218 if (is_valid_policy_hnd(&domain_pol)) {
1219 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1221 if (is_valid_policy_hnd(&connect_pol)) {
1222 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
1227 static NTSTATUS rpc_sh_user_show_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 status, result;
1235 union samr_UserInfo *info = NULL;
1236 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1239 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1241 return NT_STATUS_INVALID_PARAMETER;
1244 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1249 if (!NT_STATUS_IS_OK(status)) {
1252 if (!NT_STATUS_IS_OK(result)) {
1256 d_printf(_("user rid: %d, group rid: %d\n"),
1258 info->info21.primary_gid);
1263 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1264 TALLOC_CTX *mem_ctx,
1265 struct rpc_sh_ctx *ctx,
1266 struct rpc_pipe_client *pipe_hnd,
1267 int argc, const char **argv)
1269 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1270 rpc_sh_user_show_internals);
1273 #define FETCHSTR(name, rec) \
1274 do { if (strequal(ctx->thiscmd, name)) { \
1275 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1278 #define SETSTR(name, rec, flag) \
1279 do { if (strequal(ctx->thiscmd, name)) { \
1280 init_lsa_String(&(info->info21.rec), argv[0]); \
1281 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1284 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1285 TALLOC_CTX *mem_ctx,
1286 struct rpc_sh_ctx *ctx,
1287 struct rpc_pipe_client *pipe_hnd,
1288 struct policy_handle *user_hnd,
1289 int argc, const char **argv)
1291 NTSTATUS status, result;
1292 const char *username;
1293 const char *oldval = "";
1294 union samr_UserInfo *info = NULL;
1295 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1298 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1299 _("Usage:"), ctx->whoami);
1300 return NT_STATUS_INVALID_PARAMETER;
1303 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1308 if (!NT_STATUS_IS_OK(status)) {
1311 if (!NT_STATUS_IS_OK(result)) {
1315 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1317 FETCHSTR("fullname", full_name);
1318 FETCHSTR("homedir", home_directory);
1319 FETCHSTR("homedrive", home_drive);
1320 FETCHSTR("logonscript", logon_script);
1321 FETCHSTR("profilepath", profile_path);
1322 FETCHSTR("description", description);
1325 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1329 if (strcmp(argv[0], "NULL") == 0) {
1333 ZERO_STRUCT(info->info21);
1335 SETSTR("fullname", full_name, FULL_NAME);
1336 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1337 SETSTR("homedrive", home_drive, HOME_DRIVE);
1338 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1339 SETSTR("profilepath", profile_path, PROFILE_PATH);
1340 SETSTR("description", description, DESCRIPTION);
1342 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1347 if (!NT_STATUS_IS_OK(status)) {
1353 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1354 ctx->thiscmd, oldval, argv[0]);
1361 #define HANDLEFLG(name, rec) \
1362 do { if (strequal(ctx->thiscmd, name)) { \
1363 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1365 newflags = oldflags | ACB_##rec; \
1367 newflags = oldflags & ~ACB_##rec; \
1370 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1371 TALLOC_CTX *mem_ctx,
1372 struct rpc_sh_ctx *ctx,
1373 struct rpc_pipe_client *pipe_hnd,
1374 int argc, const char **argv)
1376 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1377 rpc_sh_user_str_edit_internals);
1380 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1381 TALLOC_CTX *mem_ctx,
1382 struct rpc_sh_ctx *ctx,
1383 struct rpc_pipe_client *pipe_hnd,
1384 struct policy_handle *user_hnd,
1385 int argc, const char **argv)
1387 NTSTATUS status, result;
1388 const char *username;
1389 const char *oldval = "unknown";
1390 uint32 oldflags, newflags;
1392 union samr_UserInfo *info = NULL;
1393 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1396 ((argc == 1) && !strequal(argv[0], "yes") &&
1397 !strequal(argv[0], "no"))) {
1398 /* TRANSATORS: The yes|no here are program keywords. Please do
1400 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1402 return NT_STATUS_INVALID_PARAMETER;
1405 newval = strequal(argv[0], "yes");
1407 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1412 if (!NT_STATUS_IS_OK(status)) {
1415 if (!NT_STATUS_IS_OK(result)) {
1419 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1420 oldflags = info->info21.acct_flags;
1421 newflags = info->info21.acct_flags;
1423 HANDLEFLG("disabled", DISABLED);
1424 HANDLEFLG("pwnotreq", PWNOTREQ);
1425 HANDLEFLG("autolock", AUTOLOCK);
1426 HANDLEFLG("pwnoexp", PWNOEXP);
1429 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1434 ZERO_STRUCT(info->info21);
1436 info->info21.acct_flags = newflags;
1437 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1439 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1444 if (!NT_STATUS_IS_OK(status)) {
1448 if (NT_STATUS_IS_OK(result)) {
1449 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1450 ctx->thiscmd, oldval, argv[0]);
1458 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1459 TALLOC_CTX *mem_ctx,
1460 struct rpc_sh_ctx *ctx,
1461 struct rpc_pipe_client *pipe_hnd,
1462 int argc, const char **argv)
1464 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1465 rpc_sh_user_flag_edit_internals);
1468 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1469 TALLOC_CTX *mem_ctx,
1470 struct rpc_sh_ctx *ctx)
1472 static struct rpc_sh_cmd cmds[] = {
1474 { "fullname", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1475 N_("Show/Set a user's full name") },
1477 { "homedir", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1478 N_("Show/Set a user's home directory") },
1480 { "homedrive", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1481 N_("Show/Set a user's home drive") },
1483 { "logonscript", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1484 N_("Show/Set a user's logon script") },
1486 { "profilepath", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1487 N_("Show/Set a user's profile path") },
1489 { "description", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1490 N_("Show/Set a user's description") },
1492 { "disabled", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1493 N_("Show/Set whether a user is disabled") },
1495 { "autolock", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1496 N_("Show/Set whether a user locked out") },
1498 { "pwnotreq", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1499 N_("Show/Set whether a user does not need a password") },
1501 { "pwnoexp", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1502 N_("Show/Set whether a user's password does not expire") },
1504 { NULL, NULL, 0, NULL, NULL }
1510 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1511 TALLOC_CTX *mem_ctx,
1512 struct rpc_sh_ctx *ctx)
1514 static struct rpc_sh_cmd cmds[] = {
1516 { "list", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_list,
1517 N_("List available users") },
1519 { "info", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_info,
1520 N_("List the domain groups a user is member of") },
1522 { "show", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_show,
1523 N_("Show info about a user") },
1525 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1526 N_("Show/Modify a user's fields") },
1528 { NULL, NULL, 0, NULL, NULL }
1534 /****************************************************************************/
1537 * Basic usage function for 'net rpc group'.
1538 * @param argc Standard main() style argc.
1539 * @param argv Standard main() style argv. Initial components are already
1543 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1545 return net_group_usage(c, argc, argv);
1549 * Delete group on a remote RPC server.
1551 * All parameters are provided by the run_rpc_command function, except for
1552 * argc, argv which are passed through.
1554 * @param domain_sid The domain sid acquired from the remote server.
1555 * @param cli A cli_state connected to the server.
1556 * @param mem_ctx Talloc context, destroyed on completion of the function.
1557 * @param argc Standard main() style argc.
1558 * @param argv Standard main() style argv. Initial components are already
1561 * @return Normal NTSTATUS return.
1564 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1565 const struct dom_sid *domain_sid,
1566 const char *domain_name,
1567 struct cli_state *cli,
1568 struct rpc_pipe_client *pipe_hnd,
1569 TALLOC_CTX *mem_ctx,
1573 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1574 bool group_is_primary = false;
1575 NTSTATUS status, result;
1577 struct samr_RidAttrArray *rids = NULL;
1580 /* struct samr_RidWithAttribute *user_gids; */
1581 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1583 struct samr_Ids group_rids, name_types;
1584 struct lsa_String lsa_acct_name;
1585 union samr_UserInfo *info = NULL;
1587 if (argc < 1 || c->display_usage) {
1588 rpc_group_usage(c, argc,argv);
1589 return NT_STATUS_OK; /* ok? */
1592 status = dcerpc_samr_Connect2(b, mem_ctx,
1594 MAXIMUM_ALLOWED_ACCESS,
1597 if (!NT_STATUS_IS_OK(status)) {
1598 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1602 if (!NT_STATUS_IS_OK(result)) {
1604 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1608 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1610 MAXIMUM_ALLOWED_ACCESS,
1611 CONST_DISCARD(struct dom_sid2 *, domain_sid),
1614 if (!NT_STATUS_IS_OK(status)) {
1615 d_fprintf(stderr, _("Request open_domain failed\n"));
1619 if (!NT_STATUS_IS_OK(result)) {
1621 d_fprintf(stderr, _("Request open_domain failed\n"));
1625 init_lsa_String(&lsa_acct_name, argv[0]);
1627 status = dcerpc_samr_LookupNames(b, mem_ctx,
1634 if (!NT_STATUS_IS_OK(status)) {
1635 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1639 if (!NT_STATUS_IS_OK(result)) {
1641 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1645 switch (name_types.ids[0])
1647 case SID_NAME_DOM_GRP:
1648 status = dcerpc_samr_OpenGroup(b, mem_ctx,
1650 MAXIMUM_ALLOWED_ACCESS,
1654 if (!NT_STATUS_IS_OK(status)) {
1655 d_fprintf(stderr, _("Request open_group failed"));
1659 if (!NT_STATUS_IS_OK(result)) {
1661 d_fprintf(stderr, _("Request open_group failed"));
1665 group_rid = group_rids.ids[0];
1667 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
1671 if (!NT_STATUS_IS_OK(status)) {
1673 _("Unable to query group members of %s"),
1678 if (!NT_STATUS_IS_OK(result)) {
1681 _("Unable to query group members of %s"),
1686 if (c->opt_verbose) {
1688 _("Domain Group %s (rid: %d) has %d members\n"),
1689 argv[0],group_rid, rids->count);
1692 /* Check if group is anyone's primary group */
1693 for (i = 0; i < rids->count; i++)
1695 status = dcerpc_samr_OpenUser(b, mem_ctx,
1697 MAXIMUM_ALLOWED_ACCESS,
1701 if (!NT_STATUS_IS_OK(status)) {
1703 _("Unable to open group member %d\n"),
1708 if (!NT_STATUS_IS_OK(result)) {
1711 _("Unable to open group member %d\n"),
1716 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1721 if (!NT_STATUS_IS_OK(status)) {
1723 _("Unable to lookup userinfo for group "
1729 if (!NT_STATUS_IS_OK(result)) {
1732 _("Unable to lookup userinfo for group "
1738 if (info->info21.primary_gid == group_rid) {
1739 if (c->opt_verbose) {
1740 d_printf(_("Group is primary group "
1742 info->info21.account_name.string);
1744 group_is_primary = true;
1747 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1750 if (group_is_primary) {
1751 d_fprintf(stderr, _("Unable to delete group because "
1752 "some of it's members have it as primary "
1754 status = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1758 /* remove all group members */
1759 for (i = 0; i < rids->count; i++)
1762 d_printf(_("Remove group member %d..."),
1764 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
1768 if (!NT_STATUS_IS_OK(status)) {
1772 if (NT_STATUS_IS_OK(result)) {
1774 d_printf(_("ok\n"));
1777 d_printf("%s\n", _("failed"));
1782 status = dcerpc_samr_DeleteDomainGroup(b, mem_ctx,
1785 if (!NT_STATUS_IS_OK(status)) {
1792 /* removing a local group is easier... */
1793 case SID_NAME_ALIAS:
1794 status = dcerpc_samr_OpenAlias(b, mem_ctx,
1796 MAXIMUM_ALLOWED_ACCESS,
1800 if (!NT_STATUS_IS_OK(status)) {
1801 d_fprintf(stderr, _("Request open_alias failed\n"));
1804 if (!NT_STATUS_IS_OK(result)) {
1806 d_fprintf(stderr, _("Request open_alias failed\n"));
1810 status = dcerpc_samr_DeleteDomAlias(b, mem_ctx,
1813 if (!NT_STATUS_IS_OK(status)) {
1821 d_fprintf(stderr, _("%s is of type %s. This command is only "
1822 "for deleting local or global groups\n"),
1823 argv[0],sid_type_lookup(name_types.ids[0]));
1824 status = NT_STATUS_UNSUCCESSFUL;
1828 if (NT_STATUS_IS_OK(status)) {
1830 d_printf(_("Deleted %s '%s'\n"),
1831 sid_type_lookup(name_types.ids[0]), argv[0]);
1833 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
1834 get_friendly_nt_error_msg(status));
1842 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1844 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1845 rpc_group_delete_internals, argc,argv);
1848 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1850 NET_API_STATUS status;
1851 struct GROUP_INFO_1 info1;
1852 uint32_t parm_error = 0;
1854 if (argc != 1 || c->display_usage) {
1855 rpc_group_usage(c, argc, argv);
1861 info1.grpi1_name = argv[0];
1862 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1863 info1.grpi1_comment = c->opt_comment;
1866 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1870 _("Failed to add group '%s' with error: %s.\n"),
1871 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1875 d_printf(_("Added group '%s'.\n"), argv[0]);
1881 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
1883 NET_API_STATUS status;
1884 struct LOCALGROUP_INFO_1 info1;
1885 uint32_t parm_error = 0;
1887 if (argc != 1 || c->display_usage) {
1888 rpc_group_usage(c, argc, argv);
1894 info1.lgrpi1_name = argv[0];
1895 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1896 info1.lgrpi1_comment = c->opt_comment;
1899 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1903 _("Failed to add alias '%s' with error: %s.\n"),
1904 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1908 d_printf(_("Added alias '%s'.\n"), argv[0]);
1914 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1916 if (c->opt_localgroup)
1917 return rpc_alias_add_internals(c, argc, argv);
1919 return rpc_group_add_internals(c, argc, argv);
1922 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1923 TALLOC_CTX *mem_ctx,
1925 struct dom_sid *sid,
1926 enum lsa_SidType *type)
1928 struct dom_sid *sids = NULL;
1929 enum lsa_SidType *types = NULL;
1930 struct rpc_pipe_client *pipe_hnd = NULL;
1931 struct policy_handle lsa_pol;
1932 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1934 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1936 if (!NT_STATUS_IS_OK(result)) {
1940 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1941 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1943 if (!NT_STATUS_IS_OK(result)) {
1947 result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1948 &name, NULL, 1, &sids, &types);
1950 if (NT_STATUS_IS_OK(result)) {
1951 sid_copy(sid, &sids[0]);
1955 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
1959 TALLOC_FREE(pipe_hnd);
1962 if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
1964 /* Try as S-1-5-whatever */
1966 struct dom_sid tmp_sid;
1968 if (string_to_sid(&tmp_sid, name)) {
1969 sid_copy(sid, &tmp_sid);
1970 *type = SID_NAME_UNKNOWN;
1971 result = NT_STATUS_OK;
1978 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
1979 TALLOC_CTX *mem_ctx,
1980 const struct dom_sid *group_sid,
1983 struct policy_handle connect_pol, domain_pol;
1984 NTSTATUS status, result;
1986 struct policy_handle group_pol;
1987 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1989 struct samr_Ids rids, rid_types;
1990 struct lsa_String lsa_acct_name;
1994 sid_copy(&sid, group_sid);
1996 if (!sid_split_rid(&sid, &group_rid)) {
1997 return NT_STATUS_UNSUCCESSFUL;
2000 /* Get sam policy handle */
2001 status = dcerpc_samr_Connect2(b, mem_ctx,
2003 MAXIMUM_ALLOWED_ACCESS,
2006 if (!NT_STATUS_IS_OK(status)) {
2009 if (!NT_STATUS_IS_OK(result)) {
2013 /* Get domain policy handle */
2014 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2016 MAXIMUM_ALLOWED_ACCESS,
2020 if (!NT_STATUS_IS_OK(status)) {
2023 if (!NT_STATUS_IS_OK(result)) {
2027 init_lsa_String(&lsa_acct_name, member);
2029 status = dcerpc_samr_LookupNames(b, mem_ctx,
2036 if (!NT_STATUS_IS_OK(status)) {
2037 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2042 if (!NT_STATUS_IS_OK(result)) {
2044 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2049 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2051 MAXIMUM_ALLOWED_ACCESS,
2055 if (!NT_STATUS_IS_OK(status)) {
2059 if (!NT_STATUS_IS_OK(result)) {
2064 status = dcerpc_samr_AddGroupMember(b, mem_ctx,
2067 0x0005, /* unknown flags */
2069 if (!NT_STATUS_IS_OK(status)) {
2076 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2080 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2081 TALLOC_CTX *mem_ctx,
2082 const struct dom_sid *alias_sid,
2085 struct policy_handle connect_pol, domain_pol;
2086 NTSTATUS status, result;
2088 struct policy_handle alias_pol;
2089 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2091 struct dom_sid member_sid;
2092 enum lsa_SidType member_type;
2096 sid_copy(&sid, alias_sid);
2098 if (!sid_split_rid(&sid, &alias_rid)) {
2099 return NT_STATUS_UNSUCCESSFUL;
2102 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2103 member, &member_sid, &member_type);
2105 if (!NT_STATUS_IS_OK(result)) {
2106 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2111 /* Get sam policy handle */
2112 status = dcerpc_samr_Connect2(b, mem_ctx,
2114 MAXIMUM_ALLOWED_ACCESS,
2117 if (!NT_STATUS_IS_OK(status)) {
2120 if (!NT_STATUS_IS_OK(result)) {
2125 /* Get domain policy handle */
2126 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2128 MAXIMUM_ALLOWED_ACCESS,
2132 if (!NT_STATUS_IS_OK(status)) {
2135 if (!NT_STATUS_IS_OK(result)) {
2140 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2142 MAXIMUM_ALLOWED_ACCESS,
2146 if (!NT_STATUS_IS_OK(status)) {
2149 if (!NT_STATUS_IS_OK(result)) {
2153 status = dcerpc_samr_AddAliasMember(b, mem_ctx,
2157 if (!NT_STATUS_IS_OK(status)) {
2164 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2168 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2169 const struct dom_sid *domain_sid,
2170 const char *domain_name,
2171 struct cli_state *cli,
2172 struct rpc_pipe_client *pipe_hnd,
2173 TALLOC_CTX *mem_ctx,
2177 struct dom_sid group_sid;
2178 enum lsa_SidType group_type;
2180 if (argc != 2 || c->display_usage) {
2183 _("net rpc group addmem <group> <member>\n"
2184 " Add a member to a group\n"
2185 " group\tGroup to add member to\n"
2186 " member\tMember to add to group\n"));
2187 return NT_STATUS_UNSUCCESSFUL;
2190 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2191 &group_sid, &group_type))) {
2192 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2194 return NT_STATUS_UNSUCCESSFUL;
2197 if (group_type == SID_NAME_DOM_GRP) {
2198 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2199 &group_sid, argv[1]);
2201 if (!NT_STATUS_IS_OK(result)) {
2202 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2203 argv[1], argv[0], nt_errstr(result));
2208 if (group_type == SID_NAME_ALIAS) {
2209 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2210 &group_sid, argv[1]);
2212 if (!NT_STATUS_IS_OK(result)) {
2213 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2214 argv[1], argv[0], nt_errstr(result));
2219 d_fprintf(stderr, _("Can only add members to global or local groups "
2220 "which %s is not\n"), argv[0]);
2222 return NT_STATUS_UNSUCCESSFUL;
2225 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2227 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2228 rpc_group_addmem_internals,
2232 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2233 struct rpc_pipe_client *pipe_hnd,
2234 TALLOC_CTX *mem_ctx,
2235 const struct dom_sid *group_sid,
2238 struct policy_handle connect_pol, domain_pol;
2239 NTSTATUS status, result;
2241 struct policy_handle group_pol;
2242 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2244 struct samr_Ids rids, rid_types;
2245 struct lsa_String lsa_acct_name;
2249 sid_copy(&sid, group_sid);
2251 if (!sid_split_rid(&sid, &group_rid))
2252 return NT_STATUS_UNSUCCESSFUL;
2254 /* Get sam policy handle */
2255 status = dcerpc_samr_Connect2(b, mem_ctx,
2257 MAXIMUM_ALLOWED_ACCESS,
2260 if (!NT_STATUS_IS_OK(status)) {
2263 if (!NT_STATUS_IS_OK(result)) {
2268 /* Get domain policy handle */
2269 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2271 MAXIMUM_ALLOWED_ACCESS,
2275 if (!NT_STATUS_IS_OK(status)) {
2278 if (!NT_STATUS_IS_OK(result)) {
2282 init_lsa_String(&lsa_acct_name, member);
2284 status = dcerpc_samr_LookupNames(b, mem_ctx,
2291 if (!NT_STATUS_IS_OK(status)) {
2292 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2297 if (!NT_STATUS_IS_OK(result)) {
2299 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2304 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2306 MAXIMUM_ALLOWED_ACCESS,
2310 if (!NT_STATUS_IS_OK(status)) {
2313 if (!NT_STATUS_IS_OK(result)) {
2318 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2322 if (!NT_STATUS_IS_OK(status)) {
2328 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2332 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2333 TALLOC_CTX *mem_ctx,
2334 const struct dom_sid *alias_sid,
2337 struct policy_handle connect_pol, domain_pol;
2338 NTSTATUS status, result;
2340 struct policy_handle alias_pol;
2341 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2343 struct dom_sid member_sid;
2344 enum lsa_SidType member_type;
2348 sid_copy(&sid, alias_sid);
2350 if (!sid_split_rid(&sid, &alias_rid))
2351 return NT_STATUS_UNSUCCESSFUL;
2353 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2354 member, &member_sid, &member_type);
2356 if (!NT_STATUS_IS_OK(result)) {
2357 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2362 /* Get sam policy handle */
2363 status = dcerpc_samr_Connect2(b, mem_ctx,
2365 MAXIMUM_ALLOWED_ACCESS,
2368 if (!NT_STATUS_IS_OK(status)) {
2371 if (!NT_STATUS_IS_OK(result)) {
2376 /* Get domain policy handle */
2377 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2379 MAXIMUM_ALLOWED_ACCESS,
2383 if (!NT_STATUS_IS_OK(status)) {
2386 if (!NT_STATUS_IS_OK(result)) {
2391 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2393 MAXIMUM_ALLOWED_ACCESS,
2397 if (!NT_STATUS_IS_OK(status)) {
2401 if (!NT_STATUS_IS_OK(result)) {
2405 status = dcerpc_samr_DeleteAliasMember(b, mem_ctx,
2410 if (!NT_STATUS_IS_OK(status)) {
2417 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2421 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2422 const struct dom_sid *domain_sid,
2423 const char *domain_name,
2424 struct cli_state *cli,
2425 struct rpc_pipe_client *pipe_hnd,
2426 TALLOC_CTX *mem_ctx,
2430 struct dom_sid group_sid;
2431 enum lsa_SidType group_type;
2433 if (argc != 2 || c->display_usage) {
2436 _("net rpc group delmem <group> <member>\n"
2437 " Delete a member from a group\n"
2438 " group\tGroup to delete member from\n"
2439 " member\tMember to delete from group\n"));
2440 return NT_STATUS_UNSUCCESSFUL;
2443 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2444 &group_sid, &group_type))) {
2445 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2447 return NT_STATUS_UNSUCCESSFUL;
2450 if (group_type == SID_NAME_DOM_GRP) {
2451 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2452 &group_sid, argv[1]);
2454 if (!NT_STATUS_IS_OK(result)) {
2455 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2456 argv[1], argv[0], nt_errstr(result));
2461 if (group_type == SID_NAME_ALIAS) {
2462 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2463 &group_sid, argv[1]);
2465 if (!NT_STATUS_IS_OK(result)) {
2466 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2467 argv[1], argv[0], nt_errstr(result));
2472 d_fprintf(stderr, _("Can only delete members from global or local "
2473 "groups which %s is not\n"), argv[0]);
2475 return NT_STATUS_UNSUCCESSFUL;
2478 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2480 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2481 rpc_group_delmem_internals,
2486 * List groups on a remote RPC server.
2488 * All parameters are provided by the run_rpc_command function, except for
2489 * argc, argv which are passes through.
2491 * @param domain_sid The domain sid acquired from the remote server.
2492 * @param cli A cli_state connected to the server.
2493 * @param mem_ctx Talloc context, destroyed on completion of the function.
2494 * @param argc Standard main() style argc.
2495 * @param argv Standard main() style argv. Initial components are already
2498 * @return Normal NTSTATUS return.
2501 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2502 const struct dom_sid *domain_sid,
2503 const char *domain_name,
2504 struct cli_state *cli,
2505 struct rpc_pipe_client *pipe_hnd,
2506 TALLOC_CTX *mem_ctx,
2510 struct policy_handle connect_pol, domain_pol;
2511 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2512 uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2513 struct samr_SamArray *groups = NULL;
2514 bool global = false;
2516 bool builtin = false;
2518 if (c->display_usage) {
2521 _("net rpc group list [global] [local] [builtin]\n"
2522 " List groups on RPC server\n"
2523 " global\tList global groups\n"
2524 " local\tList local groups\n"
2525 " builtin\tList builtin groups\n"
2526 " If none of global, local or builtin is "
2527 "specified, all three options are considered "
2529 return NT_STATUS_OK;
2538 for (i=0; i<argc; i++) {
2539 if (strequal(argv[i], "global"))
2542 if (strequal(argv[i], "local"))
2545 if (strequal(argv[i], "builtin"))
2549 /* Get sam policy handle */
2551 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2553 MAXIMUM_ALLOWED_ACCESS,
2555 if (!NT_STATUS_IS_OK(result)) {
2559 /* Get domain policy handle */
2561 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2563 MAXIMUM_ALLOWED_ACCESS,
2564 CONST_DISCARD(struct dom_sid2 *, domain_sid),
2566 if (!NT_STATUS_IS_OK(result)) {
2570 /* Query domain groups */
2571 if (c->opt_long_list_entries)
2572 d_printf(_("\nGroup name Comment"
2573 "\n-----------------------------\n"));
2575 uint32_t max_size, total_size, returned_size;
2576 union samr_DispInfo info;
2580 dcerpc_get_query_dispinfo_params(
2581 loop_count, &max_entries, &max_size);
2583 result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
2592 num_entries = info.info3.count;
2593 start_idx += info.info3.count;
2595 if (!NT_STATUS_IS_OK(result) &&
2596 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2599 for (i = 0; i < num_entries; i++) {
2601 const char *group = NULL;
2602 const char *desc = NULL;
2604 group = info.info3.entries[i].account_name.string;
2605 desc = info.info3.entries[i].description.string;
2607 if (c->opt_long_list_entries)
2608 printf("%-21.21s %-50.50s\n",
2611 printf("%s\n", group);
2613 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2614 /* query domain aliases */
2619 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2625 if (!NT_STATUS_IS_OK(result) &&
2626 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2629 for (i = 0; i < num_entries; i++) {
2631 const char *description = NULL;
2633 if (c->opt_long_list_entries) {
2635 struct policy_handle alias_pol;
2636 union samr_AliasInfo *info = NULL;
2638 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2641 groups->entries[i].idx,
2643 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2647 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2649 description = info->description.string;
2653 if (description != NULL) {
2654 printf("%-21.21s %-50.50s\n",
2655 groups->entries[i].name.string,
2658 printf("%s\n", groups->entries[i].name.string);
2661 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2662 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2663 /* Get builtin policy handle */
2665 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2667 MAXIMUM_ALLOWED_ACCESS,
2668 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2670 if (!NT_STATUS_IS_OK(result)) {
2673 /* query builtin aliases */
2676 if (!builtin) break;
2678 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2684 if (!NT_STATUS_IS_OK(result) &&
2685 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2688 for (i = 0; i < num_entries; i++) {
2690 const char *description = NULL;
2692 if (c->opt_long_list_entries) {
2694 struct policy_handle alias_pol;
2695 union samr_AliasInfo *info = NULL;
2697 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2700 groups->entries[i].idx,
2702 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2706 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2708 description = info->description.string;
2712 if (description != NULL) {
2713 printf("%-21.21s %-50.50s\n",
2714 groups->entries[i].name.string,
2717 printf("%s\n", groups->entries[i].name.string);
2720 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2726 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2728 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2729 rpc_group_list_internals,
2733 static NTSTATUS rpc_list_group_members(struct net_context *c,
2734 struct rpc_pipe_client *pipe_hnd,
2735 TALLOC_CTX *mem_ctx,
2736 const char *domain_name,
2737 const struct dom_sid *domain_sid,
2738 struct policy_handle *domain_pol,
2742 struct policy_handle group_pol;
2743 uint32 num_members, *group_rids;
2745 struct samr_RidAttrArray *rids = NULL;
2746 struct lsa_Strings names;
2747 struct samr_Ids types;
2750 sid_to_fstring(sid_str, domain_sid);
2752 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2754 MAXIMUM_ALLOWED_ACCESS,
2758 if (!NT_STATUS_IS_OK(result))
2761 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
2765 if (!NT_STATUS_IS_OK(result))
2768 num_members = rids->count;
2769 group_rids = rids->rids;
2771 while (num_members > 0) {
2772 int this_time = 512;
2774 if (num_members < this_time)
2775 this_time = num_members;
2777 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
2784 if (!NT_STATUS_IS_OK(result))
2787 /* We only have users as members, but make the output
2788 the same as the output of alias members */
2790 for (i = 0; i < this_time; i++) {
2792 if (c->opt_long_list_entries) {
2793 printf("%s-%d %s\\%s %d\n", sid_str,
2794 group_rids[i], domain_name,
2795 names.names[i].string,
2798 printf("%s\\%s\n", domain_name,
2799 names.names[i].string);
2803 num_members -= this_time;
2807 return NT_STATUS_OK;
2810 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2811 struct rpc_pipe_client *pipe_hnd,
2812 TALLOC_CTX *mem_ctx,
2813 struct policy_handle *domain_pol,
2817 struct rpc_pipe_client *lsa_pipe;
2818 struct policy_handle alias_pol, lsa_pol;
2820 struct dom_sid *alias_sids;
2823 enum lsa_SidType *types;
2825 struct lsa_SidArray sid_array;
2827 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2829 MAXIMUM_ALLOWED_ACCESS,
2833 if (!NT_STATUS_IS_OK(result))
2836 result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
2840 if (!NT_STATUS_IS_OK(result)) {
2841 d_fprintf(stderr, _("Couldn't list alias members\n"));
2845 num_members = sid_array.num_sids;
2847 if (num_members == 0) {
2848 return NT_STATUS_OK;
2851 result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2852 &ndr_table_lsarpc.syntax_id,
2854 if (!NT_STATUS_IS_OK(result)) {
2855 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
2856 nt_errstr(result) );
2860 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2861 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2863 if (!NT_STATUS_IS_OK(result)) {
2864 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
2865 TALLOC_FREE(lsa_pipe);
2869 alias_sids = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, num_members);
2871 d_fprintf(stderr, _("Out of memory\n"));
2872 TALLOC_FREE(lsa_pipe);
2873 return NT_STATUS_NO_MEMORY;
2876 for (i=0; i<num_members; i++) {
2877 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2880 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
2881 num_members, alias_sids,
2882 &domains, &names, &types);
2884 if (!NT_STATUS_IS_OK(result) &&
2885 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2886 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
2887 TALLOC_FREE(lsa_pipe);
2891 for (i = 0; i < num_members; i++) {
2893 sid_to_fstring(sid_str, &alias_sids[i]);
2895 if (c->opt_long_list_entries) {
2896 printf("%s %s\\%s %d\n", sid_str,
2897 domains[i] ? domains[i] : _("*unknown*"),
2898 names[i] ? names[i] : _("*unknown*"), types[i]);
2901 printf("%s\\%s\n", domains[i], names[i]);
2903 printf("%s\n", sid_str);
2907 TALLOC_FREE(lsa_pipe);
2908 return NT_STATUS_OK;
2911 static NTSTATUS rpc_group_members_internals(struct net_context *c,
2912 const struct dom_sid *domain_sid,
2913 const char *domain_name,
2914 struct cli_state *cli,
2915 struct rpc_pipe_client *pipe_hnd,
2916 TALLOC_CTX *mem_ctx,
2921 struct policy_handle connect_pol, domain_pol;
2922 struct samr_Ids rids, rid_types;
2923 struct lsa_String lsa_acct_name;
2925 /* Get sam policy handle */
2927 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2929 MAXIMUM_ALLOWED_ACCESS,
2932 if (!NT_STATUS_IS_OK(result))
2935 /* Get domain policy handle */
2937 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2939 MAXIMUM_ALLOWED_ACCESS,
2940 CONST_DISCARD(struct dom_sid2 *, domain_sid),
2943 if (!NT_STATUS_IS_OK(result))
2946 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
2948 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2955 if (!NT_STATUS_IS_OK(result)) {
2957 /* Ok, did not find it in the global sam, try with builtin */
2959 struct dom_sid sid_Builtin;
2961 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2963 sid_copy(&sid_Builtin, &global_sid_Builtin);
2965 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2967 MAXIMUM_ALLOWED_ACCESS,
2971 if (!NT_STATUS_IS_OK(result)) {
2972 d_fprintf(stderr, _("Couldn't find group %s\n"),
2977 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2984 if (!NT_STATUS_IS_OK(result)) {
2985 d_fprintf(stderr, _("Couldn't find group %s\n"),
2991 if (rids.count != 1) {
2992 d_fprintf(stderr, _("Couldn't find group %s\n"),
2997 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
2998 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
2999 domain_sid, &domain_pol,
3003 if (rid_types.ids[0] == SID_NAME_ALIAS) {
3004 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
3008 return NT_STATUS_NO_SUCH_GROUP;
3011 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
3013 if (argc != 1 || c->display_usage) {
3014 return rpc_group_usage(c, argc, argv);
3017 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
3018 rpc_group_members_internals,
3022 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
3024 NET_API_STATUS status;
3025 struct GROUP_INFO_0 g0;
3029 d_printf(_("Usage:\n"));
3030 d_printf("net rpc group rename group newname\n");
3034 g0.grpi0_name = argv[1];
3036 status = NetGroupSetInfo(c->opt_host,
3043 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
3044 argv[0], libnetapi_get_error_string(c->netapi_ctx,
3052 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
3054 if (argc != 2 || c->display_usage) {
3055 return rpc_group_usage(c, argc, argv);
3058 return rpc_group_rename_internals(c, argc, argv);
3062 * 'net rpc group' entrypoint.
3063 * @param argc Standard main() style argc.
3064 * @param argv Standard main() style argv. Initial components are already
3068 int net_rpc_group(struct net_context *c, int argc, const char **argv)
3070 NET_API_STATUS status;
3072 struct functable func[] = {
3077 N_("Create specified group"),
3078 N_("net rpc group add\n"
3079 " Create specified group")
3085 N_("Delete specified group"),
3086 N_("net rpc group delete\n"
3087 " Delete specified group")
3093 N_("Add member to group"),
3094 N_("net rpc group addmem\n"
3095 " Add member to group")
3101 N_("Remove member from group"),
3102 N_("net rpc group delmem\n"
3103 " Remove member from group")
3110 N_("net rpc group list\n"
3117 N_("List group members"),
3118 N_("net rpc group members\n"
3119 " List group members")
3126 N_("net rpc group rename\n"
3129 {NULL, NULL, 0, NULL, NULL}
3132 status = libnetapi_net_init(&c->netapi_ctx);
3136 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
3137 libnetapi_set_password(c->netapi_ctx, c->opt_password);
3138 if (c->opt_kerberos) {
3139 libnetapi_set_use_kerberos(c->netapi_ctx);
3143 if (c->display_usage) {
3144 d_printf(_("Usage:\n"));
3145 d_printf(_("net rpc group\n"
3146 " Alias for net rpc group list global "
3147 "local builtin\n"));
3148 net_display_usage_from_functable(func);
3152 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
3153 rpc_group_list_internals,
3157 return net_run_function(c, argc, argv, "net rpc group", func);
3160 /****************************************************************************/
3162 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
3164 return net_share_usage(c, argc, argv);
3168 * Add a share on a remote RPC server.
3170 * @param argc Standard main() style argc.
3171 * @param argv Standard main() style argv. Initial components are already
3174 * @return A shell status integer (0 for success).
3177 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3179 NET_API_STATUS status;
3182 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3183 uint32 num_users=0, perms=0;
3184 char *password=NULL; /* don't allow a share password */
3185 struct SHARE_INFO_2 i2;
3186 uint32_t parm_error = 0;
3188 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3189 return rpc_share_usage(c, argc, argv);
3192 if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
3196 path = strchr(sharename, '=');
3203 i2.shi2_netname = sharename;
3204 i2.shi2_type = type;
3205 i2.shi2_remark = c->opt_comment;
3206 i2.shi2_permissions = perms;
3207 i2.shi2_max_uses = c->opt_maxusers;
3208 i2.shi2_current_uses = num_users;
3209 i2.shi2_path = path;
3210 i2.shi2_passwd = password;
3212 status = NetShareAdd(c->opt_host,
3217 printf(_("NetShareAdd failed with: %s\n"),
3218 libnetapi_get_error_string(c->netapi_ctx, status));
3225 * Delete a share on a remote RPC server.
3227 * @param domain_sid The domain sid acquired from the remote server.
3228 * @param argc Standard main() style argc.
3229 * @param argv Standard main() style argv. Initial components are already
3232 * @return A shell status integer (0 for success).
3234 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3236 if (argc < 1 || c->display_usage) {
3237 return rpc_share_usage(c, argc, argv);
3240 return NetShareDel(c->opt_host, argv[0], 0);
3244 * Formatted print of share info
3246 * @param r pointer to SHARE_INFO_1 to format
3249 static void display_share_info_1(struct net_context *c,
3250 struct SHARE_INFO_1 *r)
3252 if (c->opt_long_list_entries) {
3253 d_printf("%-12s %-8.8s %-50s\n",
3255 net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3258 d_printf("%s\n", r->shi1_netname);
3262 static WERROR get_share_info(struct net_context *c,
3263 struct rpc_pipe_client *pipe_hnd,
3264 TALLOC_CTX *mem_ctx,
3268 struct srvsvc_NetShareInfoCtr *info_ctr)
3272 union srvsvc_NetShareInfo info;
3273 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3275 /* no specific share requested, enumerate all */
3278 uint32_t preferred_len = 0xffffffff;
3279 uint32_t total_entries = 0;
3280 uint32_t resume_handle = 0;
3282 info_ctr->level = level;
3284 status = dcerpc_srvsvc_NetShareEnumAll(b, mem_ctx,
3291 if (!NT_STATUS_IS_OK(status)) {
3292 return ntstatus_to_werror(status);
3297 /* request just one share */
3298 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
3305 if (!NT_STATUS_IS_OK(status)) {
3306 result = ntstatus_to_werror(status);
3310 if (!W_ERROR_IS_OK(result)) {
3315 ZERO_STRUCTP(info_ctr);
3317 info_ctr->level = level;
3322 struct srvsvc_NetShareCtr1 *ctr1;
3324 ctr1 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr1);
3325 W_ERROR_HAVE_NO_MEMORY(ctr1);
3328 ctr1->array = info.info1;
3330 info_ctr->ctr.ctr1 = ctr1;
3336 struct srvsvc_NetShareCtr2 *ctr2;
3338 ctr2 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr2);
3339 W_ERROR_HAVE_NO_MEMORY(ctr2);
3342 ctr2->array = info.info2;
3344 info_ctr->ctr.ctr2 = ctr2;
3350 struct srvsvc_NetShareCtr502 *ctr502;
3352 ctr502 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr502);
3353 W_ERROR_HAVE_NO_MEMORY(ctr502);
3356 ctr502->array = info.info502;
3358 info_ctr->ctr.ctr502 = ctr502;
3368 * 'net rpc share list' entrypoint.
3369 * @param argc Standard main() style argc.
3370 * @param argv Standard main() style argv. Initial components are already
3373 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3375 NET_API_STATUS status;
3376 struct SHARE_INFO_1 *i1 = NULL;
3377 uint32_t entries_read = 0;
3378 uint32_t total_entries = 0;
3379 uint32_t resume_handle = 0;
3380 uint32_t i, level = 1;
3382 if (c->display_usage) {
3384 "net rpc share list\n"
3387 _("List shares on remote server"));
3391 status = NetShareEnum(c->opt_host,
3393 (uint8_t **)(void *)&i1,
3402 /* Display results */
3404 if (c->opt_long_list_entries) {
3406 "\nEnumerating shared resources (exports) on remote server:\n\n"
3407 "\nShare name Type Description\n"
3408 "---------- ---- -----------\n"));
3410 for (i = 0; i < entries_read; i++)
3411 display_share_info_1(c, &i1[i]);
3416 static bool check_share_availability(struct cli_state *cli, const char *netname)
3420 status = cli_tcon_andx(cli, netname, "A:", "", 0);
3421 if (!NT_STATUS_IS_OK(status)) {
3422 d_printf(_("skipping [%s]: not a file share.\n"), netname);
3426 status = cli_tdis(cli);
3427 if (!NT_STATUS_IS_OK(status)) {
3428 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3435 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3436 const char *netname, uint32 type)
3438 /* only support disk shares */
3439 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3440 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3445 /* skip builtin shares */
3446 /* FIXME: should print$ be added too ? */
3447 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3448 strequal(netname,"global"))
3451 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3452 printf(_("excluding [%s]\n"), netname);
3456 return check_share_availability(cli, netname);
3460 * Migrate shares from a remote RPC server to the local RPC server.
3462 * All parameters are provided by the run_rpc_command function, except for
3463 * argc, argv which are passed through.
3465 * @param domain_sid The domain sid acquired from the remote server.
3466 * @param cli A cli_state connected to the server.
3467 * @param mem_ctx Talloc context, destroyed on completion of the function.
3468 * @param argc Standard main() style argc.
3469 * @param argv Standard main() style argv. Initial components are already
3472 * @return Normal NTSTATUS return.
3475 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3476 const struct dom_sid *domain_sid,
3477 const char *domain_name,
3478 struct cli_state *cli,
3479 struct rpc_pipe_client *pipe_hnd,
3480 TALLOC_CTX *mem_ctx,
3485 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3486 struct srvsvc_NetShareInfoCtr ctr_src;
3488 struct rpc_pipe_client *srvsvc_pipe = NULL;
3489 struct cli_state *cli_dst = NULL;
3490 uint32 level = 502; /* includes secdesc */
3491 uint32_t parm_error = 0;
3492 struct dcerpc_binding_handle *b;
3494 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3496 if (!W_ERROR_IS_OK(result))
3499 /* connect destination PI_SRVSVC */
3500 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3501 &ndr_table_srvsvc.syntax_id);
3502 if (!NT_STATUS_IS_OK(nt_status))
3505 b = srvsvc_pipe->binding_handle;
3507 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3509 union srvsvc_NetShareInfo info;
3510 struct srvsvc_NetShareInfo502 info502 =
3511 ctr_src.ctr.ctr502->array[i];
3513 /* reset error-code */
3514 nt_status = NT_STATUS_UNSUCCESSFUL;
3516 if (!check_share_sanity(c, cli, info502.name, info502.type))
3519 /* finally add the share on the dst server */
3521 printf(_("migrating: [%s], path: %s, comment: %s, without "
3523 info502.name, info502.path, info502.comment);
3525 info.info502 = &info502;
3527 nt_status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
3528 srvsvc_pipe->desthost,
3533 if (!NT_STATUS_IS_OK(nt_status)) {
3534 printf(_("cannot add share: %s\n"),
3535 nt_errstr(nt_status));
3538 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3539 printf(_(" [%s] does already exist\n"),
3544 if (!W_ERROR_IS_OK(result)) {
3545 nt_status = werror_to_ntstatus(result);
3546 printf(_("cannot add share: %s\n"),
3547 win_errstr(result));
3553 nt_status = NT_STATUS_OK;
3557 cli_shutdown(cli_dst);
3565 * Migrate shares from a RPC server to another.
3567 * @param argc Standard main() style argc.
3568 * @param argv Standard main() style argv. Initial components are already
3571 * @return A shell status integer (0 for success).
3573 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3576 if (c->display_usage) {
3578 "net rpc share migrate shares\n"
3581 _("Migrate shares to local server"));
3586 printf(_("no server to migrate\n"));
3590 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3591 rpc_share_migrate_shares_internals,
3598 * @param f file_info
3599 * @param mask current search mask
3600 * @param state arg-pointer
3603 static NTSTATUS copy_fn(const char *mnt, struct file_info *f,
3604 const char *mask, void *state)
3606 static NTSTATUS nt_status;
3607 static struct copy_clistate *local_state;
3608 static fstring filename, new_mask;
3611 struct net_context *c;
3613 local_state = (struct copy_clistate *)state;
3614 nt_status = NT_STATUS_UNSUCCESSFUL;
3618 if (strequal(f->name, ".") || strequal(f->name, ".."))
3619 return NT_STATUS_OK;
3621 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3624 if (f->mode & aDIR) {
3626 DEBUG(3,("got dir: %s\n", f->name));
3628 fstrcpy(dir, local_state->cwd);
3630 fstrcat(dir, f->name);
3632 switch (net_mode_share)
3634 case NET_MODE_SHARE_MIGRATE:
3635 /* create that directory */
3636 nt_status = net_copy_file(c, local_state->mem_ctx,
3637 local_state->cli_share_src,
3638 local_state->cli_share_dst,
3640 c->opt_acls? true : false,
3641 c->opt_attrs? true : false,
3642 c->opt_timestamps? true:false,
3646 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3647 return NT_STATUS_INTERNAL_ERROR;
3650 if (!NT_STATUS_IS_OK(nt_status)) {
3651 printf(_("could not handle dir %s: %s\n"),
3652 dir, nt_errstr(nt_status));
3656 /* search below that directory */
3657 fstrcpy(new_mask, dir);
3658 fstrcat(new_mask, "\\*");
3660 old_dir = local_state->cwd;
3661 local_state->cwd = dir;
3662 nt_status = sync_files(local_state, new_mask);
3663 if (!NT_STATUS_IS_OK(nt_status)) {
3664 printf(_("could not handle files\n"));
3666 local_state->cwd = old_dir;
3673 fstrcpy(filename, local_state->cwd);
3674 fstrcat(filename, "\\");
3675 fstrcat(filename, f->name);
3677 DEBUG(3,("got file: %s\n", filename));
3679 switch (net_mode_share)
3681 case NET_MODE_SHARE_MIGRATE:
3682 nt_status = net_copy_file(c, local_state->mem_ctx,
3683 local_state->cli_share_src,
3684 local_state->cli_share_dst,
3686 c->opt_acls? true : false,
3687 c->opt_attrs? true : false,
3688 c->opt_timestamps? true: false,
3692 d_fprintf(stderr, _("Unsupported file mode %d\n"),
3694 return NT_STATUS_INTERNAL_ERROR;
3697 if (!NT_STATUS_IS_OK(nt_status))
3698 printf(_("could not handle file %s: %s\n"),
3699 filename, nt_errstr(nt_status));
3704 * sync files, can be called recursivly to list files
3705 * and then call copy_fn for each file
3707 * @param cp_clistate pointer to the copy_clistate we work with
3708 * @param mask the current search mask
3710 * @return Boolean result
3712 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask)
3714 struct cli_state *targetcli;
3715 char *targetpath = NULL;
3718 DEBUG(3,("calling cli_list with mask: %s\n", mask));
3720 if ( !cli_resolve_path(talloc_tos(), "", NULL, cp_clistate->cli_share_src,
3721 mask, &targetcli, &targetpath ) ) {
3722 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
3724 mask, cli_errstr(cp_clistate->cli_share_src));
3725 return cli_nt_error(cp_clistate->cli_share_src);
3728 status = cli_list(targetcli, targetpath, cp_clistate->attribute,
3729 copy_fn, cp_clistate);
3730 if (!NT_STATUS_IS_OK(status)) {
3731 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
3732 mask, nt_errstr(status));
3740 * Set the top level directory permissions before we do any further copies.
3741 * Should set up ACL inheritance.
3744 bool copy_top_level_perms(struct net_context *c,
3745 struct copy_clistate *cp_clistate,
3746 const char *sharename)
3748 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3750 switch (net_mode_share) {
3751 case NET_MODE_SHARE_MIGRATE:
3752 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3753 nt_status = net_copy_fileattr(c,
3754 cp_clistate->mem_ctx,
3755 cp_clistate->cli_share_src,
3756 cp_clistate->cli_share_dst,
3758 c->opt_acls? true : false,
3759 c->opt_attrs? true : false,
3760 c->opt_timestamps? true: false,
3764 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3768 if (!NT_STATUS_IS_OK(nt_status)) {
3769 printf(_("Could handle directory attributes for top level "
3770 "directory of share %s. Error %s\n"),
3771 sharename, nt_errstr(nt_status));
3779 * Sync all files inside a remote share to another share (over smb).
3781 * All parameters are provided by the run_rpc_command function, except for
3782 * argc, argv which are passed through.
3784 * @param domain_sid The domain sid acquired from the remote server.
3785 * @param cli A cli_state connected to the server.
3786 * @param mem_ctx Talloc context, destroyed on completion of the function.
3787 * @param argc Standard main() style argc.
3788 * @param argv Standard main() style argv. Initial components are already
3791 * @return Normal NTSTATUS return.
3794 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
3795 const struct dom_sid *domain_sid,
3796 const char *domain_name,
3797 struct cli_state *cli,
3798 struct rpc_pipe_client *pipe_hnd,
3799 TALLOC_CTX *mem_ctx,
3804 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3805 struct srvsvc_NetShareInfoCtr ctr_src;
3808 struct copy_clistate cp_clistate;
3809 bool got_src_share = false;
3810 bool got_dst_share = false;
3811 const char *mask = "\\*";
3814 dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3816 nt_status = NT_STATUS_NO_MEMORY;
3820 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3823 if (!W_ERROR_IS_OK(result))
3826 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3828 struct srvsvc_NetShareInfo502 info502 =
3829 ctr_src.ctr.ctr502->array[i];
3831 if (!check_share_sanity(c, cli, info502.name, info502.type))
3834 /* one might not want to mirror whole discs :) */
3835 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3836 d_printf(_("skipping [%s]: builtin/hidden share\n"),
3841 switch (net_mode_share)
3843 case NET_MODE_SHARE_MIGRATE:
3847 d_fprintf(stderr, _("Unsupported mode %d\n"),
3851 printf(_(" [%s] files and directories %s ACLs, %s DOS "
3854 c->opt_acls ? _("including") : _("without"),
3855 c->opt_attrs ? _("including") : _("without"),
3856 c->opt_timestamps ? _("(preserving timestamps)") : "");
3858 cp_clistate.mem_ctx = mem_ctx;
3859 cp_clistate.cli_share_src = NULL;
3860 cp_clistate.cli_share_dst = NULL;
3861 cp_clistate.cwd = NULL;
3862 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3865 /* open share source */
3866 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
3867 &cli->dest_ss, cli->desthost,
3868 info502.name, "A:");
3869 if (!NT_STATUS_IS_OK(nt_status))
3872 got_src_share = true;
3874 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3875 /* open share destination */
3876 nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
3877 NULL, dst, info502.name, "A:");
3878 if (!NT_STATUS_IS_OK(nt_status))
3881 got_dst_share = true;
3884 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
3885 d_fprintf(stderr, _("Could not handle the top level "
3886 "directory permissions for the "
3887 "share: %s\n"), info502.name);
3888 nt_status = NT_STATUS_UNSUCCESSFUL;
3892 nt_status = sync_files(&cp_clistate, mask);
3893 if (!NT_STATUS_IS_OK(nt_status)) {
3894 d_fprintf(stderr, _("could not handle files for share: "
3895 "%s\n"), info502.name);
3900 nt_status = NT_STATUS_OK;
3905 cli_shutdown(cp_clistate.cli_share_src);
3908 cli_shutdown(cp_clistate.cli_share_dst);
3915 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
3917 if (c->display_usage) {
3919 "net share migrate files\n"
3922 _("Migrate files to local server"));
3927 d_printf(_("no server to migrate\n"));
3931 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3932 rpc_share_migrate_files_internals,
3937 * Migrate share-ACLs from a remote RPC server to the local RPC server.
3939 * All parameters are provided by the run_rpc_command function, except for
3940 * argc, argv which are passed through.
3942 * @param domain_sid The domain sid acquired from the remote server.
3943 * @param cli A cli_state connected to the server.
3944 * @param mem_ctx Talloc context, destroyed on completion of the function.
3945 * @param argc Standard main() style argc.
3946 * @param argv Standard main() style argv. Initial components are already
3949 * @return Normal NTSTATUS return.
3952 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
3953 const struct dom_sid *domain_sid,
3954 const char *domain_name,
3955 struct cli_state *cli,
3956 struct rpc_pipe_client *pipe_hnd,
3957 TALLOC_CTX *mem_ctx,
3962 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3963 struct srvsvc_NetShareInfoCtr ctr_src;
3964 union srvsvc_NetShareInfo info;
3966 struct rpc_pipe_client *srvsvc_pipe = NULL;
3967 struct cli_state *cli_dst = NULL;
3968 uint32 level = 502; /* includes secdesc */
3969 uint32_t parm_error = 0;
3970 struct dcerpc_binding_handle *b;
3972 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3975 if (!W_ERROR_IS_OK(result))
3978 /* connect destination PI_SRVSVC */
3979 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3980 &ndr_table_srvsvc.syntax_id);
3981 if (!NT_STATUS_IS_OK(nt_status))
3984 b = srvsvc_pipe->binding_handle;
3986 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3988 struct srvsvc_NetShareInfo502 info502 =
3989 ctr_src.ctr.ctr502->array[i];
3991 /* reset error-code */
3992 nt_status = NT_STATUS_UNSUCCESSFUL;
3994 if (!check_share_sanity(c, cli, info502.name, info502.type))
3997 printf(_("migrating: [%s], path: %s, comment: %s, including "
3999 info502.name, info502.path, info502.comment);
4002 display_sec_desc(info502.sd_buf.sd);
4004 /* FIXME: shouldn't we be able to just set the security descriptor ? */
4005 info.info502 = &info502;
4007 /* finally modify the share on the dst server */
4008 nt_status = dcerpc_srvsvc_NetShareSetInfo(b, mem_ctx,
4009 srvsvc_pipe->desthost,
4015 if (!NT_STATUS_IS_OK(nt_status)) {
4016 printf(_("cannot set share-acl: %s\n"),
4017 nt_errstr(nt_status));
4020 if (!W_ERROR_IS_OK(result)) {
4021 nt_status = werror_to_ntstatus(result);
4022 printf(_("cannot set share-acl: %s\n"),
4023 win_errstr(result));
4029 nt_status = NT_STATUS_OK;
4033 cli_shutdown(cli_dst);
4041 * Migrate share-acls from a RPC server to another.
4043 * @param argc Standard main() style argc.
4044 * @param argv Standard main() style argv. Initial components are already
4047 * @return A shell status integer (0 for success).
4049 static int rpc_share_migrate_security(struct net_context *c, int argc,
4052 if (c->display_usage) {
4054 "net rpc share migrate security\n"
4057 _("Migrate share-acls to local server"));
4062 d_printf(_("no server to migrate\n"));
4066 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4067 rpc_share_migrate_security_internals,
4072 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
4073 * from one server to another.
4075 * @param argc Standard main() style argc.
4076 * @param argv Standard main() style argv. Initial components are already
4079 * @return A shell status integer (0 for success).
4082 static int rpc_share_migrate_all(struct net_context *c, int argc,
4087 if (c->display_usage) {
4089 "net rpc share migrate all\n"
4092 _("Migrates shares including all share settings"));
4097 d_printf(_("no server to migrate\n"));
4101 /* order is important. we don't want to be locked out by the share-acl
4102 * before copying files - gd */
4104 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4105 rpc_share_migrate_shares_internals, argc, argv);
4109 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4110 rpc_share_migrate_files_internals, argc, argv);
4114 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4115 rpc_share_migrate_security_internals, argc,
4121 * 'net rpc share migrate' entrypoint.
4122 * @param argc Standard main() style argc.
4123 * @param argv Standard main() style argv. Initial components are already
4126 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
4129 struct functable func[] = {
4132 rpc_share_migrate_all,
4134 N_("Migrate shares from remote to local server"),
4135 N_("net rpc share migrate all\n"
4136 " Migrate shares from remote to local server")
4140 rpc_share_migrate_files,
4142 N_("Migrate files from remote to local server"),
4143 N_("net rpc share migrate files\n"
4144 " Migrate files from remote to local server")
4148 rpc_share_migrate_security,
4150 N_("Migrate share-ACLs from remote to local server"),
4151 N_("net rpc share migrate security\n"
4152 " Migrate share-ACLs from remote to local server")
4156 rpc_share_migrate_shares,
4158 N_("Migrate shares from remote to local server"),
4159 N_("net rpc share migrate shares\n"
4160 " Migrate shares from remote to local server")
4162 {NULL, NULL, 0, NULL, NULL}
4165 net_mode_share = NET_MODE_SHARE_MIGRATE;
4167 return net_run_function(c, argc, argv, "net rpc share migrate", func);
4173 struct dom_sid *members;
4176 static int num_server_aliases;
4177 static struct full_alias *server_aliases;
4180 * Add an alias to the static list.
4182 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
4184 if (server_aliases == NULL)
4185 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
4187 server_aliases[num_server_aliases] = *alias;
4188 num_server_aliases += 1;
4192 * For a specific domain on the server, fetch all the aliases
4193 * and their members. Add all of them to the server_aliases.
4196 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4197 TALLOC_CTX *mem_ctx,
4198 struct policy_handle *connect_pol,
4199 const struct dom_sid *domain_sid)
4201 uint32 start_idx, max_entries, num_entries, i;
4202 struct samr_SamArray *groups = NULL;
4204 struct policy_handle domain_pol;
4206 /* Get domain policy handle */
4208 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
4210 MAXIMUM_ALLOWED_ACCESS,
4211 CONST_DISCARD(struct dom_sid2 *, domain_sid),
4213 if (!NT_STATUS_IS_OK(result))
4220 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
4226 for (i = 0; i < num_entries; i++) {
4228 struct policy_handle alias_pol;
4229 struct full_alias alias;
4230 struct lsa_SidArray sid_array;
4233 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
4235 MAXIMUM_ALLOWED_ACCESS,
4236 groups->entries[i].idx,
4238 if (!NT_STATUS_IS_OK(result))
4241 result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
4244 if (!NT_STATUS_IS_OK(result))
4247 alias.num_members = sid_array.num_sids;
4249 result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
4250 if (!NT_STATUS_IS_OK(result))
4253 alias.members = NULL;
4255 if (alias.num_members > 0) {
4256 alias.members = SMB_MALLOC_ARRAY(struct dom_sid, alias.num_members);
4258 for (j = 0; j < alias.num_members; j++)
4259 sid_copy(&alias.members[j],
4260 sid_array.sids[j].sid);
4263 sid_compose(&alias.sid, domain_sid,
4264 groups->entries[i].idx);
4266 push_alias(mem_ctx, &alias);
4268 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4270 result = NT_STATUS_OK;
4273 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
4279 * Dump server_aliases as names for debugging purposes.
4282 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4283 const struct dom_sid *domain_sid,
4284 const char *domain_name,
4285 struct cli_state *cli,
4286 struct rpc_pipe_client *pipe_hnd,
4287 TALLOC_CTX *mem_ctx,
4293 struct policy_handle lsa_pol;
4295 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4296 SEC_FLAG_MAXIMUM_ALLOWED,
4298 if (!NT_STATUS_IS_OK(result))
4301 for (i=0; i<num_server_aliases; i++) {
4304 enum lsa_SidType *types;
4307 struct full_alias *alias = &server_aliases[i];
4309 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4311 &domains, &names, &types);
4312 if (!NT_STATUS_IS_OK(result))
4315 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4317 if (alias->num_members == 0) {
4322 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4325 &domains, &names, &types);
4327 if (!NT_STATUS_IS_OK(result) &&
4328 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4331 for (j=0; j<alias->num_members; j++)
4332 DEBUG(1, ("%s\\%s (%d); ",
4333 domains[j] ? domains[j] : "*unknown*",
4334 names[j] ? names[j] : "*unknown*",types[j]));
4338 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
4340 return NT_STATUS_OK;
4344 * Fetch a list of all server aliases and their members into
4348 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4349 const struct dom_sid *domain_sid,
4350 const char *domain_name,
4351 struct cli_state *cli,
4352 struct rpc_pipe_client *pipe_hnd,
4353 TALLOC_CTX *mem_ctx,
4358 struct policy_handle connect_pol;
4360 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
4362 MAXIMUM_ALLOWED_ACCESS,
4365 if (!NT_STATUS_IS_OK(result))
4368 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4369 &global_sid_Builtin);
4371 if (!NT_STATUS_IS_OK(result))
4374 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4377 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
4382 static void init_user_token(struct security_token *token, struct dom_sid *user_sid)
4384 token->num_sids = 4;
4386 if (!(token->sids = SMB_MALLOC_ARRAY(struct dom_sid, 4))) {
4387 d_fprintf(stderr, "malloc %s\n",_("failed"));
4388 token->num_sids = 0;
4392 token->sids[0] = *user_sid;
4393 sid_copy(&token->sids[1], &global_sid_World);
4394 sid_copy(&token->sids[2], &global_sid_Network);
4395 sid_copy(&token->sids[3], &global_sid_Authenticated_Users);
4398 static void free_user_token(struct security_token *token)
4400 SAFE_FREE(token->sids);
4403 static void add_sid_to_token(struct security_token *token, struct dom_sid *sid)
4405 if (security_token_has_sid(token, sid))
4408 token->sids = SMB_REALLOC_ARRAY(token->sids, struct dom_sid, token->num_sids+1);
4413 sid_copy(&token->sids[token->num_sids], sid);
4415 token->num_sids += 1;
4420 struct security_token token;
4423 static void dump_user_token(struct user_token *token)
4427 d_printf("%s\n", token->name);
4429 for (i=0; i<token->token.num_sids; i++) {
4430 d_printf(" %s\n", sid_string_tos(&token->token.sids[i]));
4434 static bool is_alias_member(struct dom_sid *sid, struct full_alias *alias)
4438 for (i=0; i<alias->num_members; i++) {
4439 if (dom_sid_compare(sid, &alias->members[i]) == 0)
4446 static void collect_sid_memberships(struct security_token *token, struct dom_sid sid)
4450 for (i=0; i<num_server_aliases; i++) {
4451 if (is_alias_member(&sid, &server_aliases[i]))
4452 add_sid_to_token(token, &server_aliases[i].sid);
4457 * We got a user token with all the SIDs we can know about without asking the
4458 * server directly. These are the user and domain group sids. All of these can
4459 * be members of aliases. So scan the list of aliases for each of the SIDs and
4460 * add them to the token.
4463 static void collect_alias_memberships(struct security_token *token)
4465 int num_global_sids = token->num_sids;
4468 for (i=0; i<num_global_sids; i++) {
4469 collect_sid_memberships(token, token->sids[i]);
4473 static bool get_user_sids(const char *domain, const char *user, struct security_token *token)
4475 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4476 enum wbcSidType type;
4478 struct wbcDomainSid wsid;
4479 char *sid_str = NULL;
4480 struct dom_sid user_sid;
4481 uint32_t num_groups;
4482 gid_t *groups = NULL;
4485 fstr_sprintf(full_name, "%s%c%s",
4486 domain, *lp_winbind_separator(), user);
4488 /* First let's find out the user sid */
4490 wbc_status = wbcLookupName(domain, user, &wsid, &type);
4492 if (!WBC_ERROR_IS_OK(wbc_status)) {
4493 DEBUG(1, ("winbind could not find %s: %s\n",
4494 full_name, wbcErrorString(wbc_status)));
4498 wbc_status = wbcSidToString(&wsid, &sid_str);
4499 if (!WBC_ERROR_IS_OK(wbc_status)) {
4503 if (type != WBC_SID_NAME_USER) {
4504 wbcFreeMemory(sid_str);
4505 DEBUG(1, ("%s is not a user\n", full_name));
4509 if (!string_to_sid(&user_sid, sid_str)) {
4510 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4514 wbcFreeMemory(sid_str);
4517 init_user_token(token, &user_sid);
4519 /* And now the groups winbind knows about */
4521 wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4522 if (!WBC_ERROR_IS_OK(wbc_status)) {
4523 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4524 full_name, wbcErrorString(wbc_status)));
4528 for (i = 0; i < num_groups; i++) {
4529 gid_t gid = groups[i];
4532 wbc_status = wbcGidToSid(gid, &wsid);
4533 if (!WBC_ERROR_IS_OK(wbc_status)) {
4534 DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4535 (unsigned int)gid, wbcErrorString(wbc_status)));
4536 wbcFreeMemory(groups);
4540 wbc_status = wbcSidToString(&wsid, &sid_str);
4541 if (!WBC_ERROR_IS_OK(wbc_status)) {
4542 wbcFreeMemory(groups);
4546 DEBUG(3, (" %s\n", sid_str));
4548 string_to_sid(&sid, sid_str);
4549 wbcFreeMemory(sid_str);
4552 add_sid_to_token(token, &sid);
4554 wbcFreeMemory(groups);
4560 * Get a list of all user tokens we want to look at
4563 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4564 struct user_token **user_tokens)
4566 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4567 uint32_t i, num_users;
4569 struct user_token *result;
4570 TALLOC_CTX *frame = NULL;
4572 if (lp_winbind_use_default_domain() &&
4573 (c->opt_target_workgroup == NULL)) {
4574 d_fprintf(stderr, _("winbind use default domain = yes set, "
4575 "please specify a workgroup\n"));
4579 /* Send request to winbind daemon */
4581 wbc_status = wbcListUsers(NULL, &num_users, &users);
4582 if (!WBC_ERROR_IS_OK(wbc_status)) {
4583 DEBUG(1, (_("winbind could not list users: %s\n"),
4584 wbcErrorString(wbc_status)));
4588 result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4590 if (result == NULL) {
4591 DEBUG(1, ("Could not malloc sid array\n"));
4592 wbcFreeMemory(users);
4596 frame = talloc_stackframe();
4597 for (i=0; i < num_users; i++) {
4598 fstring domain, user;
4601 fstrcpy(result[i].name, users[i]);
4603 p = strchr(users[i], *lp_winbind_separator());
4605 DEBUG(3, ("%s\n", users[i]));
4608 fstrcpy(domain, c->opt_target_workgroup);
4609 fstrcpy(user, users[i]);
4612 fstrcpy(domain, users[i]);
4617 get_user_sids(domain, user, &(result[i].token));
4620 wbcFreeMemory(users);
4622 *num_tokens = num_users;
4623 *user_tokens = result;
4628 static bool get_user_tokens_from_file(FILE *f,
4630 struct user_token **tokens)
4632 struct user_token *token = NULL;
4637 if (fgets(line, sizeof(line)-1, f) == NULL) {
4641 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
4642 line[strlen(line)-1] = '\0';
4645 if (line[0] == ' ') {
4649 if(!string_to_sid(&sid, &line[1])) {
4650 DEBUG(1,("get_user_tokens_from_file: Could "
4651 "not convert sid %s \n",&line[1]));
4655 if (token == NULL) {
4656 DEBUG(0, ("File does not begin with username"));
4660 add_sid_to_token(&token->token, &sid);
4664 /* And a new user... */
4667 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4668 if (*tokens == NULL) {
4669 DEBUG(0, ("Could not realloc tokens\n"));
4673 token = &((*tokens)[*num_tokens-1]);
4675 fstrcpy(token->name, line);
4676 token->token.num_sids = 0;
4677 token->token.sids = NULL;
4686 * Show the list of all users that have access to a share
4689 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4690 TALLOC_CTX *mem_ctx,
4691 const char *netname,
4693 struct user_token *tokens)
4696 struct security_descriptor *share_sd = NULL;
4697 struct security_descriptor *root_sd = NULL;
4698 struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4700 union srvsvc_NetShareInfo info;
4704 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4706 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
4713 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4714 DEBUG(1, ("Coult not query secdesc for share %s\n",
4719 share_sd = info.info502->sd_buf.sd;
4720 if (share_sd == NULL) {
4721 DEBUG(1, ("Got no secdesc for share %s\n",
4727 if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
4731 if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
4732 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
4733 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4736 for (i=0; i<num_tokens; i++) {
4739 if (share_sd != NULL) {
4740 status = se_access_check(share_sd, &tokens[i].token,
4743 if (!NT_STATUS_IS_OK(status)) {
4744 DEBUG(1, ("Could not check share_sd for "
4751 if (root_sd == NULL) {
4752 d_printf(" %s\n", tokens[i].name);
4756 status = se_access_check(root_sd, &tokens[i].token,
4758 if (!NT_STATUS_IS_OK(status)) {
4759 DEBUG(1, ("Could not check root_sd for user %s\n",
4763 d_printf(" %s\n", tokens[i].name);
4766 if (fnum != (uint16_t)-1)
4767 cli_close(cli, fnum);
4779 static void collect_share(const char *name, uint32 m,
4780 const char *comment, void *state)
4782 struct share_list *share_list = (struct share_list *)state;
4784 if (m != STYPE_DISKTREE)
4787 share_list->num_shares += 1;
4788 share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4789 if (!share_list->shares) {
4790 share_list->num_shares = 0;
4793 share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4797 * List shares on a remote RPC server, including the security descriptors.
4799 * All parameters are provided by the run_rpc_command function, except for
4800 * argc, argv which are passed through.
4802 * @param domain_sid The domain sid acquired from the remote server.
4803 * @param cli A cli_state connected to the server.
4804 * @param mem_ctx Talloc context, destroyed on completion of the function.
4805 * @param argc Standard main() style argc.
4806 * @param argv Standard main() style argv. Initial components are already
4809 * @return Normal NTSTATUS return.
4812 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
4813 const struct dom_sid *domain_sid,
4814 const char *domain_name,
4815 struct cli_state *cli,
4816 struct rpc_pipe_client *pipe_hnd,
4817 TALLOC_CTX *mem_ctx,
4826 struct user_token *tokens = NULL;
4829 struct share_list share_list;
4834 f = fopen(argv[0], "r");
4838 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4839 return NT_STATUS_UNSUCCESSFUL;
4842 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4848 DEBUG(0, ("Could not read users from file\n"));
4849 return NT_STATUS_UNSUCCESSFUL;
4852 for (i=0; i<num_tokens; i++)
4853 collect_alias_memberships(&tokens[i].token);
4855 share_list.num_shares = 0;
4856 share_list.shares = NULL;
4858 ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4861 DEBUG(0, ("Error returning browse list: %s\n",
4866 for (i = 0; i < share_list.num_shares; i++) {
4867 char *netname = share_list.shares[i];
4869 if (netname[strlen(netname)-1] == '$')
4872 d_printf("%s\n", netname);
4874 show_userlist(pipe_hnd, mem_ctx, netname,
4875 num_tokens, tokens);
4878 for (i=0; i<num_tokens; i++) {
4879 free_user_token(&tokens[i].token);
4882 SAFE_FREE(share_list.shares);
4884 return NT_STATUS_OK;
4887 static int rpc_share_allowedusers(struct net_context *c, int argc,
4892 if (c->display_usage) {
4894 "net rpc share allowedusers\n"
4897 _("List allowed users"));
4901 result = run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
4902 rpc_aliaslist_internals,
4907 result = run_rpc_command(c, NULL, &ndr_table_lsarpc.syntax_id, 0,
4913 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4914 rpc_share_allowedusers_internals,
4918 int net_usersidlist(struct net_context *c, int argc, const char **argv)
4921 struct user_token *tokens = NULL;
4925 net_usersidlist_usage(c, argc, argv);
4929 if (!get_user_tokens(c, &num_tokens, &tokens)) {
4930 DEBUG(0, ("Could not get the user/sid list\n"));
4934 for (i=0; i<num_tokens; i++) {
4935 dump_user_token(&tokens[i]);
4936 free_user_token(&tokens[i].token);
4943 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
4945 d_printf(_("net usersidlist\n"
4946 "\tprints out a list of all users the running winbind knows\n"
4947 "\tabout, together with all their SIDs. This is used as\n"
4948 "\tinput to the 'net rpc share allowedusers' command.\n\n"));
4950 net_common_flags_usage(c, argc, argv);
4955 * 'net rpc share' entrypoint.
4956 * @param argc Standard main() style argc.
4957 * @param argv Standard main() style argv. Initial components are already
4961 int net_rpc_share(struct net_context *c, int argc, const char **argv)
4963 NET_API_STATUS status;
4965 struct functable func[] = {
4971 N_("net rpc share add\n"
4979 N_("net rpc share delete\n"
4984 rpc_share_allowedusers,
4986 N_("Modify allowed users"),
4987 N_("net rpc share allowedusers\n"
4988 " Modify allowed users")
4994 N_("Migrate share to local server"),
4995 N_("net rpc share migrate\n"
4996 " Migrate share to local server")
5003 N_("net rpc share list\n"
5006 {NULL, NULL, 0, NULL, NULL}
5009 status = libnetapi_net_init(&c->netapi_ctx);
5013 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5014 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5015 if (c->opt_kerberos) {
5016 libnetapi_set_use_kerberos(c->netapi_ctx);
5020 if (c->display_usage) {
5025 " Alias for net rpc share list\n"));
5026 net_display_usage_from_functable(func);
5030 return rpc_share_list(c, argc, argv);
5033 return net_run_function(c, argc, argv, "net rpc share", func);
5036 static NTSTATUS rpc_sh_share_list(struct net_context *c,
5037 TALLOC_CTX *mem_ctx,
5038 struct rpc_sh_ctx *ctx,
5039 struct rpc_pipe_client *pipe_hnd,
5040 int argc, const char **argv)
5043 return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
5046 static NTSTATUS rpc_sh_share_add(struct net_context *c,
5047 TALLOC_CTX *mem_ctx,
5048 struct rpc_sh_ctx *ctx,
5049 struct rpc_pipe_client *pipe_hnd,
5050 int argc, const char **argv)
5052 NET_API_STATUS status;
5053 uint32_t parm_err = 0;
5054 struct SHARE_INFO_2 i2;
5056 if ((argc < 2) || (argc > 3)) {
5057 d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
5059 return NT_STATUS_INVALID_PARAMETER;
5062 i2.shi2_netname = argv[0];
5063 i2.shi2_type = STYPE_DISKTREE;
5064 i2.shi2_remark = (argc == 3) ? argv[2] : "";
5065 i2.shi2_permissions = 0;
5066 i2.shi2_max_uses = 0;
5067 i2.shi2_current_uses = 0;
5068 i2.shi2_path = argv[1];
5069 i2.shi2_passwd = NULL;
5071 status = NetShareAdd(pipe_hnd->desthost,
5076 return werror_to_ntstatus(W_ERROR(status));
5079 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
5080 TALLOC_CTX *mem_ctx,
5081 struct rpc_sh_ctx *ctx,
5082 struct rpc_pipe_client *pipe_hnd,
5083 int argc, const char **argv)
5086 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5087 return NT_STATUS_INVALID_PARAMETER;
5090 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
5093 static NTSTATUS rpc_sh_share_info(struct net_context *c,
5094 TALLOC_CTX *mem_ctx,
5095 struct rpc_sh_ctx *ctx,
5096 struct rpc_pipe_client *pipe_hnd,
5097 int argc, const char **argv)
5099 union srvsvc_NetShareInfo info;
5102 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5105 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
5106 return NT_STATUS_INVALID_PARAMETER;
5109 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
5115 if (!NT_STATUS_IS_OK(status)) {
5116 result = ntstatus_to_werror(status);
5119 if (!W_ERROR_IS_OK(result)) {
5123 d_printf(_("Name: %s\n"), info.info2->name);
5124 d_printf(_("Comment: %s\n"), info.info2->comment);
5125 d_printf(_("Path: %s\n"), info.info2->path);
5126 d_printf(_("Password: %s\n"), info.info2->password);
5129 return werror_to_ntstatus(result);
5132 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
5133 struct rpc_sh_ctx *ctx)
5135 static struct rpc_sh_cmd cmds[] = {
5137 { "list", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_list,
5138 N_("List available shares") },
5140 { "add", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_add,
5141 N_("Add a share") },
5143 { "delete", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_delete,
5144 N_("Delete a share") },
5146 { "info", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_info,
5147 N_("Get information about a share") },
5149 { NULL, NULL, 0, NULL, NULL }
5155 /****************************************************************************/
5157 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
5159 return net_file_usage(c, argc, argv);
5163 * Close a file on a remote RPC server.
5165 * @param argc Standard main() style argc.
5166 * @param argv Standard main() style argv. Initial components are already
5169 * @return A shell status integer (0 for success).
5171 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5173 if (argc < 1 || c->display_usage) {
5174 return rpc_file_usage(c, argc, argv);
5177 return NetFileClose(c->opt_host, atoi(argv[0]));
5181 * Formatted print of open file info
5183 * @param r struct FILE_INFO_3 contents
5186 static void display_file_info_3(struct FILE_INFO_3 *r)
5188 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5189 r->fi3_id, r->fi3_username, r->fi3_permissions,
5190 r->fi3_num_locks, r->fi3_pathname);
5194 * List files for a user on a remote RPC server.
5196 * @param argc Standard main() style argc.
5197 * @param argv Standard main() style argv. Initial components are already
5200 * @return A shell status integer (0 for success)..
5203 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5205 NET_API_STATUS status;
5206 uint32 preferred_len = 0xffffffff, i;
5207 const char *username=NULL;
5208 uint32_t total_entries = 0;
5209 uint32_t entries_read = 0;
5210 uint32_t resume_handle = 0;
5211 struct FILE_INFO_3 *i3 = NULL;
5213 if (c->display_usage) {
5214 return rpc_file_usage(c, argc, argv);
5217 /* if argc > 0, must be user command */
5219 username = smb_xstrdup(argv[0]);
5222 status = NetFileEnum(c->opt_host,
5226 (uint8_t **)(void *)&i3,
5236 /* Display results */
5239 "\nEnumerating open files on remote server:\n\n"
5240 "\nFileId Opened by Perms Locks Path"
5241 "\n------ --------- ----- ----- ---- \n"));
5242 for (i = 0; i < entries_read; i++) {
5243 display_file_info_3(&i3[i]);
5250 * 'net rpc file' entrypoint.
5251 * @param argc Standard main() style argc.
5252 * @param argv Standard main() style argv. Initial components are already
5256 int net_rpc_file(struct net_context *c, int argc, const char **argv)
5258 NET_API_STATUS status;
5260 struct functable func[] = {
5265 N_("Close opened file"),
5266 N_("net rpc file close\n"
5267 " Close opened file")
5273 N_("List files opened by user"),
5274 N_("net rpc file user\n"
5275 " List files opened by user")
5282 N_("Display information about opened file"),
5283 N_("net rpc file info\n"
5284 " Display information about opened file")
5287 {NULL, NULL, 0, NULL, NULL}
5290 status = libnetapi_net_init(&c->netapi_ctx);
5294 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5295 libnetapi_set_password(c->netapi_ctx, c->opt_password);
5296 if (c->opt_kerberos) {
5297 libnetapi_set_use_kerberos(c->netapi_ctx);
5301 if (c->display_usage) {
5302 d_printf(_("Usage:\n"));
5303 d_printf(_("net rpc file\n"
5304 " List opened files\n"));
5305 net_display_usage_from_functable(func);
5309 return rpc_file_user(c, argc, argv);
5312 return net_run_function(c, argc, argv, "net rpc file", func);
5316 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5318 * All parameters are provided by the run_rpc_command function, except for
5319 * argc, argv which are passed through.
5321 * @param c A net_context structure.
5322 * @param domain_sid The domain sid acquired from the remote server.
5323 * @param cli A cli_state connected to the server.
5324 * @param mem_ctx Talloc context, destroyed on completion of the function.
5325 * @param argc Standard main() style argc.
5326 * @param argv Standard main() style argv. Initial components are already
5329 * @return Normal NTSTATUS return.
5332 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5333 const struct dom_sid *domain_sid,
5334 const char *domain_name,
5335 struct cli_state *cli,
5336 struct rpc_pipe_client *pipe_hnd,
5337 TALLOC_CTX *mem_ctx,
5341 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5343 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5345 status = dcerpc_initshutdown_Abort(b, mem_ctx, NULL, &result);
5346 if (!NT_STATUS_IS_OK(status)) {
5349 if (W_ERROR_IS_OK(result)) {
5350 d_printf(_("\nShutdown successfully aborted\n"));
5351 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5353 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5355 return werror_to_ntstatus(result);
5359 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5361 * All parameters are provided by the run_rpc_command function, except for
5362 * argc, argv which are passed through.
5364 * @param c A net_context structure.
5365 * @param domain_sid The domain sid acquired from the remote server.
5366 * @param cli A cli_state connected to the server.
5367 * @param mem_ctx Talloc context, destroyed on completion of the function.
5368 * @param argc Standard main() style argc.
5369 * @param argv Standard main() style argv. Initial components are already
5372 * @return Normal NTSTATUS return.
5375 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5376 const struct dom_sid *domain_sid,
5377 const char *domain_name,
5378 struct cli_state *cli,
5379 struct rpc_pipe_client *pipe_hnd,
5380 TALLOC_CTX *mem_ctx,
5384 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5386 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5388 result = dcerpc_winreg_AbortSystemShutdown(b, mem_ctx, NULL, &werr);
5390 if (!NT_STATUS_IS_OK(result)) {
5391 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5394 if (W_ERROR_IS_OK(werr)) {
5395 d_printf(_("\nShutdown successfully aborted\n"));
5396 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5398 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5400 return werror_to_ntstatus(werr);
5404 * ABORT the shutdown of a remote RPC server.
5406 * @param argc Standard main() style argc.
5407 * @param argv Standard main() style argv. Initial components are already
5410 * @return A shell status integer (0 for success).
5413 static int rpc_shutdown_abort(struct net_context *c, int argc,
5418 if (c->display_usage) {
5420 "net rpc abortshutdown\n"
5423 _("Abort a scheduled shutdown"));
5427 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5428 rpc_shutdown_abort_internals, argc, argv);
5433 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5435 return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5436 rpc_reg_shutdown_abort_internals,
5441 * Shut down a remote RPC Server via initshutdown pipe.
5443 * All parameters are provided by the run_rpc_command function, except for
5444 * argc, argv which are passed through.
5446 * @param c A net_context structure.
5447 * @param domain_sid The domain sid acquired from the remote server.
5448 * @param cli A cli_state connected to the server.
5449 * @param mem_ctx Talloc context, destroyed on completion of the function.
5450 * @param argc Standard main() style argc.
5451 * @param argv Standard main() style argv. Initial components are already
5454 * @return Normal NTSTATUS return.
5457 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5458 const struct dom_sid *domain_sid,
5459 const char *domain_name,
5460 struct cli_state *cli,
5461 struct rpc_pipe_client *pipe_hnd,
5462 TALLOC_CTX *mem_ctx,
5466 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5468 const char *msg = N_("This machine will be shutdown shortly");
5469 uint32 timeout = 20;
5470 struct lsa_StringLarge msg_string;
5471 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5473 if (c->opt_comment) {
5474 msg = c->opt_comment;
5476 if (c->opt_timeout) {
5477 timeout = c->opt_timeout;
5480 msg_string.string = msg;
5482 /* create an entry */
5483 status = dcerpc_initshutdown_Init(b, mem_ctx, NULL,
5484 &msg_string, timeout, c->opt_force, c->opt_reboot,
5486 if (!NT_STATUS_IS_OK(status)) {
5489 if (W_ERROR_IS_OK(result)) {
5490 d_printf(_("\nShutdown of remote machine succeeded\n"));
5491 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5493 DEBUG(1,("Shutdown of remote machine failed!\n"));
5495 return werror_to_ntstatus(result);
5499 * Shut down a remote RPC Server via winreg pipe.
5501 * All parameters are provided by the run_rpc_command function, except for
5502 * argc, argv which are passed through.
5504 * @param c A net_context structure.
5505 * @param domain_sid The domain sid acquired from the remote server.
5506 * @param cli A cli_state connected to the server.
5507 * @param mem_ctx Talloc context, destroyed on completion of the function.
5508 * @param argc Standard main() style argc.
5509 * @param argv Standard main() style argv. Initial components are already
5512 * @return Normal NTSTATUS return.
5515 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5516 const struct dom_sid *domain_sid,
5517 const char *domain_name,
5518 struct cli_state *cli,
5519 struct rpc_pipe_client *pipe_hnd,
5520 TALLOC_CTX *mem_ctx,
5524 const char *msg = N_("This machine will be shutdown shortly");
5525 uint32 timeout = 20;
5526 struct lsa_StringLarge msg_string;
5529 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5531 if (c->opt_comment) {
5532 msg = c->opt_comment;
5534 msg_string.string = msg;
5536 if (c->opt_timeout) {
5537 timeout = c->opt_timeout;
5540 /* create an entry */
5541 result = dcerpc_winreg_InitiateSystemShutdown(b, mem_ctx, NULL,
5542 &msg_string, timeout, c->opt_force, c->opt_reboot,
5544 if (!NT_STATUS_IS_OK(result)) {
5545 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5549 if (W_ERROR_IS_OK(werr)) {
5550 d_printf(_("\nShutdown of remote machine succeeded\n"));
5552 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5553 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5554 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5556 d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5559 return werror_to_ntstatus(werr);
5563 * Shut down a remote RPC server.
5565 * @param argc Standard main() style argc.
5566 * @param argv Standard main() style argv. Initial components are already
5569 * @return A shell status integer (0 for success).
5572 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5576 if (c->display_usage) {
5578 "net rpc shutdown\n"
5581 _("Shut down a remote RPC server"));
5585 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5586 rpc_init_shutdown_internals, argc, argv);
5589 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5590 rc = run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5591 rpc_reg_shutdown_internals, argc, argv);
5597 /***************************************************************************
5598 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5599 ***************************************************************************/
5602 * Add interdomain trust account to the RPC server.
5603 * All parameters (except for argc and argv) are passed by run_rpc_command
5606 * @param c A net_context structure.
5607 * @param domain_sid The domain sid acquired from the server.
5608 * @param cli A cli_state connected to the server.
5609 * @param mem_ctx Talloc context, destroyed on completion of the function.
5610 * @param argc Standard main() style argc.
5611 * @param argv Standard main() style argv. Initial components are already
5614 * @return normal NTSTATUS return code.
5617 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
5618 const struct dom_sid *domain_sid,
5619 const char *domain_name,
5620 struct cli_state *cli,
5621 struct rpc_pipe_client *pipe_hnd,
5622 TALLOC_CTX *mem_ctx,
5626 struct policy_handle connect_pol, domain_pol, user_pol;
5627 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5629 struct lsa_String lsa_acct_name;
5631 uint32 acct_flags=0;
5633 uint32_t access_granted = 0;
5634 union samr_UserInfo info;
5635 unsigned int orig_timeout;
5640 _(" net rpc trustdom add <domain_name> "
5641 "<trust password>\n"));
5642 return NT_STATUS_INVALID_PARAMETER;
5646 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5649 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5650 return NT_STATUS_NO_MEMORY;
5653 strupper_m(acct_name);
5655 init_lsa_String(&lsa_acct_name, acct_name);
5657 /* Get samr policy handle */
5658 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5660 MAXIMUM_ALLOWED_ACCESS,
5662 if (!NT_STATUS_IS_OK(result)) {
5666 /* Get domain policy handle */
5667 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5669 MAXIMUM_ALLOWED_ACCESS,
5670 CONST_DISCARD(struct dom_sid2 *, domain_sid),
5672 if (!NT_STATUS_IS_OK(result)) {
5676 /* This call can take a long time - allow the server to time out.
5677 * 35 seconds should do it. */
5679 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5681 /* Create trusting domain's account */
5682 acb_info = ACB_NORMAL;
5683 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5684 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5685 SAMR_USER_ACCESS_SET_PASSWORD |
5686 SAMR_USER_ACCESS_GET_ATTRIBUTES |
5687 SAMR_USER_ACCESS_SET_ATTRIBUTES;
5689 result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5698 /* And restore our original timeout. */
5699 rpccli_set_timeout(pipe_hnd, orig_timeout);
5701 if (!NT_STATUS_IS_OK(result)) {
5702 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
5703 acct_name, nt_errstr(result));
5708 struct samr_CryptPassword crypt_pwd;
5710 ZERO_STRUCT(info.info23);
5712 init_samr_CryptPassword(argv[1],
5713 &cli->user_session_key,
5716 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
5717 SAMR_FIELD_NT_PASSWORD_PRESENT;
5718 info.info23.info.acct_flags = ACB_DOMTRUST;
5719 info.info23.password = crypt_pwd;
5721 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5726 if (!NT_STATUS_IS_OK(result)) {
5727 DEBUG(0,("Could not set trust account password: %s\n",
5728 nt_errstr(result)));
5734 SAFE_FREE(acct_name);
5739 * Create interdomain trust account for a remote domain.
5741 * @param argc Standard argc.
5742 * @param argv Standard argv without initial components.
5744 * @return Integer status (0 means success).
5747 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5749 if (argc > 0 && !c->display_usage) {
5750 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5751 rpc_trustdom_add_internals, argc, argv);
5755 _("net rpc trustdom add <domain_name> <trust "
5763 * Remove interdomain trust account from the RPC server.
5764 * All parameters (except for argc and argv) are passed by run_rpc_command
5767 * @param c A net_context structure.
5768 * @param domain_sid The domain sid acquired from the server.
5769 * @param cli A cli_state connected to the server.
5770 * @param mem_ctx Talloc context, destroyed on completion of the function.
5771 * @param argc Standard main() style argc.
5772 * @param argv Standard main() style argv. Initial components are already
5775 * @return normal NTSTATUS return code.
5778 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
5779 const struct dom_sid *domain_sid,
5780 const char *domain_name,
5781 struct cli_state *cli,
5782 struct rpc_pipe_client *pipe_hnd,
5783 TALLOC_CTX *mem_ctx,
5787 struct policy_handle connect_pol, domain_pol, user_pol;
5788 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5790 struct dom_sid trust_acct_sid;
5791 struct samr_Ids user_rids, name_types;
5792 struct lsa_String lsa_acct_name;
5797 _(" net rpc trustdom del <domain_name>\n"));
5798 return NT_STATUS_INVALID_PARAMETER;
5802 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5804 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5806 if (acct_name == NULL)
5807 return NT_STATUS_NO_MEMORY;
5809 strupper_m(acct_name);
5811 /* Get samr policy handle */
5812 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5814 MAXIMUM_ALLOWED_ACCESS,
5816 if (!NT_STATUS_IS_OK(result)) {
5820 /* Get domain policy handle */
5821 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5823 MAXIMUM_ALLOWED_ACCESS,
5824 CONST_DISCARD(struct dom_sid2 *, domain_sid),
5826 if (!NT_STATUS_IS_OK(result)) {
5830 init_lsa_String(&lsa_acct_name, acct_name);
5832 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5839 if (!NT_STATUS_IS_OK(result)) {
5840 d_printf(_("net rpc trustdom del: LookupNames on user %s "
5842 acct_name, nt_errstr(result) );
5846 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5848 MAXIMUM_ALLOWED_ACCESS,
5852 if (!NT_STATUS_IS_OK(result)) {
5853 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
5855 acct_name, nt_errstr(result) );
5859 /* append the rid to the domain sid */
5860 if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
5864 /* remove the sid */
5866 result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5869 if (!NT_STATUS_IS_OK(result)) {
5870 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
5871 " on user %s failed %s\n"),
5872 acct_name, nt_errstr(result) );
5878 result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5881 if (!NT_STATUS_IS_OK(result)) {
5882 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
5884 acct_name, nt_errstr(result) );
5888 if (!NT_STATUS_IS_OK(result)) {
5889 d_printf(_("Could not set trust account password: %s\n"),
5899 * Delete interdomain trust account for a remote domain.
5901 * @param argc Standard argc.
5902 * @param argv Standard argv without initial components.
5904 * @return Integer status (0 means success).
5907 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
5909 if (argc > 0 && !c->display_usage) {
5910 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5911 rpc_trustdom_del_internals, argc, argv);
5915 _("net rpc trustdom del <domain>\n"));
5920 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
5921 struct cli_state *cli,
5922 TALLOC_CTX *mem_ctx,
5923 const char *domain_name)
5925 char *dc_name = NULL;
5926 const char *buffer = NULL;
5927 struct rpc_pipe_client *netr;
5930 struct dcerpc_binding_handle *b;
5932 /* Use NetServerEnum2 */
5934 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
5936 return NT_STATUS_OK;
5939 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
5940 for domain %s\n", domain_name));
5942 /* Try netr_GetDcName */
5944 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
5946 if (!NT_STATUS_IS_OK(status)) {
5950 b = netr->binding_handle;
5952 status = dcerpc_netr_GetDcName(b, mem_ctx,
5959 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
5963 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
5964 for domain %s\n", domain_name));
5966 if (!NT_STATUS_IS_OK(status)) {
5970 return werror_to_ntstatus(result);
5974 * Establish trust relationship to a trusting domain.
5975 * Interdomain account must already be created on remote PDC.
5977 * @param c A net_context structure.
5978 * @param argc Standard argc.
5979 * @param argv Standard argv without initial components.
5981 * @return Integer status (0 means success).
5984 static int rpc_trustdom_establish(struct net_context *c, int argc,
5987 struct cli_state *cli = NULL;
5988 struct sockaddr_storage server_ss;
5989 struct rpc_pipe_client *pipe_hnd = NULL;
5990 struct policy_handle connect_hnd;
5991 TALLOC_CTX *mem_ctx;
5993 struct dom_sid *domain_sid;
5998 union lsa_PolicyInformation *info = NULL;
6001 * Connect to \\server\ipc$ as 'our domain' account with password
6004 if (argc != 1 || c->display_usage) {
6007 _("net rpc trustdom establish <domain_name>\n"));
6011 domain_name = smb_xstrdup(argv[0]);
6012 strupper_m(domain_name);
6014 /* account name used at first is our domain's name with '$' */
6015 if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
6018 strupper_m(acct_name);
6021 * opt_workgroup will be used by connection functions further,
6022 * hence it should be set to remote domain name instead of ours
6024 if (c->opt_workgroup) {
6025 c->opt_workgroup = smb_xstrdup(domain_name);
6028 c->opt_user_name = acct_name;
6030 /* find the domain controller */
6031 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
6032 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
6036 /* connect to ipc$ as username/password */
6037 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
6038 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
6040 /* Is it trusting domain account for sure ? */
6041 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
6042 nt_errstr(nt_status)));
6046 /* store who we connected to */
6048 saf_store( domain_name, pdc_name );
6051 * Connect to \\server\ipc$ again (this time anonymously)
6054 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
6057 if (NT_STATUS_IS_ERR(nt_status)) {
6058 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
6059 domain_name, nt_errstr(nt_status)));
6063 if (!(mem_ctx = talloc_init("establishing trust relationship to "
6064 "domain %s", domain_name))) {
6065 DEBUG(0, ("talloc_init() failed\n"));
6070 /* Make sure we're talking to a proper server */
6072 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
6073 if (!NT_STATUS_IS_OK(nt_status)) {
6075 talloc_destroy(mem_ctx);
6080 * Call LsaOpenPolicy and LsaQueryInfo
6083 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6085 if (!NT_STATUS_IS_OK(nt_status)) {
6086 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
6088 talloc_destroy(mem_ctx);
6092 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
6094 if (NT_STATUS_IS_ERR(nt_status)) {
6095 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6096 nt_errstr(nt_status)));
6098 talloc_destroy(mem_ctx);
6102 /* Querying info level 5 */
6104 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6106 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6108 if (NT_STATUS_IS_ERR(nt_status)) {
6109 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6110 nt_errstr(nt_status)));
6112 talloc_destroy(mem_ctx);
6116 domain_sid = info->account_domain.sid;
6118 /* There should be actually query info level 3 (following nt serv behaviour),
6119 but I still don't know if it's _really_ necessary */
6122 * Store the password in secrets db
6125 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6126 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6128 talloc_destroy(mem_ctx);
6133 * Close the pipes and clean up
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 close LSA pipe. Error was %s\n",
6139 nt_errstr(nt_status)));
6141 talloc_destroy(mem_ctx);
6147 talloc_destroy(mem_ctx);
6149 d_printf(_("Trust to domain %s established\n"), domain_name);
6154 * Revoke trust relationship to the remote domain.
6156 * @param c A net_context structure.
6157 * @param argc Standard argc.
6158 * @param argv Standard argv without initial components.
6160 * @return Integer status (0 means success).
6163 static int rpc_trustdom_revoke(struct net_context *c, int argc,
6169 if (argc < 1 || c->display_usage) {
6172 _("net rpc trustdom revoke <domain_name>\n"
6173 " Revoke trust relationship\n"
6174 " domain_name\tName of domain to revoke trust\n"));
6178 /* generate upper cased domain name */
6179 domain_name = smb_xstrdup(argv[0]);
6180 strupper_m(domain_name);
6182 /* delete password of the trust */
6183 if (!pdb_del_trusteddom_pw(domain_name)) {
6184 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6191 SAFE_FREE(domain_name);
6195 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6196 const struct dom_sid *domain_sid,
6197 const char *domain_name,
6198 struct cli_state *cli,
6199 struct rpc_pipe_client *pipe_hnd,
6200 TALLOC_CTX *mem_ctx,
6205 if (!sid_to_fstring(str_sid, domain_sid)) {
6206 return NT_STATUS_UNSUCCESSFUL;
6208 d_printf("%s\n", str_sid);
6209 return NT_STATUS_OK;
6212 static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
6216 /* convert sid into ascii string */
6217 sid_to_fstring(ascii_sid, dom_sid);
6219 d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
6222 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6223 TALLOC_CTX *mem_ctx,
6224 struct policy_handle *pol,
6225 struct dom_sid dom_sid,
6226 const char *trusted_dom_name)
6229 union lsa_TrustedDomainInfo *info = NULL;
6230 char *cleartextpwd = NULL;
6231 uint8_t session_key[16];
6232 DATA_BLOB session_key_blob;
6233 DATA_BLOB data = data_blob_null;
6235 nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
6238 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6240 if (NT_STATUS_IS_ERR(nt_status)) {
6241 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6242 nt_errstr(nt_status)));
6246 data = data_blob(info->password.password->data,
6247 info->password.password->length);
6249 if (!rpccli_get_pwd_hash(pipe_hnd, session_key)) {
6250 DEBUG(0, ("Could not retrieve password hash\n"));
6254 session_key_blob = data_blob_const(session_key, sizeof(session_key));
6255 cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key_blob);
6257 if (cleartextpwd == NULL) {
6258 DEBUG(0,("retrieved NULL password\n"));
6259 nt_status = NT_STATUS_UNSUCCESSFUL;
6263 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6264 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6265 nt_status = NT_STATUS_UNSUCCESSFUL;
6269 #ifdef DEBUG_PASSWORD
6270 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
6271 "password: [%s]\n", trusted_dom_name,
6272 sid_string_dbg(&dom_sid), cleartextpwd));
6276 SAFE_FREE(cleartextpwd);
6277 data_blob_free(&data);
6282 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6285 /* common variables */
6286 TALLOC_CTX* mem_ctx;
6287 struct cli_state *cli = NULL;
6288 struct rpc_pipe_client *pipe_hnd = NULL;
6290 const char *domain_name = NULL;
6291 struct dom_sid *queried_dom_sid;
6292 struct policy_handle connect_hnd;
6293 union lsa_PolicyInformation *info = NULL;
6295 /* trusted domains listing variables */
6296 unsigned int enum_ctx = 0;
6298 struct lsa_DomainList dom_list;
6301 if (c->display_usage) {
6303 "net rpc trustdom vampire\n"
6306 _("Vampire trust relationship from remote server"));
6311 * Listing trusted domains (stored in secrets.tdb, if local)
6314 mem_ctx = talloc_init("trust relationships vampire");
6317 * set domain and pdc name to local samba server (default)
6318 * or to remote one given in command line
6321 if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6322 domain_name = c->opt_workgroup;
6323 c->opt_target_workgroup = c->opt_workgroup;
6325 fstrcpy(pdc_name, global_myname());
6326 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6327 c->opt_target_workgroup = domain_name;
6330 /* open \PIPE\lsarpc and open policy handle */
6331 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6332 if (!NT_STATUS_IS_OK(nt_status)) {
6333 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6334 nt_errstr(nt_status)));
6335 talloc_destroy(mem_ctx);
6339 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6341 if (!NT_STATUS_IS_OK(nt_status)) {
6342 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6343 nt_errstr(nt_status) ));
6345 talloc_destroy(mem_ctx);
6349 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6351 if (NT_STATUS_IS_ERR(nt_status)) {
6352 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6353 nt_errstr(nt_status)));
6355 talloc_destroy(mem_ctx);
6359 /* query info level 5 to obtain sid of a domain being queried */
6360 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6362 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6365 if (NT_STATUS_IS_ERR(nt_status)) {
6366 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6367 nt_errstr(nt_status)));
6369 talloc_destroy(mem_ctx);
6373 queried_dom_sid = info->account_domain.sid;
6376 * Keep calling LsaEnumTrustdom over opened pipe until
6377 * the end of enumeration is reached
6380 d_printf(_("Vampire trusted domains:\n\n"));
6383 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6388 if (NT_STATUS_IS_ERR(nt_status)) {
6389 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6390 nt_errstr(nt_status)));
6392 talloc_destroy(mem_ctx);
6396 for (i = 0; i < dom_list.count; i++) {
6398 print_trusted_domain(dom_list.domains[i].sid,
6399 dom_list.domains[i].name.string);
6401 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
6402 *dom_list.domains[i].sid,
6403 dom_list.domains[i].name.string);
6404 if (!NT_STATUS_IS_OK(nt_status)) {
6406 talloc_destroy(mem_ctx);
6412 * in case of no trusted domains say something rather
6413 * than just display blank line
6415 if (!dom_list.count) d_printf(_("none\n"));
6417 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6419 /* close this connection before doing next one */
6420 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6421 if (NT_STATUS_IS_ERR(nt_status)) {
6422 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6423 nt_errstr(nt_status)));
6425 talloc_destroy(mem_ctx);
6429 /* close lsarpc pipe and connection to IPC$ */
6432 talloc_destroy(mem_ctx);
6436 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6438 /* common variables */
6439 TALLOC_CTX* mem_ctx;
6440 struct cli_state *cli = NULL, *remote_cli = NULL;
6441 struct rpc_pipe_client *pipe_hnd = NULL;
6443 const char *domain_name = NULL;
6444 struct dom_sid *queried_dom_sid;
6445 int ascii_dom_name_len;
6446 struct policy_handle connect_hnd;
6447 union lsa_PolicyInformation *info = NULL;
6449 /* trusted domains listing variables */
6450 unsigned int num_domains, enum_ctx = 0;
6452 struct lsa_DomainList dom_list;
6456 /* trusting domains listing variables */
6457 struct policy_handle domain_hnd;
6458 struct samr_SamArray *trusts = NULL;
6460 if (c->display_usage) {
6462 "net rpc trustdom list\n"
6465 _("List incoming and outgoing trust relationships"));
6470 * Listing trusted domains (stored in secrets.tdb, if local)
6473 mem_ctx = talloc_init("trust relationships listing");
6476 * set domain and pdc name to local samba server (default)
6477 * or to remote one given in command line
6480 if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6481 domain_name = c->opt_workgroup;
6482 c->opt_target_workgroup = c->opt_workgroup;
6484 fstrcpy(pdc_name, global_myname());
6485 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6486 c->opt_target_workgroup = domain_name;
6489 /* open \PIPE\lsarpc and open policy handle */
6490 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6491 if (!NT_STATUS_IS_OK(nt_status)) {
6492 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6493 nt_errstr(nt_status)));
6494 talloc_destroy(mem_ctx);
6498 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6500 if (!NT_STATUS_IS_OK(nt_status)) {
6501 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6502 nt_errstr(nt_status) ));
6504 talloc_destroy(mem_ctx);
6508 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6510 if (NT_STATUS_IS_ERR(nt_status)) {
6511 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6512 nt_errstr(nt_status)));
6514 talloc_destroy(mem_ctx);
6518 /* query info level 5 to obtain sid of a domain being queried */
6519 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6521 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6524 if (NT_STATUS_IS_ERR(nt_status)) {
6525 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6526 nt_errstr(nt_status)));
6528 talloc_destroy(mem_ctx);
6532 queried_dom_sid = info->account_domain.sid;
6535 * Keep calling LsaEnumTrustdom over opened pipe until
6536 * the end of enumeration is reached
6539 d_printf(_("Trusted domains list:\n\n"));
6541 found_domain = false;
6544 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6549 if (NT_STATUS_IS_ERR(nt_status)) {
6550 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6551 nt_errstr(nt_status)));
6553 talloc_destroy(mem_ctx);
6557 for (i = 0; i < dom_list.count; i++) {
6558 print_trusted_domain(dom_list.domains[i].sid,
6559 dom_list.domains[i].name.string);
6560 found_domain = true;
6564 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6567 * in case of no trusted domains say something rather
6568 * than just display blank line
6570 if (!found_domain) {
6571 d_printf(_("none\n"));
6574 /* close this connection before doing next one */
6575 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6576 if (NT_STATUS_IS_ERR(nt_status)) {
6577 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6578 nt_errstr(nt_status)));
6580 talloc_destroy(mem_ctx);
6584 TALLOC_FREE(pipe_hnd);
6587 * Listing trusting domains (stored in passdb backend, if local)
6590 d_printf(_("\nTrusting domains list:\n\n"));
6593 * Open \PIPE\samr and get needed policy handles
6595 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6597 if (!NT_STATUS_IS_OK(nt_status)) {
6598 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6600 talloc_destroy(mem_ctx);
6605 nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6607 SAMR_ACCESS_LOOKUP_DOMAIN,
6609 if (!NT_STATUS_IS_OK(nt_status)) {
6610 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6611 nt_errstr(nt_status)));
6613 talloc_destroy(mem_ctx);
6617 /* SamrOpenDomain - we have to open domain policy handle in order to be
6618 able to enumerate accounts*/
6619 nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6621 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6624 if (!NT_STATUS_IS_OK(nt_status)) {
6625 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6626 nt_errstr(nt_status)));
6628 talloc_destroy(mem_ctx);
6633 * perform actual enumeration
6636 found_domain = false;
6638 enum_ctx = 0; /* reset enumeration context from last enumeration */
6641 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6648 if (NT_STATUS_IS_ERR(nt_status)) {
6649 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6650 nt_errstr(nt_status)));
6652 talloc_destroy(mem_ctx);
6656 for (i = 0; i < num_domains; i++) {
6658 char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6660 found_domain = true;
6663 * get each single domain's sid (do we _really_ need this ?):
6664 * 1) connect to domain's pdc
6665 * 2) query the pdc for domain's sid
6668 /* get rid of '$' tail */
6669 ascii_dom_name_len = strlen(str);
6670 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6671 str[ascii_dom_name_len - 1] = '\0';
6673 /* set opt_* variables to remote domain */
6675 c->opt_workgroup = talloc_strdup(mem_ctx, str);
6676 c->opt_target_workgroup = c->opt_workgroup;
6678 d_printf("%-20s", str);
6680 /* connect to remote domain controller */
6681 nt_status = net_make_ipc_connection(c,
6682 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6684 if (NT_STATUS_IS_OK(nt_status)) {
6685 /* query for domain's sid */
6686 if (run_rpc_command(
6688 &ndr_table_lsarpc.syntax_id, 0,
6689 rpc_query_domain_sid, argc,
6691 d_printf(_("strange - couldn't get domain's sid\n"));
6693 cli_shutdown(remote_cli);
6696 d_fprintf(stderr, _("domain controller is not "
6697 "responding: %s\n"),
6698 nt_errstr(nt_status));
6699 d_printf(_("couldn't get domain's sid\n"));
6703 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6705 if (!found_domain) {
6709 /* close opened samr and domain policy handles */
6710 nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6711 if (!NT_STATUS_IS_OK(nt_status)) {
6712 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6715 nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6716 if (!NT_STATUS_IS_OK(nt_status)) {
6717 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6720 /* close samr pipe and connection to IPC$ */
6723 talloc_destroy(mem_ctx);
6728 * Entrypoint for 'net rpc trustdom' code.
6730 * @param argc Standard argc.
6731 * @param argv Standard argv without initial components.
6733 * @return Integer status (0 means success).
6736 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
6738 struct functable func[] = {
6743 N_("Add trusting domain's account"),
6744 N_("net rpc trustdom add\n"
6745 " Add trusting domain's account")
6751 N_("Remove trusting domain's account"),
6752 N_("net rpc trustdom del\n"
6753 " Remove trusting domain's account")
6757 rpc_trustdom_establish,
6759 N_("Establish outgoing trust relationship"),
6760 N_("net rpc trustdom establish\n"
6761 " Establish outgoing trust relationship")
6765 rpc_trustdom_revoke,
6767 N_("Revoke outgoing trust relationship"),
6768 N_("net rpc trustdom revoke\n"
6769 " Revoke outgoing trust relationship")
6775 N_("List in- and outgoing domain trusts"),
6776 N_("net rpc trustdom list\n"
6777 " List in- and outgoing domain trusts")
6781 rpc_trustdom_vampire,
6783 N_("Vampire trusts from remote server"),
6784 N_("net rpc trustdom vampire\n"
6785 " Vampire trusts from remote server")
6787 {NULL, NULL, 0, NULL, NULL}
6790 return net_run_function(c, argc, argv, "net rpc trustdom", func);
6794 * Check if a server will take rpc commands
6795 * @param flags Type of server to connect to (PDC, DMB, localhost)
6796 * if the host is not explicitly specified
6797 * @return bool (true means rpc supported)
6799 bool net_rpc_check(struct net_context *c, unsigned flags)
6801 struct cli_state *cli;
6803 struct sockaddr_storage server_ss;
6804 char *server_name = NULL;
6807 /* flags (i.e. server type) may depend on command */
6808 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
6811 if ((cli = cli_initialise()) == NULL) {
6815 status = cli_connect(cli, server_name, &server_ss);
6816 if (!NT_STATUS_IS_OK(status))
6818 if (!attempt_netbios_session_request(&cli, global_myname(),
6819 server_name, &server_ss))
6821 status = cli_negprot(cli);
6822 if (!NT_STATUS_IS_OK(status))
6824 if (cli->protocol < PROTOCOL_NT1)
6833 /* dump sam database via samsync rpc calls */
6834 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
6835 if (c->display_usage) {
6840 _("Dump remote SAM database"));
6844 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6845 NET_FLAGS_ANONYMOUS,
6846 rpc_samdump_internals, argc, argv);
6849 /* syncronise sam database via samsync rpc calls */
6850 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
6852 struct functable func[] = {
6857 N_("Dump remote SAM database to ldif"),
6858 N_("net rpc vampire ldif\n"
6859 " Dump remote SAM database to LDIF file or "
6866 N_("Dump remote SAM database to Kerberos Keytab"),
6867 N_("net rpc vampire keytab\n"
6868 " Dump remote SAM database to Kerberos keytab "
6875 N_("Dump remote SAM database to passdb"),
6876 N_("net rpc vampire passdb\n"
6877 " Dump remote SAM database to passdb")
6880 {NULL, NULL, 0, NULL, NULL}
6884 if (c->display_usage) {
6889 _("Vampire remote SAM database"));
6893 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6894 NET_FLAGS_ANONYMOUS,
6895 rpc_vampire_internals,
6899 return net_run_function(c, argc, argv, "net rpc vampire", func);
6903 * Migrate everything from a print server.
6905 * @param c A net_context structure.
6906 * @param argc Standard main() style argc.
6907 * @param argv Standard main() style argv. Initial components are already
6910 * @return A shell status integer (0 for success).
6912 * The order is important !
6913 * To successfully add drivers the print queues have to exist !
6914 * Applying ACLs should be the last step, because you're easily locked out.
6917 static int rpc_printer_migrate_all(struct net_context *c, int argc,
6922 if (c->display_usage) {
6924 "net rpc printer migrate all\n"
6927 _("Migrate everything from a print server"));
6932 d_printf(_("no server to migrate\n"));
6936 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6937 rpc_printer_migrate_printers_internals, argc,
6942 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6943 rpc_printer_migrate_drivers_internals, argc,
6948 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6949 rpc_printer_migrate_forms_internals, argc, argv);
6953 ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6954 rpc_printer_migrate_settings_internals, argc,
6959 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6960 rpc_printer_migrate_security_internals, argc,
6966 * Migrate print drivers from a print server.
6968 * @param c A net_context structure.
6969 * @param argc Standard main() style argc.
6970 * @param argv Standard main() style argv. Initial components are already
6973 * @return A shell status integer (0 for success).
6975 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
6978 if (c->display_usage) {
6980 "net rpc printer migrate drivers\n"
6983 _("Migrate print-drivers from a print-server"));
6988 d_printf(_("no server to migrate\n"));
6992 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6993 rpc_printer_migrate_drivers_internals,
6998 * Migrate print-forms from a print-server.
7000 * @param c A net_context structure.
7001 * @param argc Standard main() style argc.
7002 * @param argv Standard main() style argv. Initial components are already
7005 * @return A shell status integer (0 for success).
7007 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
7010 if (c->display_usage) {
7012 "net rpc printer migrate forms\n"
7015 _("Migrate print-forms from a print-server"));
7020 d_printf(_("no server to migrate\n"));
7024 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7025 rpc_printer_migrate_forms_internals,
7030 * Migrate printers from a print-server.
7032 * @param c A net_context structure.
7033 * @param argc Standard main() style argc.
7034 * @param argv Standard main() style argv. Initial components are already
7037 * @return A shell status integer (0 for success).
7039 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
7042 if (c->display_usage) {
7044 "net rpc printer migrate printers\n"
7047 _("Migrate printers from a print-server"));
7052 d_printf(_("no server to migrate\n"));
7056 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7057 rpc_printer_migrate_printers_internals,
7062 * Migrate printer-ACLs from a print-server
7064 * @param c A net_context structure.
7065 * @param argc Standard main() style argc.
7066 * @param argv Standard main() style argv. Initial components are already
7069 * @return A shell status integer (0 for success).
7071 static int rpc_printer_migrate_security(struct net_context *c, int argc,
7074 if (c->display_usage) {
7076 "net rpc printer migrate security\n"
7079 _("Migrate printer-ACLs from a print-server"));
7084 d_printf(_("no server to migrate\n"));
7088 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7089 rpc_printer_migrate_security_internals,
7094 * Migrate printer-settings from a print-server.
7096 * @param c A net_context structure.
7097 * @param argc Standard main() style argc.
7098 * @param argv Standard main() style argv. Initial components are already
7101 * @return A shell status integer (0 for success).
7103 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
7106 if (c->display_usage) {
7108 "net rpc printer migrate settings\n"
7111 _("Migrate printer-settings from a "
7117 d_printf(_("no server to migrate\n"));
7121 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7122 rpc_printer_migrate_settings_internals,
7127 * 'net rpc printer' entrypoint.
7129 * @param c A net_context structure.
7130 * @param argc Standard main() style argc.
7131 * @param argv Standard main() style argv. Initial components are already
7135 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
7138 /* ouch: when addriver and setdriver are called from within
7139 rpc_printer_migrate_drivers_internals, the printer-queue already
7142 struct functable func[] = {
7145 rpc_printer_migrate_all,
7147 N_("Migrate all from remote to local print server"),
7148 N_("net rpc printer migrate all\n"
7149 " Migrate all from remote to local print server")
7153 rpc_printer_migrate_drivers,
7155 N_("Migrate drivers to local server"),
7156 N_("net rpc printer migrate drivers\n"
7157 " Migrate drivers to local server")
7161 rpc_printer_migrate_forms,
7163 N_("Migrate froms to local server"),
7164 N_("net rpc printer migrate forms\n"
7165 " Migrate froms to local server")
7169 rpc_printer_migrate_printers,
7171 N_("Migrate printers to local server"),
7172 N_("net rpc printer migrate printers\n"
7173 " Migrate printers to local server")
7177 rpc_printer_migrate_security,
7179 N_("Mirgate printer ACLs to local server"),
7180 N_("net rpc printer migrate security\n"
7181 " Mirgate printer ACLs to local server")
7185 rpc_printer_migrate_settings,
7187 N_("Migrate printer settings to local server"),
7188 N_("net rpc printer migrate settings\n"
7189 " Migrate printer settings to local server")
7191 {NULL, NULL, 0, NULL, NULL}
7194 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7199 * List printers on a remote RPC server.
7201 * @param c A net_context structure.
7202 * @param argc Standard main() style argc.
7203 * @param argv Standard main() style argv. Initial components are already
7206 * @return A shell status integer (0 for success).
7208 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7210 if (c->display_usage) {
7212 "net rpc printer list\n"
7215 _("List printers on a remote RPC server"));
7219 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7220 rpc_printer_list_internals,
7225 * List printer-drivers on a remote RPC server.
7227 * @param c A net_context structure.
7228 * @param argc Standard main() style argc.
7229 * @param argv Standard main() style argv. Initial components are already
7232 * @return A shell status integer (0 for success).
7234 static int rpc_printer_driver_list(struct net_context *c, int argc,
7237 if (c->display_usage) {
7239 "net rpc printer driver\n"
7242 _("List printer-drivers on a remote RPC server"));
7246 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7247 rpc_printer_driver_list_internals,
7252 * Publish printer in ADS via MSRPC.
7254 * @param c A net_context structure.
7255 * @param argc Standard main() style argc.
7256 * @param argv Standard main() style argv. Initial components are already
7259 * @return A shell status integer (0 for success).
7261 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7264 if (c->display_usage) {
7266 "net rpc printer publish publish\n"
7269 _("Publish printer in ADS via MSRPC"));
7273 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7274 rpc_printer_publish_publish_internals,
7279 * Update printer in ADS via MSRPC.
7281 * @param c A net_context structure.
7282 * @param argc Standard main() style argc.
7283 * @param argv Standard main() style argv. Initial components are already
7286 * @return A shell status integer (0 for success).
7288 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7290 if (c->display_usage) {
7292 "net rpc printer publish update\n"
7295 _("Update printer in ADS via MSRPC"));
7299 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7300 rpc_printer_publish_update_internals,
7305 * UnPublish printer in ADS via MSRPC.
7307 * @param c A net_context structure.
7308 * @param argc Standard main() style argc.
7309 * @param argv Standard main() style argv. Initial components are already
7312 * @return A shell status integer (0 for success).
7314 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7317 if (c->display_usage) {
7319 "net rpc printer publish unpublish\n"
7322 _("UnPublish printer in ADS via MSRPC"));
7326 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7327 rpc_printer_publish_unpublish_internals,
7332 * List published printers via MSRPC.
7334 * @param c A net_context structure.
7335 * @param argc Standard main() style argc.
7336 * @param argv Standard main() style argv. Initial components are already
7339 * @return A shell status integer (0 for success).
7341 static int rpc_printer_publish_list(struct net_context *c, int argc,
7344 if (c->display_usage) {
7346 "net rpc printer publish list\n"
7349 _("List published printers via MSRPC"));
7353 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7354 rpc_printer_publish_list_internals,
7360 * Publish printer in ADS.
7362 * @param c A net_context structure.
7363 * @param argc Standard main() style argc.
7364 * @param argv Standard main() style argv. Initial components are already
7367 * @return A shell status integer (0 for success).
7369 static int rpc_printer_publish(struct net_context *c, int argc,
7373 struct functable func[] = {
7376 rpc_printer_publish_publish,
7378 N_("Publish printer in AD"),
7379 N_("net rpc printer publish publish\n"
7380 " Publish printer in AD")
7384 rpc_printer_publish_update,
7386 N_("Update printer in AD"),
7387 N_("net rpc printer publish update\n"
7388 " Update printer in AD")
7392 rpc_printer_publish_unpublish,
7394 N_("Unpublish printer"),
7395 N_("net rpc printer publish unpublish\n"
7396 " Unpublish printer")
7400 rpc_printer_publish_list,
7402 N_("List published printers"),
7403 N_("net rpc printer publish list\n"
7404 " List published printers")
7406 {NULL, NULL, 0, NULL, NULL}
7410 if (c->display_usage) {
7411 d_printf(_("Usage:\n"));
7412 d_printf(_("net rpc printer publish\n"
7413 " List published printers\n"
7414 " Alias of net rpc printer publish "
7416 net_display_usage_from_functable(func);
7419 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7420 rpc_printer_publish_list_internals,
7424 return net_run_function(c, argc, argv, "net rpc printer publish",func);
7430 * Display rpc printer help page.
7432 * @param c A net_context structure.
7433 * @param argc Standard main() style argc.
7434 * @param argv Standard main() style argv. Initial components are already
7437 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
7439 d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
7440 "\tlists all printers on print-server\n\n"));
7441 d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
7442 "\tlists all printer-drivers on print-server\n\n"));
7443 d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
7444 "\tpublishes printer settings in Active Directory\n"
7445 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
7446 d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
7447 "\n\tmigrates printers from remote to local server\n\n"));
7448 d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
7449 "\n\tmigrates printer-settings from remote to local server\n\n"));
7450 d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
7451 "\n\tmigrates printer-drivers from remote to local server\n\n"));
7452 d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
7453 "\n\tmigrates printer-forms from remote to local server\n\n"));
7454 d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
7455 "\n\tmigrates printer-ACLs from remote to local server\n\n"));
7456 d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
7457 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
7458 "\tremote to local print-server\n\n"));
7459 net_common_methods_usage(c, argc, argv);
7460 net_common_flags_usage(c, argc, argv);
7462 "\t-v or --verbose\t\t\tgive verbose output\n"
7463 "\t --destination\t\tmigration target server (default: localhost)\n"));
7469 * 'net rpc printer' entrypoint.
7471 * @param c A net_context structure.
7472 * @param argc Standard main() style argc.
7473 * @param argv Standard main() style argv. Initial components are already
7476 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7478 struct functable func[] = {
7483 N_("List all printers on print server"),
7484 N_("net rpc printer list\n"
7485 " List all printers on print server")
7489 rpc_printer_migrate,
7491 N_("Migrate printer to local server"),
7492 N_("net rpc printer migrate\n"
7493 " Migrate printer to local server")
7497 rpc_printer_driver_list,
7499 N_("List printer drivers"),
7500 N_("net rpc printer driver\n"
7501 " List printer drivers")
7505 rpc_printer_publish,
7507 N_("Publish printer in AD"),
7508 N_("net rpc printer publish\n"
7509 " Publish printer in AD")
7511 {NULL, NULL, 0, NULL, NULL}
7515 if (c->display_usage) {
7516 d_printf(_("Usage:\n"));
7517 d_printf(_("net rpc printer\n"
7518 " List printers\n"));
7519 net_display_usage_from_functable(func);
7522 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7523 rpc_printer_list_internals,
7527 return net_run_function(c, argc, argv, "net rpc printer", func);
7531 * 'net rpc' entrypoint.
7533 * @param c A net_context structure.
7534 * @param argc Standard main() style argc.
7535 * @param argv Standard main() style argv. Initial components are already
7539 int net_rpc(struct net_context *c, int argc, const char **argv)
7541 NET_API_STATUS status;
7543 struct functable func[] = {
7548 N_("Modify global audit settings"),
7549 N_("net rpc audit\n"
7550 " Modify global audit settings")
7556 N_("Show basic info about a domain"),
7558 " Show basic info about a domain")
7564 N_("Join a domain"),
7572 N_("Join a domain created in server manager"),
7573 N_("net rpc oldjoin\n"
7574 " Join a domain created in server manager")
7580 N_("Test that a join is valid"),
7581 N_("net rpc testjoin\n"
7582 " Test that a join is valid")
7588 N_("List/modify users"),
7590 " List/modify users")
7596 N_("Change a user password"),
7597 N_("net rpc password\n"
7598 " Change a user password\n"
7599 " Alias for net rpc user password")
7605 N_("List/modify groups"),
7606 N_("net rpc group\n"
7607 " List/modify groups")
7613 N_("List/modify shares"),
7614 N_("net rpc share\n"
7615 " List/modify shares")
7621 N_("List open files"),
7629 N_("List/modify printers"),
7630 N_("net rpc printer\n"
7631 " List/modify printers")
7635 net_rpc_changetrustpw,
7637 N_("Change trust account password"),
7638 N_("net rpc changetrustpw\n"
7639 " Change trust account password")
7645 N_("Modify domain trusts"),
7646 N_("net rpc trustdom\n"
7647 " Modify domain trusts")
7653 N_("Abort a remote shutdown"),
7654 N_("net rpc abortshutdown\n"
7655 " Abort a remote shutdown")
7661 N_("Shutdown a remote server"),
7662 N_("net rpc shutdown\n"
7663 " Shutdown a remote server")
7669 N_("Dump SAM data of remote NT PDC"),
7670 N_("net rpc samdump\n"
7671 " Dump SAM data of remote NT PDC")
7677 N_("Sync a remote NT PDC's data into local passdb"),
7678 N_("net rpc vampire\n"
7679 " Sync a remote NT PDC's data into local passdb")
7685 N_("Fetch the domain sid into local secrets.tdb"),
7686 N_("net rpc getsid\n"
7687 " Fetch the domain sid into local secrets.tdb")
7693 N_("Manage privileges assigned to SID"),
7694 N_("net rpc rights\n"
7695 " Manage privileges assigned to SID")
7701 N_("Start/stop/query remote services"),
7702 N_("net rpc service\n"
7703 " Start/stop/query remote services")
7709 N_("Manage registry hives"),
7710 N_("net rpc registry\n"
7711 " Manage registry hives")
7717 N_("Open interactive shell on remote server"),
7718 N_("net rpc shell\n"
7719 " Open interactive shell on remote server")
7721 {NULL, NULL, 0, NULL, NULL}
7724 status = libnetapi_net_init(&c->netapi_ctx);
7728 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
7729 libnetapi_set_password(c->netapi_ctx, c->opt_password);
7730 if (c->opt_kerberos) {
7731 libnetapi_set_use_kerberos(c->netapi_ctx);
7733 if (c->opt_ccache) {
7734 libnetapi_set_use_ccache(c->netapi_ctx);
7737 return net_run_function(c, argc, argv, "net rpc", func);