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 "libsmb/namequery.h"
26 #include "rpc_client/cli_pipe.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "../librpc/gen_ndr/ndr_samr_c.h"
29 #include "rpc_client/cli_samr.h"
30 #include "rpc_client/init_samr.h"
31 #include "../librpc/gen_ndr/ndr_lsa_c.h"
32 #include "rpc_client/cli_lsarpc.h"
33 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
35 #include "../librpc/gen_ndr/ndr_spoolss.h"
36 #include "../librpc/gen_ndr/ndr_initshutdown_c.h"
37 #include "../librpc/gen_ndr/ndr_winreg_c.h"
39 #include "lib/netapi/netapi.h"
40 #include "lib/netapi/netapi_net.h"
41 #include "librpc/gen_ndr/libnet_join.h"
42 #include "libnet/libnet_join.h"
43 #include "rpc_client/init_lsa.h"
44 #include "../libcli/security/security.h"
45 #include "libsmb/libsmb.h"
47 #include "nsswitch/libwbclient/wbclient.h"
49 #include "../libcli/smb/smbXcli_base.h"
50 #include "libsmb/dsgetdcname.h"
52 static int net_mode_share;
53 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
58 * @brief RPC based subcommands for the 'net' utility.
60 * This file should contain much of the functionality that used to
61 * be found in rpcclient, except that the commands should change
62 * less often, and the functionality should be sane (the user is not
63 * expected to know a rid/sid before they conduct an operation etc.)
65 * @todo Perhaps eventually these should be split out into a number
66 * of files, as this could get quite big.
71 * Many of the RPC functions need the domain sid. This function gets
72 * it at the start of every run
74 * @param cli A cli_state already connected to the remote machine
76 * @return The Domain SID of the remote machine.
79 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
80 struct dom_sid **domain_sid,
81 const char **domain_name)
83 struct rpc_pipe_client *lsa_pipe = NULL;
84 struct policy_handle pol;
85 NTSTATUS status, result;
86 union lsa_PolicyInformation *info = NULL;
87 struct dcerpc_binding_handle *b;
89 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
91 if (!NT_STATUS_IS_OK(status)) {
92 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
96 b = lsa_pipe->binding_handle;
98 status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
99 SEC_FLAG_MAXIMUM_ALLOWED,
101 if (!NT_STATUS_IS_OK(status)) {
102 d_fprintf(stderr, "open_policy %s: %s\n",
108 status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
110 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
113 if (!NT_STATUS_IS_OK(status)) {
114 d_fprintf(stderr, "lsaquery %s: %s\n",
119 if (!NT_STATUS_IS_OK(result)) {
120 d_fprintf(stderr, "lsaquery %s: %s\n",
126 *domain_name = info->account_domain.name.string;
127 *domain_sid = info->account_domain.sid;
129 dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
130 TALLOC_FREE(lsa_pipe);
136 * Run a single RPC command, from start to finish.
138 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
139 * @param conn_flag a NET_FLAG_ combination. Passed to
140 * net_make_ipc_connection.
141 * @param argc Standard main() style argc.
142 * @param argv Standard main() style argv. Initial components are already
144 * @return A shell status integer (0 for success).
147 int run_rpc_command(struct net_context *c,
148 struct cli_state *cli_arg,
149 const struct ndr_interface_table *table,
155 struct cli_state *cli = NULL;
156 struct rpc_pipe_client *pipe_hnd = NULL;
159 struct dom_sid *domain_sid;
160 const char *domain_name;
163 /* make use of cli_state handed over as an argument, if possible */
165 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
166 if (!NT_STATUS_IS_OK(nt_status)) {
167 DEBUG(1, ("failed to make ipc connection: %s\n",
168 nt_errstr(nt_status)));
181 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
182 DEBUG(0, ("talloc_init() failed\n"));
186 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
188 if (!NT_STATUS_IS_OK(nt_status)) {
192 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
193 if (lp_client_schannel()
194 && (ndr_syntax_id_equal(&table->syntax_id,
195 &ndr_table_netlogon.syntax_id))) {
196 /* Always try and create an schannel netlogon pipe. */
197 TALLOC_FREE(c->netlogon_creds);
198 nt_status = cli_rpc_pipe_open_schannel(
199 cli, c->msg_ctx, table, NCACN_NP,
201 &pipe_hnd, c, &c->netlogon_creds);
202 if (!NT_STATUS_IS_OK(nt_status)) {
203 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
204 nt_errstr(nt_status) ));
208 if (conn_flags & NET_FLAGS_SEAL) {
209 struct cli_credentials *creds = NULL;
211 creds = net_context_creds(c, mem_ctx);
213 DBG_ERR("net_rpc_ntlm_creds() failed\n");
214 nt_status = NT_STATUS_INTERNAL_ERROR;
218 nt_status = cli_rpc_pipe_open_with_creds(
220 (conn_flags & NET_FLAGS_TCP) ?
221 NCACN_IP_TCP : NCACN_NP,
222 DCERPC_AUTH_TYPE_NTLMSSP,
223 DCERPC_AUTH_LEVEL_PRIVACY,
224 smbXcli_conn_remote_name(cli->conn),
227 nt_status = cli_rpc_pipe_open_noauth(
231 if (!NT_STATUS_IS_OK(nt_status)) {
232 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
234 nt_errstr(nt_status) ));
240 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
242 if (!NT_STATUS_IS_OK(nt_status)) {
243 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
246 DEBUG(5, ("rpc command function succeeded\n"));
249 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
251 TALLOC_FREE(pipe_hnd);
256 /* close the connection only if it was opened here */
261 talloc_destroy(mem_ctx);
266 * Force a change of the trust account password.
268 * All parameters are provided by the run_rpc_command function, except for
269 * argc, argv which are passed through.
271 * @param domain_sid The domain sid acquired from the remote server.
272 * @param cli A cli_state connected to the server.
273 * @param mem_ctx Talloc context, destroyed on completion of the function.
274 * @param argc Standard main() style argc.
275 * @param argv Standard main() style argv. Initial components are already
278 * @return Normal NTSTATUS return.
281 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
282 const struct dom_sid *domain_sid,
283 const char *domain_name,
284 struct cli_state *cli,
285 struct rpc_pipe_client *pipe_hnd,
291 const char *dcname = NULL;
294 return NT_STATUS_INTERNAL_ERROR;
297 dcname = smbXcli_conn_remote_name(cli->conn);
299 status = trust_pw_change(c->netlogon_creds,
301 pipe_hnd->binding_handle,
302 c->opt_target_workgroup,
305 if (!NT_STATUS_IS_OK(status)) {
306 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
315 * Force a change of the trust account password.
317 * @param argc Standard main() style argc.
318 * @param argv Standard main() style argv. Initial components are already
321 * @return A shell status integer (0 for success).
324 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
326 int conn_flags = NET_FLAGS_PDC;
328 if (!c->opt_user_specified && !c->opt_kerberos) {
329 conn_flags |= NET_FLAGS_ANONYMOUS;
332 if (c->display_usage) {
334 "net rpc changetrustpw\n"
337 _("Change the machine trust password"));
341 return run_rpc_command(c, NULL, &ndr_table_netlogon,
343 rpc_changetrustpw_internals,
348 * Join a domain, the old way. This function exists to allow
349 * the message to be displayed when oldjoin was explicitly
350 * requested, but not when it was implied by "net rpc join".
352 * This uses 'machinename' as the initial password, and changes it.
354 * The password should be created with 'server manager' or equiv first.
356 * @param argc Standard main() style argc.
357 * @param argv Standard main() style argv. Initial components are already
360 * @return A shell status integer (0 for success).
363 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
365 struct libnet_JoinCtx *r = NULL;
368 const char *domain = lp_workgroup(); /* FIXME */
369 bool modify_config = lp_config_backend_is_registry();
370 enum netr_SchannelType sec_chan_type;
373 if (c->display_usage) {
376 " Join a domain the old way\n");
380 mem_ctx = talloc_init("net_rpc_oldjoin");
385 werr = libnet_init_JoinCtx(mem_ctx, &r);
386 if (!W_ERROR_IS_OK(werr)) {
391 check what type of join - if the user wants to join as
392 a BDC, the server must agree that we are a BDC.
395 sec_chan_type = get_sec_channel_type(argv[0]);
397 sec_chan_type = get_sec_channel_type(NULL);
401 d_fprintf(stderr, _("Could not initialise message context. "
402 "Try running as root\n"));
403 werr = WERR_ACCESS_DENIED;
407 pw = talloc_strndup(r, lp_netbios_name(), 14);
409 werr = WERR_NOT_ENOUGH_MEMORY;
413 r->in.msg_ctx = c->msg_ctx;
414 r->in.domain_name = domain;
415 r->in.secure_channel_type = sec_chan_type;
416 r->in.dc_name = c->opt_host;
417 r->in.admin_account = "";
418 r->in.admin_password = strlower_talloc(r, pw);
419 if (r->in.admin_password == NULL) {
420 werr = WERR_NOT_ENOUGH_MEMORY;
424 r->in.modify_config = modify_config;
425 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
426 WKSSVC_JOIN_FLAGS_JOIN_UNSECURE |
427 WKSSVC_JOIN_FLAGS_MACHINE_PWD_PASSED;
429 werr = libnet_Join(mem_ctx, r);
430 if (!W_ERROR_IS_OK(werr)) {
434 /* Check the short name of the domain */
436 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
437 d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE());
438 d_printf("domain name obtained from the server.\n");
439 d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name);
440 d_printf("You should set \"workgroup = %s\" in %s.\n",
441 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
444 d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name);
446 if (r->out.dns_domain_name) {
447 d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name,
448 r->out.dns_domain_name);
450 d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name,
451 r->out.netbios_domain_name);
454 /* print out informative error string in case there is one */
455 if (r->out.error_string != NULL) {
456 d_printf("%s\n", r->out.error_string);
459 TALLOC_FREE(mem_ctx);
464 if (c->opt_flags & NET_FLAGS_EXPECT_FALLBACK) {
468 /* issue an overall failure message at the end. */
469 d_fprintf(stderr, _("Failed to join domain: %s\n"),
470 r && r->out.error_string ? r->out.error_string :
471 get_friendly_werror_msg(werr));
474 TALLOC_FREE(mem_ctx);
480 * check that a join is OK
482 * @return A shell status integer (0 for success)
485 int net_rpc_testjoin(struct net_context *c, int argc, const char **argv)
489 const char *domain = c->opt_target_workgroup;
490 const char *dc = c->opt_host;
492 if (c->display_usage) {
495 " Test if a join is OK\n");
499 mem_ctx = talloc_init("net_rpc_testjoin");
505 struct netr_DsRGetDCNameInfo *info;
508 d_fprintf(stderr, _("Could not initialise message context. "
509 "Try running as root\n"));
510 talloc_destroy(mem_ctx);
514 status = dsgetdcname(mem_ctx,
521 if (!NT_STATUS_IS_OK(status)) {
522 talloc_destroy(mem_ctx);
526 dc = strip_hostname(info->dc_unc);
529 /* Display success or failure */
530 status = libnet_join_ok(c->msg_ctx,
534 if (!NT_STATUS_IS_OK(status)) {
535 fprintf(stderr,"Join to domain '%s' is not valid: %s\n",
536 domain, nt_errstr(status));
537 talloc_destroy(mem_ctx);
541 printf("Join to '%s' is OK\n",domain);
542 talloc_destroy(mem_ctx);
548 * Join a domain using the administrator username and password
550 * @param argc Standard main() style argc
551 * @param argc Standard main() style argv. Initial components are already
552 * stripped. Currently not used.
553 * @return A shell status integer (0 for success)
557 static int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
559 struct libnet_JoinCtx *r = NULL;
562 const char *domain = lp_workgroup(); /* FIXME */
563 bool modify_config = lp_config_backend_is_registry();
564 enum netr_SchannelType sec_chan_type;
566 if (c->display_usage) {
569 " Join a domain the new way\n");
573 mem_ctx = talloc_init("net_rpc_join_newstyle");
578 werr = libnet_init_JoinCtx(mem_ctx, &r);
579 if (!W_ERROR_IS_OK(werr)) {
584 check what type of join - if the user wants to join as
585 a BDC, the server must agree that we are a BDC.
588 sec_chan_type = get_sec_channel_type(argv[0]);
590 sec_chan_type = get_sec_channel_type(NULL);
594 d_fprintf(stderr, _("Could not initialise message context. "
595 "Try running as root\n"));
596 werr = WERR_ACCESS_DENIED;
600 r->in.msg_ctx = c->msg_ctx;
601 r->in.domain_name = domain;
602 r->in.secure_channel_type = sec_chan_type;
603 r->in.dc_name = c->opt_host;
604 r->in.admin_account = c->opt_user_name;
605 r->in.admin_password = net_prompt_pass(c, c->opt_user_name);
607 r->in.use_kerberos = c->opt_kerberos;
608 r->in.modify_config = modify_config;
609 r->in.join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
610 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
611 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED;
613 werr = libnet_Join(mem_ctx, r);
614 if (!W_ERROR_IS_OK(werr)) {
618 /* Check the short name of the domain */
620 if (!modify_config && !strequal(lp_workgroup(), r->out.netbios_domain_name)) {
621 d_printf("The workgroup in %s does not match the short\n", get_dyn_CONFIGFILE());
622 d_printf("domain name obtained from the server.\n");
623 d_printf("Using the name [%s] from the server.\n", r->out.netbios_domain_name);
624 d_printf("You should set \"workgroup = %s\" in %s.\n",
625 r->out.netbios_domain_name, get_dyn_CONFIGFILE());
628 d_printf("Using short domain name -- %s\n", r->out.netbios_domain_name);
630 if (r->out.dns_domain_name) {
631 d_printf("Joined '%s' to realm '%s'\n", r->in.machine_name,
632 r->out.dns_domain_name);
634 d_printf("Joined '%s' to domain '%s'\n", r->in.machine_name,
635 r->out.netbios_domain_name);
638 /* print out informative error string in case there is one */
639 if (r->out.error_string != NULL) {
640 d_printf("%s\n", r->out.error_string);
643 TALLOC_FREE(mem_ctx);
648 /* issue an overall failure message at the end. */
649 d_printf("Failed to join domain: %s\n",
650 r && r->out.error_string ? r->out.error_string :
651 get_friendly_werror_msg(werr));
653 TALLOC_FREE(mem_ctx);
659 * 'net rpc join' entrypoint.
660 * @param argc Standard main() style argc.
661 * @param argv Standard main() style argv. Initial components are already
664 * Main 'net_rpc_join()' (where the admin username/password is used) is
666 * Try to just change the password, but if that doesn't work, use/prompt
667 * for a username/password.
670 int net_rpc_join(struct net_context *c, int argc, const char **argv)
674 if (c->display_usage) {
677 _("net rpc join -U <username>[%%password] <type>\n"
679 " username\tName of the admin user"
680 " password\tPassword of the admin user, will "
681 "prompt if not specified\n"
682 " type\tCan be one of the following:\n"
683 "\t\tMEMBER\tJoin as member server (default)\n"
684 "\t\tBDC\tJoin as BDC\n"
685 "\t\tPDC\tJoin as PDC\n"));
689 if (lp_server_role() == ROLE_STANDALONE) {
690 d_printf(_("cannot join as standalone machine\n"));
694 if (strlen(lp_netbios_name()) > 15) {
695 d_printf(_("Our netbios name can be at most 15 chars long, "
696 "\"%s\" is %u chars long\n"),
697 lp_netbios_name(), (unsigned int)strlen(lp_netbios_name()));
701 c->opt_flags |= NET_FLAGS_EXPECT_FALLBACK;
702 ret = net_rpc_oldjoin(c, argc, argv);
703 c->opt_flags &= ~NET_FLAGS_EXPECT_FALLBACK;
708 return net_rpc_join_newstyle(c, argc, argv);
712 * display info about a rpc domain
714 * All parameters are provided by the run_rpc_command function, except for
715 * argc, argv which are passed through.
717 * @param domain_sid The domain sid acquired from the remote server
718 * @param cli A cli_state connected to the server.
719 * @param mem_ctx Talloc context, destroyed on completion of the function.
720 * @param argc Standard main() style argc.
721 * @param argv Standard main() style argv. Initial components are already
724 * @return Normal NTSTATUS return.
727 NTSTATUS rpc_info_internals(struct net_context *c,
728 const struct dom_sid *domain_sid,
729 const char *domain_name,
730 struct cli_state *cli,
731 struct rpc_pipe_client *pipe_hnd,
736 struct policy_handle connect_pol, domain_pol;
737 NTSTATUS status, result;
738 union samr_DomainInfo *info = NULL;
739 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
741 /* Get sam policy handle */
742 status = dcerpc_samr_Connect2(b, mem_ctx,
744 MAXIMUM_ALLOWED_ACCESS,
747 if (!NT_STATUS_IS_OK(status)) {
748 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
753 if (!NT_STATUS_IS_OK(result)) {
755 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
760 /* Get domain policy handle */
761 status = dcerpc_samr_OpenDomain(b, mem_ctx,
763 MAXIMUM_ALLOWED_ACCESS,
764 discard_const_p(struct dom_sid2, domain_sid),
767 if (!NT_STATUS_IS_OK(status)) {
768 d_fprintf(stderr, _("Could not open domain: %s\n"),
772 if (!NT_STATUS_IS_OK(result)) {
774 d_fprintf(stderr, _("Could not open domain: %s\n"),
779 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
784 if (!NT_STATUS_IS_OK(status)) {
788 if (NT_STATUS_IS_OK(result)) {
789 struct dom_sid_buf sid_str;
791 d_printf(_("Domain Name: %s\n"),
792 info->general.domain_name.string);
793 d_printf(_("Domain SID: %s\n"),
794 dom_sid_str_buf(domain_sid, &sid_str));
795 d_printf(_("Sequence number: %llu\n"),
796 (unsigned long long)info->general.sequence_num);
797 d_printf(_("Num users: %u\n"), info->general.num_users);
798 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
799 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
807 * 'net rpc info' entrypoint.
808 * @param argc Standard main() style argc.
809 * @param argv Standard main() style argv. Initial components are already
813 int net_rpc_info(struct net_context *c, int argc, const char **argv)
815 if (c->display_usage) {
820 _("Display information about the domain"));
824 return run_rpc_command(c, NULL, &ndr_table_samr,
825 NET_FLAGS_PDC, rpc_info_internals,
830 * Fetch domain SID into the local secrets.tdb.
832 * All parameters are provided by the run_rpc_command function, except for
833 * argc, argv which are passed through.
835 * @param domain_sid The domain sid acquired from the remote server.
836 * @param cli A cli_state connected to the server.
837 * @param mem_ctx Talloc context, destroyed on completion of the function.
838 * @param argc Standard main() style argc.
839 * @param argv Standard main() style argv. Initial components are already
842 * @return Normal NTSTATUS return.
845 static NTSTATUS rpc_getsid_internals(struct net_context *c,
846 const struct dom_sid *domain_sid,
847 const char *domain_name,
848 struct cli_state *cli,
849 struct rpc_pipe_client *pipe_hnd,
854 struct dom_sid_buf sid_str;
856 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
857 dom_sid_str_buf(domain_sid, &sid_str),
860 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
861 DEBUG(0,("Can't store domain SID\n"));
862 return NT_STATUS_UNSUCCESSFUL;
869 * 'net rpc getsid' entrypoint.
870 * @param argc Standard main() style argc.
871 * @param argv Standard main() style argv. Initial components are already
875 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
877 int conn_flags = NET_FLAGS_PDC;
879 if (!c->opt_user_specified && !c->opt_kerberos) {
880 conn_flags |= NET_FLAGS_ANONYMOUS;
883 if (c->display_usage) {
888 _("Fetch domain SID into local secrets.tdb"));
892 return run_rpc_command(c, NULL, &ndr_table_samr,
894 rpc_getsid_internals,
898 /****************************************************************************/
901 * Basic usage function for 'net rpc user'.
902 * @param argc Standard main() style argc.
903 * @param argv Standard main() style argv. Initial components are already
907 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
909 return net_user_usage(c, argc, argv);
913 * Add a new user to a remote RPC server.
915 * @param argc Standard main() style argc.
916 * @param argv Standard main() style argv. Initial components are already
919 * @return A shell status integer (0 for success).
922 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
924 NET_API_STATUS status;
925 struct USER_INFO_1 info1;
926 uint32_t parm_error = 0;
928 if (argc < 1 || c->display_usage) {
929 rpc_user_usage(c, argc, argv);
935 info1.usri1_name = argv[0];
937 info1.usri1_password = argv[1];
940 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
943 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
944 argv[0], libnetapi_get_error_string(c->netapi_ctx,
948 d_printf(_("Added user '%s'.\n"), argv[0]);
955 * Rename a user on a remote RPC server.
957 * @param argc Standard main() style argc.
958 * @param argv Standard main() style argv. Initial components are already
961 * @return A shell status integer (0 for success).
964 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
966 NET_API_STATUS status;
967 struct USER_INFO_0 u0;
968 uint32_t parm_err = 0;
970 if (argc != 2 || c->display_usage) {
971 rpc_user_usage(c, argc, argv);
975 u0.usri0_name = argv[1];
977 status = NetUserSetInfo(c->opt_host, argv[0],
978 0, (uint8_t *)&u0, &parm_err);
981 _("Failed to rename user from %s to %s - %s\n"),
983 libnetapi_get_error_string(c->netapi_ctx, status));
985 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
992 * Set a user's primary group
994 * @param argc Standard main() style argc.
995 * @param argv Standard main() style argv. Initial components are already
998 * @return A shell status integer (0 for success).
1001 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
1004 NET_API_STATUS status;
1006 struct GROUP_INFO_2 *g2;
1007 struct USER_INFO_1051 u1051;
1008 uint32_t parm_err = 0;
1010 if (argc != 2 || c->display_usage) {
1011 rpc_user_usage(c, argc, argv);
1015 status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
1017 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
1019 libnetapi_get_error_string(c->netapi_ctx, status));
1022 g2 = (struct GROUP_INFO_2 *)buffer;
1024 u1051.usri1051_primary_group_id = g2->grpi2_group_id;
1026 NetApiBufferFree(buffer);
1028 status = NetUserSetInfo(c->opt_host, argv[0], 1051,
1029 (uint8_t *)&u1051, &parm_err);
1032 _("Failed to set user's primary group %s to %s - "
1033 "%s\n"), argv[0], argv[1],
1034 libnetapi_get_error_string(c->netapi_ctx, status));
1036 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
1043 * Delete a user from a remote RPC server.
1045 * @param argc Standard main() style argc.
1046 * @param argv Standard main() style argv. Initial components are already
1049 * @return A shell status integer (0 for success).
1052 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
1054 NET_API_STATUS status;
1056 if (argc < 1 || c->display_usage) {
1057 rpc_user_usage(c, argc, argv);
1061 status = NetUserDel(c->opt_host, argv[0]);
1064 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
1066 libnetapi_get_error_string(c->netapi_ctx, status));
1069 d_printf(_("Deleted user '%s'.\n"), argv[0]);
1076 * Set a user's password on a remote RPC server.
1078 * @param argc Standard main() style argc.
1079 * @param argv Standard main() style argv. Initial components are already
1082 * @return A shell status integer (0 for success).
1085 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
1087 NET_API_STATUS status;
1088 char *prompt = NULL;
1089 struct USER_INFO_1003 u1003;
1090 uint32_t parm_err = 0;
1093 if (argc < 1 || c->display_usage) {
1094 rpc_user_usage(c, argc, argv);
1099 u1003.usri1003_password = argv[1];
1101 char pwd[256] = {0};
1102 ret = asprintf(&prompt, _("Enter new password for %s:"),
1108 ret = samba_getpass(prompt, pwd, sizeof(pwd), false, false);
1114 u1003.usri1003_password = talloc_strdup(c, pwd);
1115 if (u1003.usri1003_password == NULL) {
1120 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
1122 /* Display results */
1125 _("Failed to set password for '%s' with error: %s.\n"),
1126 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1135 * List a user's groups from a remote RPC server.
1137 * @param argc Standard main() style argc.
1138 * @param argv Standard main() style argv. Initial components are already
1141 * @return A shell status integer (0 for success)
1144 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
1147 NET_API_STATUS status;
1148 struct GROUP_USERS_INFO_0 *u0 = NULL;
1149 uint32_t entries_read = 0;
1150 uint32_t total_entries = 0;
1154 if (argc < 1 || c->display_usage) {
1155 rpc_user_usage(c, argc, argv);
1159 status = NetUserGetGroups(c->opt_host,
1162 (uint8_t **)(void *)&u0,
1168 _("Failed to get groups for '%s' with error: %s.\n"),
1169 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1174 for (i=0; i < entries_read; i++) {
1175 printf("%s\n", u0->grui0_name);
1183 * List users on a remote RPC server.
1185 * All parameters are provided by the run_rpc_command function, except for
1186 * argc, argv which are passed through.
1188 * @param domain_sid The domain sid acquired from the remote server.
1189 * @param cli A cli_state connected to the server.
1190 * @param mem_ctx Talloc context, destroyed on completion of the function.
1191 * @param argc Standard main() style argc.
1192 * @param argv Standard main() style argv. Initial components are already
1195 * @return Normal NTSTATUS return.
1198 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
1200 NET_API_STATUS status;
1201 uint32_t start_idx=0, num_entries, i, loop_count = 0;
1202 struct NET_DISPLAY_USER *info = NULL;
1203 void *buffer = NULL;
1205 /* Query domain users */
1206 if (c->opt_long_list_entries)
1207 d_printf(_("\nUser name Comment"
1208 "\n-----------------------------\n"));
1210 uint32_t max_entries, max_size;
1212 dcerpc_get_query_dispinfo_params(
1213 loop_count, &max_entries, &max_size);
1215 status = NetQueryDisplayInformation(c->opt_host,
1222 if (status != 0 && status != ERROR_MORE_DATA) {
1226 info = (struct NET_DISPLAY_USER *)buffer;
1228 for (i = 0; i < num_entries; i++) {
1230 if (c->opt_long_list_entries)
1231 printf("%-21.21s %s\n", info->usri1_name,
1232 info->usri1_comment);
1234 printf("%s\n", info->usri1_name);
1238 NetApiBufferFree(buffer);
1241 start_idx += num_entries;
1243 } while (status == ERROR_MORE_DATA);
1249 * 'net rpc user' entrypoint.
1250 * @param argc Standard main() style argc.
1251 * @param argv Standard main() style argv. Initial components are already
1255 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1257 NET_API_STATUS status;
1259 struct functable func[] = {
1264 N_("Add specified user"),
1265 N_("net rpc user add\n"
1266 " Add specified user")
1272 N_("List domain groups of user"),
1273 N_("net rpc user info\n"
1274 " List domain groups of user")
1280 N_("Remove specified user"),
1281 N_("net rpc user delete\n"
1282 " Remove specified user")
1288 N_("Change user password"),
1289 N_("net rpc user password\n"
1290 " Change user password")
1296 N_("Rename specified user"),
1297 N_("net rpc user rename\n"
1298 " Rename specified user")
1302 rpc_user_setprimarygroup,
1304 "Set a user's primary group",
1305 "net rpc user setprimarygroup\n"
1306 " Set a user's primary group"
1308 {NULL, NULL, 0, NULL, NULL}
1311 status = libnetapi_net_init(&c->netapi_ctx);
1315 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1316 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1317 if (c->opt_kerberos) {
1318 libnetapi_set_use_kerberos(c->netapi_ctx);
1322 if (c->display_usage) {
1327 _("List all users"));
1328 net_display_usage_from_functable(func);
1332 return rpc_user_list(c, argc, argv);
1335 return net_run_function(c, argc, argv, "net rpc user", func);
1338 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1339 TALLOC_CTX *mem_ctx,
1340 struct rpc_sh_ctx *ctx,
1341 struct rpc_pipe_client *pipe_hnd,
1342 int argc, const char **argv)
1344 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1347 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1348 TALLOC_CTX *mem_ctx,
1349 struct rpc_sh_ctx *ctx,
1350 struct rpc_pipe_client *pipe_hnd,
1351 int argc, const char **argv)
1353 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1356 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1357 TALLOC_CTX *mem_ctx,
1358 struct rpc_sh_ctx *ctx,
1359 struct rpc_pipe_client *pipe_hnd,
1360 int argc, const char **argv,
1362 struct net_context *c,
1363 TALLOC_CTX *mem_ctx,
1364 struct rpc_sh_ctx *ctx,
1365 struct rpc_pipe_client *pipe_hnd,
1366 struct policy_handle *user_hnd,
1367 int argc, const char **argv))
1369 struct policy_handle connect_pol, domain_pol, user_pol;
1370 NTSTATUS status, result;
1373 enum lsa_SidType type;
1374 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1377 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1379 return NT_STATUS_INVALID_PARAMETER;
1382 ZERO_STRUCT(connect_pol);
1383 ZERO_STRUCT(domain_pol);
1384 ZERO_STRUCT(user_pol);
1386 status = net_rpc_lookup_name(c, mem_ctx, ctx->cli,
1387 argv[0], NULL, NULL, &sid, &type);
1388 if (!NT_STATUS_IS_OK(status)) {
1389 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1394 if (type != SID_NAME_USER) {
1395 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1396 sid_type_lookup(type));
1397 status = NT_STATUS_NO_SUCH_USER;
1401 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1402 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1403 status = NT_STATUS_NO_SUCH_USER;
1407 status = dcerpc_samr_Connect2(b, mem_ctx,
1409 MAXIMUM_ALLOWED_ACCESS,
1412 if (!NT_STATUS_IS_OK(status)) {
1415 if (!NT_STATUS_IS_OK(result)) {
1420 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1422 MAXIMUM_ALLOWED_ACCESS,
1426 if (!NT_STATUS_IS_OK(status)) {
1429 if (!NT_STATUS_IS_OK(result)) {
1434 status = dcerpc_samr_OpenUser(b, mem_ctx,
1436 MAXIMUM_ALLOWED_ACCESS,
1440 if (!NT_STATUS_IS_OK(status)) {
1443 if (!NT_STATUS_IS_OK(result)) {
1448 status = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1451 if (is_valid_policy_hnd(&user_pol)) {
1452 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1454 if (is_valid_policy_hnd(&domain_pol)) {
1455 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1457 if (is_valid_policy_hnd(&connect_pol)) {
1458 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
1463 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1464 TALLOC_CTX *mem_ctx,
1465 struct rpc_sh_ctx *ctx,
1466 struct rpc_pipe_client *pipe_hnd,
1467 struct policy_handle *user_hnd,
1468 int argc, const char **argv)
1470 NTSTATUS status, result;
1471 union samr_UserInfo *info = NULL;
1472 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1475 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1477 return NT_STATUS_INVALID_PARAMETER;
1480 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1485 if (!NT_STATUS_IS_OK(status)) {
1488 if (!NT_STATUS_IS_OK(result)) {
1492 d_printf(_("user rid: %d, group rid: %d\n"),
1494 info->info21.primary_gid);
1499 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1500 TALLOC_CTX *mem_ctx,
1501 struct rpc_sh_ctx *ctx,
1502 struct rpc_pipe_client *pipe_hnd,
1503 int argc, const char **argv)
1505 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1506 rpc_sh_user_show_internals);
1509 #define FETCHSTR(name, rec) \
1510 do { if (strequal(ctx->thiscmd, name)) { \
1511 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1514 #define SETSTR(name, rec, flag) \
1515 do { if (strequal(ctx->thiscmd, name)) { \
1516 init_lsa_String(&(info->info21.rec), argv[0]); \
1517 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1520 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1521 TALLOC_CTX *mem_ctx,
1522 struct rpc_sh_ctx *ctx,
1523 struct rpc_pipe_client *pipe_hnd,
1524 struct policy_handle *user_hnd,
1525 int argc, const char **argv)
1527 NTSTATUS status, result;
1528 const char *username;
1529 const char *oldval = "";
1530 union samr_UserInfo *info = NULL;
1531 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1534 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1535 _("Usage:"), ctx->whoami);
1536 return NT_STATUS_INVALID_PARAMETER;
1539 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1544 if (!NT_STATUS_IS_OK(status)) {
1547 if (!NT_STATUS_IS_OK(result)) {
1551 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1553 FETCHSTR("fullname", full_name);
1554 FETCHSTR("homedir", home_directory);
1555 FETCHSTR("homedrive", home_drive);
1556 FETCHSTR("logonscript", logon_script);
1557 FETCHSTR("profilepath", profile_path);
1558 FETCHSTR("description", description);
1561 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1565 if (strcmp(argv[0], "NULL") == 0) {
1569 ZERO_STRUCT(info->info21);
1571 SETSTR("fullname", full_name, FULL_NAME);
1572 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1573 SETSTR("homedrive", home_drive, HOME_DRIVE);
1574 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1575 SETSTR("profilepath", profile_path, PROFILE_PATH);
1576 SETSTR("description", description, DESCRIPTION);
1578 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1583 if (!NT_STATUS_IS_OK(status)) {
1589 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1590 ctx->thiscmd, oldval, argv[0]);
1597 #define HANDLEFLG(name, rec) \
1598 do { if (strequal(ctx->thiscmd, name)) { \
1599 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1601 newflags = oldflags | ACB_##rec; \
1603 newflags = oldflags & ~ACB_##rec; \
1606 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1607 TALLOC_CTX *mem_ctx,
1608 struct rpc_sh_ctx *ctx,
1609 struct rpc_pipe_client *pipe_hnd,
1610 int argc, const char **argv)
1612 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1613 rpc_sh_user_str_edit_internals);
1616 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1617 TALLOC_CTX *mem_ctx,
1618 struct rpc_sh_ctx *ctx,
1619 struct rpc_pipe_client *pipe_hnd,
1620 struct policy_handle *user_hnd,
1621 int argc, const char **argv)
1623 NTSTATUS status, result;
1624 const char *username;
1625 const char *oldval = "unknown";
1626 uint32_t oldflags, newflags;
1628 union samr_UserInfo *info = NULL;
1629 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1632 ((argc == 1) && !strequal(argv[0], "yes") &&
1633 !strequal(argv[0], "no"))) {
1634 /* TRANSATORS: The yes|no here are program keywords. Please do
1636 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1638 return NT_STATUS_INVALID_PARAMETER;
1641 newval = strequal(argv[0], "yes");
1643 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1648 if (!NT_STATUS_IS_OK(status)) {
1651 if (!NT_STATUS_IS_OK(result)) {
1655 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1656 oldflags = info->info21.acct_flags;
1657 newflags = info->info21.acct_flags;
1659 HANDLEFLG("disabled", DISABLED);
1660 HANDLEFLG("pwnotreq", PWNOTREQ);
1661 HANDLEFLG("autolock", AUTOLOCK);
1662 HANDLEFLG("pwnoexp", PWNOEXP);
1665 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1670 ZERO_STRUCT(info->info21);
1672 info->info21.acct_flags = newflags;
1673 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1675 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1680 if (!NT_STATUS_IS_OK(status)) {
1684 if (NT_STATUS_IS_OK(result)) {
1685 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1686 ctx->thiscmd, oldval, argv[0]);
1694 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1695 TALLOC_CTX *mem_ctx,
1696 struct rpc_sh_ctx *ctx,
1697 struct rpc_pipe_client *pipe_hnd,
1698 int argc, const char **argv)
1700 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1701 rpc_sh_user_flag_edit_internals);
1704 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1705 TALLOC_CTX *mem_ctx,
1706 struct rpc_sh_ctx *ctx)
1708 static struct rpc_sh_cmd cmds[] = {
1710 { "fullname", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1711 N_("Show/Set a user's full name") },
1713 { "homedir", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1714 N_("Show/Set a user's home directory") },
1716 { "homedrive", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1717 N_("Show/Set a user's home drive") },
1719 { "logonscript", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1720 N_("Show/Set a user's logon script") },
1722 { "profilepath", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1723 N_("Show/Set a user's profile path") },
1725 { "description", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1726 N_("Show/Set a user's description") },
1728 { "disabled", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1729 N_("Show/Set whether a user is disabled") },
1731 { "autolock", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1732 N_("Show/Set whether a user locked out") },
1734 { "pwnotreq", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1735 N_("Show/Set whether a user does not need a password") },
1737 { "pwnoexp", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1738 N_("Show/Set whether a user's password does not expire") },
1740 { NULL, NULL, 0, NULL, NULL }
1746 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1747 TALLOC_CTX *mem_ctx,
1748 struct rpc_sh_ctx *ctx)
1750 static struct rpc_sh_cmd cmds[] = {
1752 { "list", NULL, &ndr_table_samr, rpc_sh_user_list,
1753 N_("List available users") },
1755 { "info", NULL, &ndr_table_samr, rpc_sh_user_info,
1756 N_("List the domain groups a user is member of") },
1758 { "show", NULL, &ndr_table_samr, rpc_sh_user_show,
1759 N_("Show info about a user") },
1761 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1762 N_("Show/Modify a user's fields") },
1764 { NULL, NULL, 0, NULL, NULL }
1770 /****************************************************************************/
1773 * Basic usage function for 'net rpc group'.
1774 * @param argc Standard main() style argc.
1775 * @param argv Standard main() style argv. Initial components are already
1779 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1781 return net_group_usage(c, argc, argv);
1785 * Delete group on a remote RPC server.
1787 * All parameters are provided by the run_rpc_command function, except for
1788 * argc, argv which are passed through.
1790 * @param domain_sid The domain sid acquired from the remote server.
1791 * @param cli A cli_state connected to the server.
1792 * @param mem_ctx Talloc context, destroyed on completion of the function.
1793 * @param argc Standard main() style argc.
1794 * @param argv Standard main() style argv. Initial components are already
1797 * @return Normal NTSTATUS return.
1800 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1801 const struct dom_sid *domain_sid,
1802 const char *domain_name,
1803 struct cli_state *cli,
1804 struct rpc_pipe_client *pipe_hnd,
1805 TALLOC_CTX *mem_ctx,
1809 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1810 bool group_is_primary = false;
1811 NTSTATUS status, result;
1813 struct samr_RidAttrArray *rids = NULL;
1816 /* struct samr_RidWithAttribute *user_gids; */
1817 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1819 struct samr_Ids group_rids, name_types;
1820 struct lsa_String lsa_acct_name;
1821 union samr_UserInfo *info = NULL;
1823 if (argc < 1 || c->display_usage) {
1824 rpc_group_usage(c, argc,argv);
1825 return NT_STATUS_OK; /* ok? */
1828 status = dcerpc_samr_Connect2(b, mem_ctx,
1830 MAXIMUM_ALLOWED_ACCESS,
1833 if (!NT_STATUS_IS_OK(status)) {
1834 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1838 if (!NT_STATUS_IS_OK(result)) {
1840 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1844 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1846 MAXIMUM_ALLOWED_ACCESS,
1847 discard_const_p(struct dom_sid2, domain_sid),
1850 if (!NT_STATUS_IS_OK(status)) {
1851 d_fprintf(stderr, _("Request open_domain failed\n"));
1855 if (!NT_STATUS_IS_OK(result)) {
1857 d_fprintf(stderr, _("Request open_domain failed\n"));
1861 init_lsa_String(&lsa_acct_name, argv[0]);
1863 status = dcerpc_samr_LookupNames(b, mem_ctx,
1870 if (!NT_STATUS_IS_OK(status)) {
1871 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1875 if (!NT_STATUS_IS_OK(result)) {
1877 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1880 if (group_rids.count != 1) {
1881 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1884 if (name_types.count != 1) {
1885 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1889 switch (name_types.ids[0])
1891 case SID_NAME_DOM_GRP:
1892 status = dcerpc_samr_OpenGroup(b, mem_ctx,
1894 MAXIMUM_ALLOWED_ACCESS,
1898 if (!NT_STATUS_IS_OK(status)) {
1899 d_fprintf(stderr, _("Request open_group failed"));
1903 if (!NT_STATUS_IS_OK(result)) {
1905 d_fprintf(stderr, _("Request open_group failed"));
1909 group_rid = group_rids.ids[0];
1911 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
1915 if (!NT_STATUS_IS_OK(status)) {
1917 _("Unable to query group members of %s"),
1922 if (!NT_STATUS_IS_OK(result)) {
1925 _("Unable to query group members of %s"),
1930 if (c->opt_verbose) {
1932 _("Domain Group %s (rid: %d) has %d members\n"),
1933 argv[0],group_rid, rids->count);
1936 /* Check if group is anyone's primary group */
1937 for (i = 0; i < rids->count; i++)
1939 status = dcerpc_samr_OpenUser(b, mem_ctx,
1941 MAXIMUM_ALLOWED_ACCESS,
1945 if (!NT_STATUS_IS_OK(status)) {
1947 _("Unable to open group member %d\n"),
1952 if (!NT_STATUS_IS_OK(result)) {
1955 _("Unable to open group member %d\n"),
1960 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1965 if (!NT_STATUS_IS_OK(status)) {
1967 _("Unable to lookup userinfo for group "
1973 if (!NT_STATUS_IS_OK(result)) {
1976 _("Unable to lookup userinfo for group "
1982 if (info->info21.primary_gid == group_rid) {
1983 if (c->opt_verbose) {
1984 d_printf(_("Group is primary group "
1986 info->info21.account_name.string);
1988 group_is_primary = true;
1991 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1994 if (group_is_primary) {
1995 d_fprintf(stderr, _("Unable to delete group because "
1996 "some of it's members have it as primary "
1998 status = NT_STATUS_MEMBERS_PRIMARY_GROUP;
2002 /* remove all group members */
2003 for (i = 0; i < rids->count; i++)
2006 d_printf(_("Remove group member %d..."),
2008 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2012 if (!NT_STATUS_IS_OK(status)) {
2016 if (NT_STATUS_IS_OK(result)) {
2018 d_printf(_("ok\n"));
2021 d_printf("%s\n", _("failed"));
2026 status = dcerpc_samr_DeleteDomainGroup(b, mem_ctx,
2029 if (!NT_STATUS_IS_OK(status)) {
2036 /* removing a local group is easier... */
2037 case SID_NAME_ALIAS:
2038 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2040 MAXIMUM_ALLOWED_ACCESS,
2044 if (!NT_STATUS_IS_OK(status)) {
2045 d_fprintf(stderr, _("Request open_alias failed\n"));
2048 if (!NT_STATUS_IS_OK(result)) {
2050 d_fprintf(stderr, _("Request open_alias failed\n"));
2054 status = dcerpc_samr_DeleteDomAlias(b, mem_ctx,
2057 if (!NT_STATUS_IS_OK(status)) {
2065 d_fprintf(stderr, _("%s is of type %s. This command is only "
2066 "for deleting local or global groups\n"),
2067 argv[0],sid_type_lookup(name_types.ids[0]));
2068 status = NT_STATUS_UNSUCCESSFUL;
2072 if (NT_STATUS_IS_OK(status)) {
2074 d_printf(_("Deleted %s '%s'\n"),
2075 sid_type_lookup(name_types.ids[0]), argv[0]);
2077 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
2078 get_friendly_nt_error_msg(status));
2086 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
2088 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2089 rpc_group_delete_internals, argc,argv);
2092 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
2094 NET_API_STATUS status;
2095 struct GROUP_INFO_1 info1;
2096 uint32_t parm_error = 0;
2098 if (argc != 1 || c->display_usage) {
2099 rpc_group_usage(c, argc, argv);
2105 info1.grpi1_name = argv[0];
2106 if (c->opt_comment && strlen(c->opt_comment) > 0) {
2107 info1.grpi1_comment = c->opt_comment;
2110 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
2114 _("Failed to add group '%s' with error: %s.\n"),
2115 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2119 d_printf(_("Added group '%s'.\n"), argv[0]);
2125 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
2127 NET_API_STATUS status;
2128 struct LOCALGROUP_INFO_1 info1;
2129 uint32_t parm_error = 0;
2131 if (argc != 1 || c->display_usage) {
2132 rpc_group_usage(c, argc, argv);
2138 info1.lgrpi1_name = argv[0];
2139 if (c->opt_comment && strlen(c->opt_comment) > 0) {
2140 info1.lgrpi1_comment = c->opt_comment;
2143 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
2147 _("Failed to add alias '%s' with error: %s.\n"),
2148 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2152 d_printf(_("Added alias '%s'.\n"), argv[0]);
2158 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
2160 if (c->opt_localgroup)
2161 return rpc_alias_add_internals(c, argc, argv);
2163 return rpc_group_add_internals(c, argc, argv);
2166 static NTSTATUS get_sid_from_name(struct cli_state *cli,
2167 TALLOC_CTX *mem_ctx,
2169 struct dom_sid *sid,
2170 enum lsa_SidType *type)
2172 struct dom_sid *sids = NULL;
2173 enum lsa_SidType *types = NULL;
2174 struct rpc_pipe_client *pipe_hnd = NULL;
2175 struct policy_handle lsa_pol;
2176 NTSTATUS status, result;
2177 struct dcerpc_binding_handle *b;
2179 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc,
2181 if (!NT_STATUS_IS_OK(status)) {
2185 b = pipe_hnd->binding_handle;
2187 status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
2188 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2190 if (!NT_STATUS_IS_OK(status)) {
2194 status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
2195 &name, NULL, 1, &sids, &types);
2197 if (NT_STATUS_IS_OK(status)) {
2198 sid_copy(sid, &sids[0]);
2202 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
2206 TALLOC_FREE(pipe_hnd);
2209 if (!NT_STATUS_IS_OK(status) && (strncasecmp_m(name, "S-", 2) == 0)) {
2211 /* Try as S-1-5-whatever */
2213 struct dom_sid tmp_sid;
2215 if (string_to_sid(&tmp_sid, name)) {
2216 sid_copy(sid, &tmp_sid);
2217 *type = SID_NAME_UNKNOWN;
2218 status = NT_STATUS_OK;
2225 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
2226 TALLOC_CTX *mem_ctx,
2227 const struct dom_sid *group_sid,
2230 struct policy_handle connect_pol, domain_pol;
2231 NTSTATUS status, result;
2233 struct policy_handle group_pol;
2234 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2236 struct samr_Ids rids, rid_types;
2237 struct lsa_String lsa_acct_name;
2241 sid_copy(&sid, group_sid);
2243 if (!sid_split_rid(&sid, &group_rid)) {
2244 return NT_STATUS_UNSUCCESSFUL;
2247 /* Get sam policy handle */
2248 status = dcerpc_samr_Connect2(b, mem_ctx,
2250 MAXIMUM_ALLOWED_ACCESS,
2253 if (!NT_STATUS_IS_OK(status)) {
2256 if (!NT_STATUS_IS_OK(result)) {
2260 /* Get domain policy handle */
2261 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2263 MAXIMUM_ALLOWED_ACCESS,
2267 if (!NT_STATUS_IS_OK(status)) {
2270 if (!NT_STATUS_IS_OK(result)) {
2274 init_lsa_String(&lsa_acct_name, member);
2276 status = dcerpc_samr_LookupNames(b, mem_ctx,
2283 if (!NT_STATUS_IS_OK(status)) {
2284 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2289 if (!NT_STATUS_IS_OK(result)) {
2291 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2295 if (rids.count != 1) {
2296 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2299 if (rid_types.count != 1) {
2300 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2304 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2306 MAXIMUM_ALLOWED_ACCESS,
2310 if (!NT_STATUS_IS_OK(status)) {
2314 if (!NT_STATUS_IS_OK(result)) {
2319 status = dcerpc_samr_AddGroupMember(b, mem_ctx,
2322 0x0005, /* unknown flags */
2324 if (!NT_STATUS_IS_OK(status)) {
2331 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2335 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2336 struct cli_state *cli,
2337 TALLOC_CTX *mem_ctx,
2338 const struct dom_sid *alias_sid,
2341 struct policy_handle connect_pol, domain_pol;
2342 NTSTATUS status, result;
2344 struct policy_handle alias_pol;
2345 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2347 struct dom_sid member_sid;
2348 enum lsa_SidType member_type;
2352 sid_copy(&sid, alias_sid);
2354 if (!sid_split_rid(&sid, &alias_rid)) {
2355 return NT_STATUS_UNSUCCESSFUL;
2358 result = get_sid_from_name(cli, mem_ctx,
2359 member, &member_sid, &member_type);
2361 if (!NT_STATUS_IS_OK(result)) {
2362 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2367 /* Get sam policy handle */
2368 status = dcerpc_samr_Connect2(b, mem_ctx,
2370 MAXIMUM_ALLOWED_ACCESS,
2373 if (!NT_STATUS_IS_OK(status)) {
2376 if (!NT_STATUS_IS_OK(result)) {
2381 /* Get domain policy handle */
2382 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2384 MAXIMUM_ALLOWED_ACCESS,
2388 if (!NT_STATUS_IS_OK(status)) {
2391 if (!NT_STATUS_IS_OK(result)) {
2396 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2398 MAXIMUM_ALLOWED_ACCESS,
2402 if (!NT_STATUS_IS_OK(status)) {
2405 if (!NT_STATUS_IS_OK(result)) {
2409 status = dcerpc_samr_AddAliasMember(b, mem_ctx,
2413 if (!NT_STATUS_IS_OK(status)) {
2420 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2424 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2425 const struct dom_sid *domain_sid,
2426 const char *domain_name,
2427 struct cli_state *cli,
2428 struct rpc_pipe_client *pipe_hnd,
2429 TALLOC_CTX *mem_ctx,
2433 struct dom_sid group_sid;
2434 enum lsa_SidType group_type;
2436 if (argc != 2 || c->display_usage) {
2439 _("net rpc group addmem <group> <member>\n"
2440 " Add a member to a group\n"
2441 " group\tGroup to add member to\n"
2442 " member\tMember to add to group\n"));
2443 return NT_STATUS_UNSUCCESSFUL;
2446 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2447 &group_sid, &group_type))) {
2448 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2450 return NT_STATUS_UNSUCCESSFUL;
2453 if (group_type == SID_NAME_DOM_GRP) {
2454 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2455 &group_sid, argv[1]);
2457 if (!NT_STATUS_IS_OK(result)) {
2458 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2459 argv[1], argv[0], nt_errstr(result));
2464 if (group_type == SID_NAME_ALIAS) {
2465 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, cli, mem_ctx,
2466 &group_sid, argv[1]);
2468 if (!NT_STATUS_IS_OK(result)) {
2469 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2470 argv[1], argv[0], nt_errstr(result));
2475 d_fprintf(stderr, _("Can only add members to global or local groups "
2476 "which %s is not\n"), argv[0]);
2478 return NT_STATUS_UNSUCCESSFUL;
2481 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2483 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2484 rpc_group_addmem_internals,
2488 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2489 struct rpc_pipe_client *pipe_hnd,
2490 TALLOC_CTX *mem_ctx,
2491 const struct dom_sid *group_sid,
2494 struct policy_handle connect_pol, domain_pol;
2495 NTSTATUS status, result;
2497 struct policy_handle group_pol;
2498 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2500 struct samr_Ids rids, rid_types;
2501 struct lsa_String lsa_acct_name;
2505 sid_copy(&sid, group_sid);
2507 if (!sid_split_rid(&sid, &group_rid))
2508 return NT_STATUS_UNSUCCESSFUL;
2510 /* Get sam policy handle */
2511 status = dcerpc_samr_Connect2(b, mem_ctx,
2513 MAXIMUM_ALLOWED_ACCESS,
2516 if (!NT_STATUS_IS_OK(status)) {
2519 if (!NT_STATUS_IS_OK(result)) {
2524 /* Get domain policy handle */
2525 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2527 MAXIMUM_ALLOWED_ACCESS,
2531 if (!NT_STATUS_IS_OK(status)) {
2534 if (!NT_STATUS_IS_OK(result)) {
2538 init_lsa_String(&lsa_acct_name, member);
2540 status = dcerpc_samr_LookupNames(b, mem_ctx,
2547 if (!NT_STATUS_IS_OK(status)) {
2548 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2553 if (!NT_STATUS_IS_OK(result)) {
2555 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2559 if (rids.count != 1) {
2560 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2563 if (rid_types.count != 1) {
2564 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2568 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2570 MAXIMUM_ALLOWED_ACCESS,
2574 if (!NT_STATUS_IS_OK(status)) {
2577 if (!NT_STATUS_IS_OK(result)) {
2582 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2586 if (!NT_STATUS_IS_OK(status)) {
2592 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2596 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2597 struct cli_state *cli,
2598 TALLOC_CTX *mem_ctx,
2599 const struct dom_sid *alias_sid,
2602 struct policy_handle connect_pol, domain_pol;
2603 NTSTATUS status, result;
2605 struct policy_handle alias_pol;
2606 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2608 struct dom_sid member_sid;
2609 enum lsa_SidType member_type;
2613 sid_copy(&sid, alias_sid);
2615 if (!sid_split_rid(&sid, &alias_rid))
2616 return NT_STATUS_UNSUCCESSFUL;
2618 result = get_sid_from_name(cli, mem_ctx,
2619 member, &member_sid, &member_type);
2621 if (!NT_STATUS_IS_OK(result)) {
2622 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2627 /* Get sam policy handle */
2628 status = dcerpc_samr_Connect2(b, mem_ctx,
2630 MAXIMUM_ALLOWED_ACCESS,
2633 if (!NT_STATUS_IS_OK(status)) {
2636 if (!NT_STATUS_IS_OK(result)) {
2641 /* Get domain policy handle */
2642 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2644 MAXIMUM_ALLOWED_ACCESS,
2648 if (!NT_STATUS_IS_OK(status)) {
2651 if (!NT_STATUS_IS_OK(result)) {
2656 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2658 MAXIMUM_ALLOWED_ACCESS,
2662 if (!NT_STATUS_IS_OK(status)) {
2666 if (!NT_STATUS_IS_OK(result)) {
2670 status = dcerpc_samr_DeleteAliasMember(b, mem_ctx,
2675 if (!NT_STATUS_IS_OK(status)) {
2682 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2686 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2687 const struct dom_sid *domain_sid,
2688 const char *domain_name,
2689 struct cli_state *cli,
2690 struct rpc_pipe_client *pipe_hnd,
2691 TALLOC_CTX *mem_ctx,
2695 struct dom_sid group_sid;
2696 enum lsa_SidType group_type;
2698 if (argc != 2 || c->display_usage) {
2701 _("net rpc group delmem <group> <member>\n"
2702 " Delete a member from a group\n"
2703 " group\tGroup to delete member from\n"
2704 " member\tMember to delete from group\n"));
2705 return NT_STATUS_UNSUCCESSFUL;
2708 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2709 &group_sid, &group_type))) {
2710 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2712 return NT_STATUS_UNSUCCESSFUL;
2715 if (group_type == SID_NAME_DOM_GRP) {
2716 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2717 &group_sid, argv[1]);
2719 if (!NT_STATUS_IS_OK(result)) {
2720 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2721 argv[1], argv[0], nt_errstr(result));
2726 if (group_type == SID_NAME_ALIAS) {
2727 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, cli, mem_ctx,
2728 &group_sid, argv[1]);
2730 if (!NT_STATUS_IS_OK(result)) {
2731 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2732 argv[1], argv[0], nt_errstr(result));
2737 d_fprintf(stderr, _("Can only delete members from global or local "
2738 "groups which %s is not\n"), argv[0]);
2740 return NT_STATUS_UNSUCCESSFUL;
2743 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2745 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2746 rpc_group_delmem_internals,
2751 * List groups on a remote RPC server.
2753 * All parameters are provided by the run_rpc_command function, except for
2754 * argc, argv which are passes through.
2756 * @param domain_sid The domain sid acquired from the remote server.
2757 * @param cli A cli_state connected to the server.
2758 * @param mem_ctx Talloc context, destroyed on completion of the function.
2759 * @param argc Standard main() style argc.
2760 * @param argv Standard main() style argv. Initial components are already
2763 * @return Normal NTSTATUS return.
2766 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2767 const struct dom_sid *domain_sid,
2768 const char *domain_name,
2769 struct cli_state *cli,
2770 struct rpc_pipe_client *pipe_hnd,
2771 TALLOC_CTX *mem_ctx,
2775 struct policy_handle connect_pol, domain_pol;
2776 NTSTATUS status, result;
2777 uint32_t start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2778 struct samr_SamArray *groups = NULL;
2779 bool global = false;
2781 bool builtin = false;
2782 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2784 if (c->display_usage) {
2787 _("net rpc group list [global] [local] [builtin]\n"
2788 " List groups on RPC server\n"
2789 " global\tList global groups\n"
2790 " local\tList local groups\n"
2791 " builtin\tList builtin groups\n"
2792 " If none of global, local or builtin is "
2793 "specified, all three options are considered "
2795 return NT_STATUS_OK;
2804 for (i=0; i<argc; i++) {
2805 if (strequal(argv[i], "global"))
2808 if (strequal(argv[i], "local"))
2811 if (strequal(argv[i], "builtin"))
2815 /* Get sam policy handle */
2817 status = dcerpc_samr_Connect2(b, mem_ctx,
2819 MAXIMUM_ALLOWED_ACCESS,
2822 if (!NT_STATUS_IS_OK(status)) {
2825 if (!NT_STATUS_IS_OK(result)) {
2830 /* Get domain policy handle */
2832 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2834 MAXIMUM_ALLOWED_ACCESS,
2835 discard_const_p(struct dom_sid2, domain_sid),
2838 if (!NT_STATUS_IS_OK(status)) {
2841 if (!NT_STATUS_IS_OK(result)) {
2846 /* Query domain groups */
2847 if (c->opt_long_list_entries)
2848 d_printf(_("\nGroup name Comment"
2849 "\n-----------------------------\n"));
2851 uint32_t max_size, total_size, returned_size;
2852 union samr_DispInfo info;
2856 dcerpc_get_query_dispinfo_params(
2857 loop_count, &max_entries, &max_size);
2859 status = dcerpc_samr_QueryDisplayInfo(b, mem_ctx,
2869 if (!NT_STATUS_IS_OK(status)) {
2872 num_entries = info.info3.count;
2873 start_idx += info.info3.count;
2875 if (!NT_STATUS_IS_OK(result) &&
2876 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2879 for (i = 0; i < num_entries; i++) {
2881 const char *group = NULL;
2882 const char *desc = NULL;
2884 group = info.info3.entries[i].account_name.string;
2885 desc = info.info3.entries[i].description.string;
2887 if (c->opt_long_list_entries)
2888 printf("%-21.21s %-50.50s\n",
2891 printf("%s\n", group);
2893 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2894 /* query domain aliases */
2899 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2906 if (!NT_STATUS_IS_OK(status)) {
2909 if (!NT_STATUS_IS_OK(result) &&
2910 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2913 for (i = 0; i < num_entries; i++) {
2915 const char *description = NULL;
2917 if (c->opt_long_list_entries) {
2919 struct policy_handle alias_pol;
2920 union samr_AliasInfo *info = NULL;
2923 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2926 groups->entries[i].idx,
2929 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2930 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2935 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2936 status = dcerpc_samr_Close(b, mem_ctx,
2939 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2940 description = info->description.string;
2946 if (description != NULL) {
2947 printf("%-21.21s %-50.50s\n",
2948 groups->entries[i].name.string,
2951 printf("%s\n", groups->entries[i].name.string);
2954 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2955 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
2956 /* Get builtin policy handle */
2958 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2960 MAXIMUM_ALLOWED_ACCESS,
2961 discard_const_p(struct dom_sid2, &global_sid_Builtin),
2964 if (!NT_STATUS_IS_OK(status)) {
2967 if (!NT_STATUS_IS_OK(result)) {
2972 /* query builtin aliases */
2975 if (!builtin) break;
2977 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2984 if (!NT_STATUS_IS_OK(status)) {
2987 if (!NT_STATUS_IS_OK(result) &&
2988 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
2993 for (i = 0; i < num_entries; i++) {
2995 const char *description = NULL;
2997 if (c->opt_long_list_entries) {
2999 struct policy_handle alias_pol;
3000 union samr_AliasInfo *info = NULL;
3003 status = dcerpc_samr_OpenAlias(b, mem_ctx,
3006 groups->entries[i].idx,
3009 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3010 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
3015 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3016 status = dcerpc_samr_Close(b, mem_ctx,
3019 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
3020 description = info->description.string;
3026 if (description != NULL) {
3027 printf("%-21.21s %-50.50s\n",
3028 groups->entries[i].name.string,
3031 printf("%s\n", groups->entries[i].name.string);
3034 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3042 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
3044 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3045 rpc_group_list_internals,
3049 static NTSTATUS rpc_list_group_members(struct net_context *c,
3050 struct rpc_pipe_client *pipe_hnd,
3051 TALLOC_CTX *mem_ctx,
3052 const char *domain_name,
3053 const struct dom_sid *domain_sid,
3054 struct policy_handle *domain_pol,
3057 NTSTATUS result, status;
3058 struct policy_handle group_pol;
3059 uint32_t num_members, *group_rids;
3061 struct samr_RidAttrArray *rids = NULL;
3062 struct lsa_Strings names;
3063 struct samr_Ids types;
3064 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3066 status = dcerpc_samr_OpenGroup(b, mem_ctx,
3068 MAXIMUM_ALLOWED_ACCESS,
3072 if (!NT_STATUS_IS_OK(status)) {
3075 if (!NT_STATUS_IS_OK(result)) {
3079 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
3083 if (!NT_STATUS_IS_OK(status)) {
3086 if (!NT_STATUS_IS_OK(result)) {
3090 num_members = rids->count;
3091 group_rids = rids->rids;
3093 while (num_members > 0) {
3094 int this_time = 512;
3096 if (num_members < this_time)
3097 this_time = num_members;
3099 status = dcerpc_samr_LookupRids(b, mem_ctx,
3106 if (!NT_STATUS_IS_OK(status)) {
3109 if (!NT_STATUS_IS_OK(result)) {
3112 if (names.count != this_time) {
3113 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3115 if (types.count != this_time) {
3116 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3118 /* We only have users as members, but make the output
3119 the same as the output of alias members */
3121 for (i = 0; i < this_time; i++) {
3123 if (c->opt_long_list_entries) {
3125 struct dom_sid_buf sid_str;
3127 sid_compose(&sid, domain_sid, group_rids[i]);
3129 printf("%s %s\\%s %d\n",
3130 dom_sid_str_buf(&sid, &sid_str),
3132 names.names[i].string,
3135 printf("%s\\%s\n", domain_name,
3136 names.names[i].string);
3140 num_members -= this_time;
3144 return NT_STATUS_OK;
3147 static NTSTATUS rpc_list_alias_members(struct net_context *c,
3148 struct rpc_pipe_client *pipe_hnd,
3149 struct cli_state *cli,
3150 TALLOC_CTX *mem_ctx,
3151 struct policy_handle *domain_pol,
3154 NTSTATUS result, status;
3155 struct rpc_pipe_client *lsa_pipe;
3156 struct policy_handle alias_pol, lsa_pol;
3157 uint32_t num_members;
3158 struct dom_sid *alias_sids;
3161 enum lsa_SidType *types;
3163 struct lsa_SidArray sid_array;
3164 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3166 status = dcerpc_samr_OpenAlias(b, mem_ctx,
3168 MAXIMUM_ALLOWED_ACCESS,
3172 if (!NT_STATUS_IS_OK(status)) {
3175 if (!NT_STATUS_IS_OK(result)) {
3179 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
3183 if (!NT_STATUS_IS_OK(status)) {
3184 d_fprintf(stderr, _("Couldn't list alias members\n"));
3187 if (!NT_STATUS_IS_OK(result)) {
3188 d_fprintf(stderr, _("Couldn't list alias members\n"));
3192 num_members = sid_array.num_sids;
3194 if (num_members == 0) {
3195 return NT_STATUS_OK;
3198 result = cli_rpc_pipe_open_noauth(cli,
3201 if (!NT_STATUS_IS_OK(result)) {
3202 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
3203 nt_errstr(result) );
3207 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
3208 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
3210 if (!NT_STATUS_IS_OK(result)) {
3211 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
3212 TALLOC_FREE(lsa_pipe);
3216 alias_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
3218 d_fprintf(stderr, _("Out of memory\n"));
3219 TALLOC_FREE(lsa_pipe);
3220 return NT_STATUS_NO_MEMORY;
3223 for (i=0; i<num_members; i++) {
3224 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
3227 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
3228 num_members, alias_sids,
3229 &domains, &names, &types);
3231 if (!NT_STATUS_IS_OK(result) &&
3232 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
3233 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
3234 TALLOC_FREE(lsa_pipe);
3238 for (i = 0; i < num_members; i++) {
3239 struct dom_sid_buf sid_str;
3240 dom_sid_str_buf(&alias_sids[i], &sid_str);
3242 if (c->opt_long_list_entries) {
3243 printf("%s %s\\%s %d\n", sid_str.buf,
3244 domains[i] ? domains[i] : _("*unknown*"),
3245 names[i] ? names[i] : _("*unknown*"), types[i]);
3248 printf("%s\\%s\n", domains[i], names[i]);
3250 printf("%s\n", sid_str.buf);
3254 TALLOC_FREE(lsa_pipe);
3255 return NT_STATUS_OK;
3258 static NTSTATUS rpc_group_members_internals(struct net_context *c,
3259 const struct dom_sid *domain_sid,
3260 const char *domain_name,
3261 struct cli_state *cli,
3262 struct rpc_pipe_client *pipe_hnd,
3263 TALLOC_CTX *mem_ctx,
3267 NTSTATUS result, status;
3268 struct policy_handle connect_pol, domain_pol;
3269 struct samr_Ids rids, rid_types;
3270 struct lsa_String lsa_acct_name;
3271 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3273 /* Get sam policy handle */
3275 status = dcerpc_samr_Connect2(b, mem_ctx,
3277 MAXIMUM_ALLOWED_ACCESS,
3280 if (!NT_STATUS_IS_OK(status)) {
3283 if (!NT_STATUS_IS_OK(result)) {
3287 /* Get domain policy handle */
3289 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3291 MAXIMUM_ALLOWED_ACCESS,
3292 discard_const_p(struct dom_sid2, domain_sid),
3295 if (!NT_STATUS_IS_OK(status)) {
3298 if (!NT_STATUS_IS_OK(result)) {
3302 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */