s3:libsmb: add cli_{query,set}_security_descriptor() which take sec_info flags
[Samba/gebeck_regimport.git] / source3 / utils / net_rpc.c
blob60000242e05f025d79b2b14e97c7d130c2652c45
1 /*
2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5 Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
6 Copyright (C) 2004,2008 Guenther Deschner (gd@samba.org)
7 Copyright (C) 2005 Jeremy Allison (jra@samba.org)
8 Copyright (C) 2006 Jelmer Vernooij (jelmer@samba.org)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include "includes.h"
24 #include "utils/net.h"
25 #include "rpc_client/cli_pipe.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../librpc/gen_ndr/ndr_samr_c.h"
28 #include "rpc_client/cli_samr.h"
29 #include "rpc_client/init_samr.h"
30 #include "../librpc/gen_ndr/ndr_lsa_c.h"
31 #include "rpc_client/cli_lsarpc.h"
32 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
33 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
34 #include "../librpc/gen_ndr/ndr_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_initshutdown_c.h"
36 #include "../librpc/gen_ndr/ndr_winreg_c.h"
37 #include "secrets.h"
38 #include "lib/netapi/netapi.h"
39 #include "lib/netapi/netapi_net.h"
40 #include "rpc_client/init_lsa.h"
41 #include "../libcli/security/security.h"
42 #include "libsmb/libsmb.h"
43 #include "libsmb/clirap.h"
44 #include "nsswitch/libwbclient/wbclient.h"
45 #include "passdb.h"
46 #include "../libcli/smb/smbXcli_base.h"
48 static int net_mode_share;
49 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
51 /**
52 * @file net_rpc.c
54 * @brief RPC based subcommands for the 'net' utility.
56 * This file should contain much of the functionality that used to
57 * be found in rpcclient, execpt that the commands should change
58 * less often, and the fucntionality should be sane (the user is not
59 * expected to know a rid/sid before they conduct an operation etc.)
61 * @todo Perhaps eventually these should be split out into a number
62 * of files, as this could get quite big.
63 **/
66 /**
67 * Many of the RPC functions need the domain sid. This function gets
68 * it at the start of every run
70 * @param cli A cli_state already connected to the remote machine
72 * @return The Domain SID of the remote machine.
73 **/
75 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
76 struct dom_sid **domain_sid,
77 const char **domain_name)
79 struct rpc_pipe_client *lsa_pipe = NULL;
80 struct policy_handle pol;
81 NTSTATUS status, result;
82 union lsa_PolicyInformation *info = NULL;
83 struct dcerpc_binding_handle *b;
85 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
86 &lsa_pipe);
87 if (!NT_STATUS_IS_OK(status)) {
88 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
89 return status;
92 b = lsa_pipe->binding_handle;
94 status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
95 SEC_FLAG_MAXIMUM_ALLOWED,
96 &pol);
97 if (!NT_STATUS_IS_OK(status)) {
98 d_fprintf(stderr, "open_policy %s: %s\n",
99 _("failed"),
100 nt_errstr(status));
101 return status;
104 status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
105 &pol,
106 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
107 &info,
108 &result);
109 if (!NT_STATUS_IS_OK(status)) {
110 d_fprintf(stderr, "lsaquery %s: %s\n",
111 _("failed"),
112 nt_errstr(status));
113 return status;
115 if (!NT_STATUS_IS_OK(result)) {
116 d_fprintf(stderr, "lsaquery %s: %s\n",
117 _("failed"),
118 nt_errstr(result));
119 return result;
122 *domain_name = info->account_domain.name.string;
123 *domain_sid = info->account_domain.sid;
125 dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
126 TALLOC_FREE(lsa_pipe);
128 return NT_STATUS_OK;
132 * Run a single RPC command, from start to finish.
134 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
135 * @param conn_flag a NET_FLAG_ combination. Passed to
136 * net_make_ipc_connection.
137 * @param argc Standard main() style argc.
138 * @param argv Standard main() style argv. Initial components are already
139 * stripped.
140 * @return A shell status integer (0 for success).
143 int run_rpc_command(struct net_context *c,
144 struct cli_state *cli_arg,
145 const struct ndr_interface_table *table,
146 int conn_flags,
147 rpc_command_fn fn,
148 int argc,
149 const char **argv)
151 struct cli_state *cli = NULL;
152 struct rpc_pipe_client *pipe_hnd = NULL;
153 TALLOC_CTX *mem_ctx;
154 NTSTATUS nt_status;
155 struct dom_sid *domain_sid;
156 const char *domain_name;
157 int ret = -1;
159 /* make use of cli_state handed over as an argument, if possible */
160 if (!cli_arg) {
161 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
162 if (!NT_STATUS_IS_OK(nt_status)) {
163 DEBUG(1, ("failed to make ipc connection: %s\n",
164 nt_errstr(nt_status)));
165 return -1;
167 } else {
168 cli = cli_arg;
171 if (!cli) {
172 return -1;
175 /* Create mem_ctx */
177 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
178 DEBUG(0, ("talloc_init() failed\n"));
179 goto fail;
182 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
183 &domain_name);
184 if (!NT_STATUS_IS_OK(nt_status)) {
185 goto fail;
188 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
189 if (lp_client_schannel()
190 && (ndr_syntax_id_equal(&table->syntax_id,
191 &ndr_table_netlogon.syntax_id))) {
192 /* Always try and create an schannel netlogon pipe. */
193 nt_status = cli_rpc_pipe_open_schannel(
194 cli, &table->syntax_id, NCACN_NP,
195 DCERPC_AUTH_LEVEL_PRIVACY, domain_name,
196 &pipe_hnd);
197 if (!NT_STATUS_IS_OK(nt_status)) {
198 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
199 nt_errstr(nt_status) ));
200 goto fail;
202 } else {
203 if (conn_flags & NET_FLAGS_SEAL) {
204 nt_status = cli_rpc_pipe_open_generic_auth(
205 cli, table,
206 (conn_flags & NET_FLAGS_TCP) ?
207 NCACN_IP_TCP : NCACN_NP,
208 DCERPC_AUTH_TYPE_NTLMSSP,
209 DCERPC_AUTH_LEVEL_PRIVACY,
210 smbXcli_conn_remote_name(cli->conn),
211 lp_workgroup(), c->opt_user_name,
212 c->opt_password, &pipe_hnd);
213 } else {
214 nt_status = cli_rpc_pipe_open_noauth(
215 cli, &table->syntax_id,
216 &pipe_hnd);
218 if (!NT_STATUS_IS_OK(nt_status)) {
219 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
220 table->name,
221 nt_errstr(nt_status) ));
222 goto fail;
227 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
229 if (!NT_STATUS_IS_OK(nt_status)) {
230 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
231 } else {
232 ret = 0;
233 DEBUG(5, ("rpc command function succedded\n"));
236 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
237 if (pipe_hnd) {
238 TALLOC_FREE(pipe_hnd);
242 fail:
243 /* close the connection only if it was opened here */
244 if (!cli_arg) {
245 cli_shutdown(cli);
248 talloc_destroy(mem_ctx);
249 return ret;
253 * Force a change of the trust acccount password.
255 * All parameters are provided by the run_rpc_command function, except for
256 * argc, argv which are passed through.
258 * @param domain_sid The domain sid acquired from the remote server.
259 * @param cli A cli_state connected to the server.
260 * @param mem_ctx Talloc context, destroyed on completion of the function.
261 * @param argc Standard main() style argc.
262 * @param argv Standard main() style argv. Initial components are already
263 * stripped.
265 * @return Normal NTSTATUS return.
268 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
269 const struct dom_sid *domain_sid,
270 const char *domain_name,
271 struct cli_state *cli,
272 struct rpc_pipe_client *pipe_hnd,
273 TALLOC_CTX *mem_ctx,
274 int argc,
275 const char **argv)
277 NTSTATUS status;
279 status = trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
280 if (!NT_STATUS_IS_OK(status)) {
281 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
282 nt_errstr(status));
283 return status;
286 return NT_STATUS_OK;
290 * Force a change of the trust acccount password.
292 * @param argc Standard main() style argc.
293 * @param argv Standard main() style argv. Initial components are already
294 * stripped.
296 * @return A shell status integer (0 for success).
299 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
301 if (c->display_usage) {
302 d_printf( "%s\n"
303 "net rpc changetrustpw\n"
304 " %s\n",
305 _("Usage:"),
306 _("Change the machine trust password"));
307 return 0;
310 return run_rpc_command(c, NULL, &ndr_table_netlogon,
311 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
312 rpc_changetrustpw_internals,
313 argc, argv);
317 * Join a domain, the old way.
319 * This uses 'machinename' as the inital password, and changes it.
321 * The password should be created with 'server manager' or equiv first.
323 * All parameters are provided by the run_rpc_command function, except for
324 * argc, argv which are passed through.
326 * @param domain_sid The domain sid acquired from the remote server.
327 * @param cli A cli_state connected to the server.
328 * @param mem_ctx Talloc context, destroyed on completion of the function.
329 * @param argc Standard main() style argc.
330 * @param argv Standard main() style argv. Initial components are already
331 * stripped.
333 * @return Normal NTSTATUS return.
336 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
337 const struct dom_sid *domain_sid,
338 const char *domain_name,
339 struct cli_state *cli,
340 struct rpc_pipe_client *pipe_hnd,
341 TALLOC_CTX *mem_ctx,
342 int argc,
343 const char **argv)
346 fstring trust_passwd;
347 unsigned char orig_trust_passwd_hash[16];
348 NTSTATUS result;
349 enum netr_SchannelType sec_channel_type;
351 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
352 &pipe_hnd);
353 if (!NT_STATUS_IS_OK(result)) {
354 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
355 "error was %s\n",
356 smbXcli_conn_remote_name(cli->conn),
357 nt_errstr(result) ));
358 return result;
362 check what type of join - if the user want's to join as
363 a BDC, the server must agree that we are a BDC.
365 if (argc >= 0) {
366 sec_channel_type = get_sec_channel_type(argv[0]);
367 } else {
368 sec_channel_type = get_sec_channel_type(NULL);
371 fstrcpy(trust_passwd, lp_netbios_name());
372 strlower_m(trust_passwd);
375 * Machine names can be 15 characters, but the max length on
376 * a password is 14. --jerry
379 trust_passwd[14] = '\0';
381 E_md4hash(trust_passwd, orig_trust_passwd_hash);
383 result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
384 lp_netbios_name(),
385 orig_trust_passwd_hash,
386 sec_channel_type);
388 if (NT_STATUS_IS_OK(result))
389 printf(_("Joined domain %s.\n"), c->opt_target_workgroup);
392 if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
393 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
394 result = NT_STATUS_UNSUCCESSFUL;
397 return result;
401 * Join a domain, the old way.
403 * @param argc Standard main() style argc.
404 * @param argv Standard main() style argv. Initial components are already
405 * stripped.
407 * @return A shell status integer (0 for success).
410 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
412 return run_rpc_command(c, NULL, &ndr_table_netlogon,
413 NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
414 rpc_oldjoin_internals,
415 argc, argv);
419 * Join a domain, the old way. This function exists to allow
420 * the message to be displayed when oldjoin was explicitly
421 * requested, but not when it was implied by "net rpc join".
423 * @param argc Standard main() style argc.
424 * @param argv Standard main() style argv. Initial components are already
425 * stripped.
427 * @return A shell status integer (0 for success).
430 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
432 int rc = -1;
434 if (c->display_usage) {
435 d_printf( "%s\n"
436 "net rpc oldjoin\n"
437 " %s\n",
438 _("Usage:"),
439 _("Join a domain the old way"));
440 return 0;
443 rc = net_rpc_perform_oldjoin(c, argc, argv);
445 if (rc) {
446 d_fprintf(stderr, _("Failed to join domain\n"));
449 return rc;
453 * 'net rpc join' entrypoint.
454 * @param argc Standard main() style argc.
455 * @param argv Standard main() style argv. Initial components are already
456 * stripped
458 * Main 'net_rpc_join()' (where the admin username/password is used) is
459 * in net_rpc_join.c.
460 * Try to just change the password, but if that doesn't work, use/prompt
461 * for a username/password.
464 int net_rpc_join(struct net_context *c, int argc, const char **argv)
466 if (c->display_usage) {
467 d_printf("%s\n%s",
468 _("Usage:"),
469 _("net rpc join -U <username>[%%password] <type>\n"
470 " Join a domain\n"
471 " username\tName of the admin user"
472 " password\tPassword of the admin user, will "
473 "prompt if not specified\n"
474 " type\tCan be one of the following:\n"
475 "\t\tMEMBER\tJoin as member server (default)\n"
476 "\t\tBDC\tJoin as BDC\n"
477 "\t\tPDC\tJoin as PDC\n"));
478 return 0;
481 if (lp_server_role() == ROLE_STANDALONE) {
482 d_printf(_("cannot join as standalone machine\n"));
483 return -1;
486 if (strlen(lp_netbios_name()) > 15) {
487 d_printf(_("Our netbios name can be at most 15 chars long, "
488 "\"%s\" is %u chars long\n"),
489 lp_netbios_name(), (unsigned int)strlen(lp_netbios_name()));
490 return -1;
493 if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
494 return 0;
496 return net_rpc_join_newstyle(c, argc, argv);
500 * display info about a rpc domain
502 * All parameters are provided by the run_rpc_command function, except for
503 * argc, argv which are passed through.
505 * @param domain_sid The domain sid acquired from the remote server
506 * @param cli A cli_state connected to the server.
507 * @param mem_ctx Talloc context, destroyed on completion of the function.
508 * @param argc Standard main() style argc.
509 * @param argv Standard main() style argv. Initial components are already
510 * stripped.
512 * @return Normal NTSTATUS return.
515 NTSTATUS rpc_info_internals(struct net_context *c,
516 const struct dom_sid *domain_sid,
517 const char *domain_name,
518 struct cli_state *cli,
519 struct rpc_pipe_client *pipe_hnd,
520 TALLOC_CTX *mem_ctx,
521 int argc,
522 const char **argv)
524 struct policy_handle connect_pol, domain_pol;
525 NTSTATUS status, result;
526 union samr_DomainInfo *info = NULL;
527 fstring sid_str;
528 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
530 sid_to_fstring(sid_str, domain_sid);
532 /* Get sam policy handle */
533 status = dcerpc_samr_Connect2(b, mem_ctx,
534 pipe_hnd->desthost,
535 MAXIMUM_ALLOWED_ACCESS,
536 &connect_pol,
537 &result);
538 if (!NT_STATUS_IS_OK(status)) {
539 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
540 nt_errstr(status));
541 goto done;
544 if (!NT_STATUS_IS_OK(result)) {
545 status = result;
546 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
547 nt_errstr(result));
548 goto done;
551 /* Get domain policy handle */
552 status = dcerpc_samr_OpenDomain(b, mem_ctx,
553 &connect_pol,
554 MAXIMUM_ALLOWED_ACCESS,
555 discard_const_p(struct dom_sid2, domain_sid),
556 &domain_pol,
557 &result);
558 if (!NT_STATUS_IS_OK(status)) {
559 d_fprintf(stderr, _("Could not open domain: %s\n"),
560 nt_errstr(status));
561 goto done;
563 if (!NT_STATUS_IS_OK(result)) {
564 status = result;
565 d_fprintf(stderr, _("Could not open domain: %s\n"),
566 nt_errstr(result));
567 goto done;
570 status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
571 &domain_pol,
573 &info,
574 &result);
575 if (!NT_STATUS_IS_OK(status)) {
576 goto done;
578 status = result;
579 if (NT_STATUS_IS_OK(result)) {
580 d_printf(_("Domain Name: %s\n"),
581 info->general.domain_name.string);
582 d_printf(_("Domain SID: %s\n"), sid_str);
583 d_printf(_("Sequence number: %llu\n"),
584 (unsigned long long)info->general.sequence_num);
585 d_printf(_("Num users: %u\n"), info->general.num_users);
586 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
587 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
590 done:
591 return status;
595 * 'net rpc info' entrypoint.
596 * @param argc Standard main() style argc.
597 * @param argv Standard main() style argv. Initial components are already
598 * stripped.
601 int net_rpc_info(struct net_context *c, int argc, const char **argv)
603 if (c->display_usage) {
604 d_printf( "%s\n"
605 "net rpc info\n"
606 " %s\n",
607 _("Usage:"),
608 _("Display information about the domain"));
609 return 0;
612 return run_rpc_command(c, NULL, &ndr_table_samr,
613 NET_FLAGS_PDC, rpc_info_internals,
614 argc, argv);
618 * Fetch domain SID into the local secrets.tdb.
620 * All parameters are provided by the run_rpc_command function, except for
621 * argc, argv which are passed through.
623 * @param domain_sid The domain sid acquired from the remote server.
624 * @param cli A cli_state connected to the server.
625 * @param mem_ctx Talloc context, destroyed on completion of the function.
626 * @param argc Standard main() style argc.
627 * @param argv Standard main() style argv. Initial components are already
628 * stripped.
630 * @return Normal NTSTATUS return.
633 static NTSTATUS rpc_getsid_internals(struct net_context *c,
634 const struct dom_sid *domain_sid,
635 const char *domain_name,
636 struct cli_state *cli,
637 struct rpc_pipe_client *pipe_hnd,
638 TALLOC_CTX *mem_ctx,
639 int argc,
640 const char **argv)
642 fstring sid_str;
644 sid_to_fstring(sid_str, domain_sid);
645 d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
646 sid_str, domain_name);
648 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
649 DEBUG(0,("Can't store domain SID\n"));
650 return NT_STATUS_UNSUCCESSFUL;
653 return NT_STATUS_OK;
657 * 'net rpc getsid' entrypoint.
658 * @param argc Standard main() style argc.
659 * @param argv Standard main() style argv. Initial components are already
660 * stripped.
663 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
665 int conn_flags = NET_FLAGS_PDC;
667 if (!c->opt_user_specified) {
668 conn_flags |= NET_FLAGS_ANONYMOUS;
671 if (c->display_usage) {
672 d_printf( "%s\n"
673 "net rpc getsid\n"
674 " %s\n",
675 _("Usage:"),
676 _("Fetch domain SID into local secrets.tdb"));
677 return 0;
680 return run_rpc_command(c, NULL, &ndr_table_samr,
681 conn_flags,
682 rpc_getsid_internals,
683 argc, argv);
686 /****************************************************************************/
689 * Basic usage function for 'net rpc user'.
690 * @param argc Standard main() style argc.
691 * @param argv Standard main() style argv. Initial components are already
692 * stripped.
695 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
697 return net_user_usage(c, argc, argv);
701 * Add a new user to a remote RPC server.
703 * @param argc Standard main() style argc.
704 * @param argv Standard main() style argv. Initial components are already
705 * stripped.
707 * @return A shell status integer (0 for success).
710 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
712 NET_API_STATUS status;
713 struct USER_INFO_1 info1;
714 uint32_t parm_error = 0;
716 if (argc < 1 || c->display_usage) {
717 rpc_user_usage(c, argc, argv);
718 return 0;
721 ZERO_STRUCT(info1);
723 info1.usri1_name = argv[0];
724 if (argc == 2) {
725 info1.usri1_password = argv[1];
728 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
730 if (status != 0) {
731 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
732 argv[0], libnetapi_get_error_string(c->netapi_ctx,
733 status));
734 return -1;
735 } else {
736 d_printf(_("Added user '%s'.\n"), argv[0]);
739 return 0;
743 * Rename a user on a remote RPC server.
745 * @param argc Standard main() style argc.
746 * @param argv Standard main() style argv. Initial components are already
747 * stripped.
749 * @return A shell status integer (0 for success).
752 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
754 NET_API_STATUS status;
755 struct USER_INFO_0 u0;
756 uint32_t parm_err = 0;
758 if (argc != 2 || c->display_usage) {
759 rpc_user_usage(c, argc, argv);
760 return 0;
763 u0.usri0_name = argv[1];
765 status = NetUserSetInfo(c->opt_host, argv[0],
766 0, (uint8_t *)&u0, &parm_err);
767 if (status) {
768 d_fprintf(stderr,
769 _("Failed to rename user from %s to %s - %s\n"),
770 argv[0], argv[1],
771 libnetapi_get_error_string(c->netapi_ctx, status));
772 } else {
773 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
776 return status;
780 * Set a user's primary group
782 * @param argc Standard main() style argc.
783 * @param argv Standard main() style argv. Initial components are already
784 * stripped.
786 * @return A shell status integer (0 for success).
789 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
790 const char **argv)
792 NET_API_STATUS status;
793 uint8_t *buffer;
794 struct GROUP_INFO_2 *g2;
795 struct USER_INFO_1051 u1051;
796 uint32_t parm_err = 0;
798 if (argc != 2 || c->display_usage) {
799 rpc_user_usage(c, argc, argv);
800 return 0;
803 status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
804 if (status) {
805 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
806 argv[1],
807 libnetapi_get_error_string(c->netapi_ctx, status));
808 return status;
810 g2 = (struct GROUP_INFO_2 *)buffer;
812 u1051.usri1051_primary_group_id = g2->grpi2_group_id;
814 NetApiBufferFree(buffer);
816 status = NetUserSetInfo(c->opt_host, argv[0], 1051,
817 (uint8_t *)&u1051, &parm_err);
818 if (status) {
819 d_fprintf(stderr,
820 _("Failed to set user's primary group %s to %s - "
821 "%s\n"), argv[0], argv[1],
822 libnetapi_get_error_string(c->netapi_ctx, status));
823 } else {
824 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
825 argv[1]);
827 return status;
831 * Delete a user from a remote RPC server.
833 * @param argc Standard main() style argc.
834 * @param argv Standard main() style argv. Initial components are already
835 * stripped.
837 * @return A shell status integer (0 for success).
840 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
842 NET_API_STATUS status;
844 if (argc < 1 || c->display_usage) {
845 rpc_user_usage(c, argc, argv);
846 return 0;
849 status = NetUserDel(c->opt_host, argv[0]);
851 if (status != 0) {
852 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
853 argv[0],
854 libnetapi_get_error_string(c->netapi_ctx, status));
855 return -1;
856 } else {
857 d_printf(_("Deleted user '%s'.\n"), argv[0]);
860 return 0;
864 * Set a user's password on a remote RPC server.
866 * @param argc Standard main() style argc.
867 * @param argv Standard main() style argv. Initial components are already
868 * stripped.
870 * @return A shell status integer (0 for success).
873 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
875 NET_API_STATUS status;
876 char *prompt = NULL;
877 struct USER_INFO_1003 u1003;
878 uint32_t parm_err = 0;
879 int ret;
881 if (argc < 1 || c->display_usage) {
882 rpc_user_usage(c, argc, argv);
883 return 0;
886 if (argv[1]) {
887 u1003.usri1003_password = argv[1];
888 } else {
889 ret = asprintf(&prompt, _("Enter new password for %s:"),
890 argv[0]);
891 if (ret == -1) {
892 return -1;
894 u1003.usri1003_password = talloc_strdup(c, getpass(prompt));
895 SAFE_FREE(prompt);
896 if (u1003.usri1003_password == NULL) {
897 return -1;
901 status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
903 /* Display results */
904 if (status != 0) {
905 d_fprintf(stderr,
906 _("Failed to set password for '%s' with error: %s.\n"),
907 argv[0], libnetapi_get_error_string(c->netapi_ctx,
908 status));
909 return -1;
912 return 0;
916 * List a user's groups from a remote RPC server.
918 * @param argc Standard main() style argc.
919 * @param argv Standard main() style argv. Initial components are already
920 * stripped.
922 * @return A shell status integer (0 for success)
925 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
928 NET_API_STATUS status;
929 struct GROUP_USERS_INFO_0 *u0 = NULL;
930 uint32_t entries_read = 0;
931 uint32_t total_entries = 0;
932 int i;
935 if (argc < 1 || c->display_usage) {
936 rpc_user_usage(c, argc, argv);
937 return 0;
940 status = NetUserGetGroups(c->opt_host,
941 argv[0],
943 (uint8_t **)(void *)&u0,
944 (uint32_t)-1,
945 &entries_read,
946 &total_entries);
947 if (status != 0) {
948 d_fprintf(stderr,
949 _("Failed to get groups for '%s' with error: %s.\n"),
950 argv[0], libnetapi_get_error_string(c->netapi_ctx,
951 status));
952 return -1;
955 for (i=0; i < entries_read; i++) {
956 printf("%s\n", u0->grui0_name);
957 u0++;
960 return 0;
964 * List users on a remote RPC server.
966 * All parameters are provided by the run_rpc_command function, except for
967 * argc, argv which are passed through.
969 * @param domain_sid The domain sid acquired from the remote server.
970 * @param cli A cli_state connected to the server.
971 * @param mem_ctx Talloc context, destroyed on completion of the function.
972 * @param argc Standard main() style argc.
973 * @param argv Standard main() style argv. Initial components are already
974 * stripped.
976 * @return Normal NTSTATUS return.
979 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
981 NET_API_STATUS status;
982 uint32_t start_idx=0, num_entries, i, loop_count = 0;
983 struct NET_DISPLAY_USER *info = NULL;
984 void *buffer = NULL;
986 /* Query domain users */
987 if (c->opt_long_list_entries)
988 d_printf(_("\nUser name Comment"
989 "\n-----------------------------\n"));
990 do {
991 uint32_t max_entries, max_size;
993 dcerpc_get_query_dispinfo_params(
994 loop_count, &max_entries, &max_size);
996 status = NetQueryDisplayInformation(c->opt_host,
998 start_idx,
999 max_entries,
1000 max_size,
1001 &num_entries,
1002 &buffer);
1003 if (status != 0 && status != ERROR_MORE_DATA) {
1004 return status;
1007 info = (struct NET_DISPLAY_USER *)buffer;
1009 for (i = 0; i < num_entries; i++) {
1011 if (c->opt_long_list_entries)
1012 printf("%-21.21s %s\n", info->usri1_name,
1013 info->usri1_comment);
1014 else
1015 printf("%s\n", info->usri1_name);
1016 info++;
1019 NetApiBufferFree(buffer);
1021 loop_count++;
1022 start_idx += num_entries;
1024 } while (status == ERROR_MORE_DATA);
1026 return status;
1030 * 'net rpc user' entrypoint.
1031 * @param argc Standard main() style argc.
1032 * @param argv Standard main() style argv. Initial components are already
1033 * stripped.
1036 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1038 NET_API_STATUS status;
1040 struct functable func[] = {
1042 "add",
1043 rpc_user_add,
1044 NET_TRANSPORT_RPC,
1045 N_("Add specified user"),
1046 N_("net rpc user add\n"
1047 " Add specified user")
1050 "info",
1051 rpc_user_info,
1052 NET_TRANSPORT_RPC,
1053 N_("List domain groups of user"),
1054 N_("net rpc user info\n"
1055 " List domain groups of user")
1058 "delete",
1059 rpc_user_delete,
1060 NET_TRANSPORT_RPC,
1061 N_("Remove specified user"),
1062 N_("net rpc user delete\n"
1063 " Remove specified user")
1066 "password",
1067 rpc_user_password,
1068 NET_TRANSPORT_RPC,
1069 N_("Change user password"),
1070 N_("net rpc user password\n"
1071 " Change user password")
1074 "rename",
1075 rpc_user_rename,
1076 NET_TRANSPORT_RPC,
1077 N_("Rename specified user"),
1078 N_("net rpc user rename\n"
1079 " Rename specified user")
1082 "setprimarygroup",
1083 rpc_user_setprimarygroup,
1084 NET_TRANSPORT_RPC,
1085 "Set a user's primary group",
1086 "net rpc user setprimarygroup\n"
1087 " Set a user's primary group"
1089 {NULL, NULL, 0, NULL, NULL}
1092 status = libnetapi_net_init(&c->netapi_ctx);
1093 if (status != 0) {
1094 return -1;
1096 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1097 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1098 if (c->opt_kerberos) {
1099 libnetapi_set_use_kerberos(c->netapi_ctx);
1102 if (argc == 0) {
1103 if (c->display_usage) {
1104 d_printf( "%s\n"
1105 "net rpc user\n"
1106 " %s\n",
1107 _("Usage:"),
1108 _("List all users"));
1109 net_display_usage_from_functable(func);
1110 return 0;
1113 return rpc_user_list(c, argc, argv);
1116 return net_run_function(c, argc, argv, "net rpc user", func);
1119 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1120 TALLOC_CTX *mem_ctx,
1121 struct rpc_sh_ctx *ctx,
1122 struct rpc_pipe_client *pipe_hnd,
1123 int argc, const char **argv)
1125 return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1128 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1129 TALLOC_CTX *mem_ctx,
1130 struct rpc_sh_ctx *ctx,
1131 struct rpc_pipe_client *pipe_hnd,
1132 int argc, const char **argv)
1134 return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1137 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1138 TALLOC_CTX *mem_ctx,
1139 struct rpc_sh_ctx *ctx,
1140 struct rpc_pipe_client *pipe_hnd,
1141 int argc, const char **argv,
1142 NTSTATUS (*fn)(
1143 struct net_context *c,
1144 TALLOC_CTX *mem_ctx,
1145 struct rpc_sh_ctx *ctx,
1146 struct rpc_pipe_client *pipe_hnd,
1147 struct policy_handle *user_hnd,
1148 int argc, const char **argv))
1150 struct policy_handle connect_pol, domain_pol, user_pol;
1151 NTSTATUS status, result;
1152 struct dom_sid sid;
1153 uint32 rid;
1154 enum lsa_SidType type;
1155 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1157 if (argc == 0) {
1158 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1159 ctx->whoami);
1160 return NT_STATUS_INVALID_PARAMETER;
1163 ZERO_STRUCT(connect_pol);
1164 ZERO_STRUCT(domain_pol);
1165 ZERO_STRUCT(user_pol);
1167 status = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1168 argv[0], NULL, NULL, &sid, &type);
1169 if (!NT_STATUS_IS_OK(status)) {
1170 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1171 nt_errstr(status));
1172 goto done;
1175 if (type != SID_NAME_USER) {
1176 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1177 sid_type_lookup(type));
1178 status = NT_STATUS_NO_SUCH_USER;
1179 goto done;
1182 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1183 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1184 status = NT_STATUS_NO_SUCH_USER;
1185 goto done;
1188 status = dcerpc_samr_Connect2(b, mem_ctx,
1189 pipe_hnd->desthost,
1190 MAXIMUM_ALLOWED_ACCESS,
1191 &connect_pol,
1192 &result);
1193 if (!NT_STATUS_IS_OK(status)) {
1194 goto done;
1196 if (!NT_STATUS_IS_OK(result)) {
1197 status = result;
1198 goto done;
1201 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1202 &connect_pol,
1203 MAXIMUM_ALLOWED_ACCESS,
1204 ctx->domain_sid,
1205 &domain_pol,
1206 &result);
1207 if (!NT_STATUS_IS_OK(status)) {
1208 goto done;
1210 if (!NT_STATUS_IS_OK(result)) {
1211 status = result;
1212 goto done;
1215 status = dcerpc_samr_OpenUser(b, mem_ctx,
1216 &domain_pol,
1217 MAXIMUM_ALLOWED_ACCESS,
1218 rid,
1219 &user_pol,
1220 &result);
1221 if (!NT_STATUS_IS_OK(status)) {
1222 goto done;
1224 if (!NT_STATUS_IS_OK(result)) {
1225 status = result;
1226 goto done;
1229 status = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1231 done:
1232 if (is_valid_policy_hnd(&user_pol)) {
1233 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1235 if (is_valid_policy_hnd(&domain_pol)) {
1236 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1238 if (is_valid_policy_hnd(&connect_pol)) {
1239 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
1241 return status;
1244 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1245 TALLOC_CTX *mem_ctx,
1246 struct rpc_sh_ctx *ctx,
1247 struct rpc_pipe_client *pipe_hnd,
1248 struct policy_handle *user_hnd,
1249 int argc, const char **argv)
1251 NTSTATUS status, result;
1252 union samr_UserInfo *info = NULL;
1253 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1255 if (argc != 0) {
1256 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1257 ctx->whoami);
1258 return NT_STATUS_INVALID_PARAMETER;
1261 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1262 user_hnd,
1264 &info,
1265 &result);
1266 if (!NT_STATUS_IS_OK(status)) {
1267 return status;
1269 if (!NT_STATUS_IS_OK(result)) {
1270 return result;
1273 d_printf(_("user rid: %d, group rid: %d\n"),
1274 info->info21.rid,
1275 info->info21.primary_gid);
1277 return result;
1280 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1281 TALLOC_CTX *mem_ctx,
1282 struct rpc_sh_ctx *ctx,
1283 struct rpc_pipe_client *pipe_hnd,
1284 int argc, const char **argv)
1286 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1287 rpc_sh_user_show_internals);
1290 #define FETCHSTR(name, rec) \
1291 do { if (strequal(ctx->thiscmd, name)) { \
1292 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1293 } while (0);
1295 #define SETSTR(name, rec, flag) \
1296 do { if (strequal(ctx->thiscmd, name)) { \
1297 init_lsa_String(&(info->info21.rec), argv[0]); \
1298 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1299 } while (0);
1301 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1302 TALLOC_CTX *mem_ctx,
1303 struct rpc_sh_ctx *ctx,
1304 struct rpc_pipe_client *pipe_hnd,
1305 struct policy_handle *user_hnd,
1306 int argc, const char **argv)
1308 NTSTATUS status, result;
1309 const char *username;
1310 const char *oldval = "";
1311 union samr_UserInfo *info = NULL;
1312 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1314 if (argc > 1) {
1315 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1316 _("Usage:"), ctx->whoami);
1317 return NT_STATUS_INVALID_PARAMETER;
1320 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1321 user_hnd,
1323 &info,
1324 &result);
1325 if (!NT_STATUS_IS_OK(status)) {
1326 return status;
1328 if (!NT_STATUS_IS_OK(result)) {
1329 return result;
1332 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1334 FETCHSTR("fullname", full_name);
1335 FETCHSTR("homedir", home_directory);
1336 FETCHSTR("homedrive", home_drive);
1337 FETCHSTR("logonscript", logon_script);
1338 FETCHSTR("profilepath", profile_path);
1339 FETCHSTR("description", description);
1341 if (argc == 0) {
1342 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1343 goto done;
1346 if (strcmp(argv[0], "NULL") == 0) {
1347 argv[0] = "";
1350 ZERO_STRUCT(info->info21);
1352 SETSTR("fullname", full_name, FULL_NAME);
1353 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1354 SETSTR("homedrive", home_drive, HOME_DRIVE);
1355 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1356 SETSTR("profilepath", profile_path, PROFILE_PATH);
1357 SETSTR("description", description, DESCRIPTION);
1359 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1360 user_hnd,
1362 info,
1363 &result);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 return status;
1368 status = result;
1370 d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1371 ctx->thiscmd, oldval, argv[0]);
1373 done:
1375 return status;
1378 #define HANDLEFLG(name, rec) \
1379 do { if (strequal(ctx->thiscmd, name)) { \
1380 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1381 if (newval) { \
1382 newflags = oldflags | ACB_##rec; \
1383 } else { \
1384 newflags = oldflags & ~ACB_##rec; \
1385 } } } while (0);
1387 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1388 TALLOC_CTX *mem_ctx,
1389 struct rpc_sh_ctx *ctx,
1390 struct rpc_pipe_client *pipe_hnd,
1391 int argc, const char **argv)
1393 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1394 rpc_sh_user_str_edit_internals);
1397 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1398 TALLOC_CTX *mem_ctx,
1399 struct rpc_sh_ctx *ctx,
1400 struct rpc_pipe_client *pipe_hnd,
1401 struct policy_handle *user_hnd,
1402 int argc, const char **argv)
1404 NTSTATUS status, result;
1405 const char *username;
1406 const char *oldval = "unknown";
1407 uint32 oldflags, newflags;
1408 bool newval;
1409 union samr_UserInfo *info = NULL;
1410 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1412 if ((argc > 1) ||
1413 ((argc == 1) && !strequal(argv[0], "yes") &&
1414 !strequal(argv[0], "no"))) {
1415 /* TRANSATORS: The yes|no here are program keywords. Please do
1416 not translate. */
1417 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1418 ctx->whoami);
1419 return NT_STATUS_INVALID_PARAMETER;
1422 newval = strequal(argv[0], "yes");
1424 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1425 user_hnd,
1427 &info,
1428 &result);
1429 if (!NT_STATUS_IS_OK(status)) {
1430 return status;
1432 if (!NT_STATUS_IS_OK(result)) {
1433 return result;
1436 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1437 oldflags = info->info21.acct_flags;
1438 newflags = info->info21.acct_flags;
1440 HANDLEFLG("disabled", DISABLED);
1441 HANDLEFLG("pwnotreq", PWNOTREQ);
1442 HANDLEFLG("autolock", AUTOLOCK);
1443 HANDLEFLG("pwnoexp", PWNOEXP);
1445 if (argc == 0) {
1446 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1447 oldval);
1448 goto done;
1451 ZERO_STRUCT(info->info21);
1453 info->info21.acct_flags = newflags;
1454 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1456 status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1457 user_hnd,
1459 info,
1460 &result);
1461 if (!NT_STATUS_IS_OK(status)) {
1462 goto done;
1464 status = result;
1465 if (NT_STATUS_IS_OK(result)) {
1466 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1467 ctx->thiscmd, oldval, argv[0]);
1470 done:
1472 return status;
1475 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1476 TALLOC_CTX *mem_ctx,
1477 struct rpc_sh_ctx *ctx,
1478 struct rpc_pipe_client *pipe_hnd,
1479 int argc, const char **argv)
1481 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1482 rpc_sh_user_flag_edit_internals);
1485 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1486 TALLOC_CTX *mem_ctx,
1487 struct rpc_sh_ctx *ctx)
1489 static struct rpc_sh_cmd cmds[] = {
1491 { "fullname", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1492 N_("Show/Set a user's full name") },
1494 { "homedir", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1495 N_("Show/Set a user's home directory") },
1497 { "homedrive", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1498 N_("Show/Set a user's home drive") },
1500 { "logonscript", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1501 N_("Show/Set a user's logon script") },
1503 { "profilepath", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1504 N_("Show/Set a user's profile path") },
1506 { "description", NULL, &ndr_table_samr, rpc_sh_user_str_edit,
1507 N_("Show/Set a user's description") },
1509 { "disabled", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1510 N_("Show/Set whether a user is disabled") },
1512 { "autolock", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1513 N_("Show/Set whether a user locked out") },
1515 { "pwnotreq", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1516 N_("Show/Set whether a user does not need a password") },
1518 { "pwnoexp", NULL, &ndr_table_samr, rpc_sh_user_flag_edit,
1519 N_("Show/Set whether a user's password does not expire") },
1521 { NULL, NULL, 0, NULL, NULL }
1524 return cmds;
1527 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1528 TALLOC_CTX *mem_ctx,
1529 struct rpc_sh_ctx *ctx)
1531 static struct rpc_sh_cmd cmds[] = {
1533 { "list", NULL, &ndr_table_samr, rpc_sh_user_list,
1534 N_("List available users") },
1536 { "info", NULL, &ndr_table_samr, rpc_sh_user_info,
1537 N_("List the domain groups a user is member of") },
1539 { "show", NULL, &ndr_table_samr, rpc_sh_user_show,
1540 N_("Show info about a user") },
1542 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1543 N_("Show/Modify a user's fields") },
1545 { NULL, NULL, 0, NULL, NULL }
1548 return cmds;
1551 /****************************************************************************/
1554 * Basic usage function for 'net rpc group'.
1555 * @param argc Standard main() style argc.
1556 * @param argv Standard main() style argv. Initial components are already
1557 * stripped.
1560 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1562 return net_group_usage(c, argc, argv);
1566 * Delete group on a remote RPC server.
1568 * All parameters are provided by the run_rpc_command function, except for
1569 * argc, argv which are passed through.
1571 * @param domain_sid The domain sid acquired from the remote server.
1572 * @param cli A cli_state connected to the server.
1573 * @param mem_ctx Talloc context, destroyed on completion of the function.
1574 * @param argc Standard main() style argc.
1575 * @param argv Standard main() style argv. Initial components are already
1576 * stripped.
1578 * @return Normal NTSTATUS return.
1581 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1582 const struct dom_sid *domain_sid,
1583 const char *domain_name,
1584 struct cli_state *cli,
1585 struct rpc_pipe_client *pipe_hnd,
1586 TALLOC_CTX *mem_ctx,
1587 int argc,
1588 const char **argv)
1590 struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1591 bool group_is_primary = false;
1592 NTSTATUS status, result;
1593 uint32_t group_rid;
1594 struct samr_RidAttrArray *rids = NULL;
1595 /* char **names; */
1596 int i;
1597 /* struct samr_RidWithAttribute *user_gids; */
1598 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1600 struct samr_Ids group_rids, name_types;
1601 struct lsa_String lsa_acct_name;
1602 union samr_UserInfo *info = NULL;
1604 if (argc < 1 || c->display_usage) {
1605 rpc_group_usage(c, argc,argv);
1606 return NT_STATUS_OK; /* ok? */
1609 status = dcerpc_samr_Connect2(b, mem_ctx,
1610 pipe_hnd->desthost,
1611 MAXIMUM_ALLOWED_ACCESS,
1612 &connect_pol,
1613 &result);
1614 if (!NT_STATUS_IS_OK(status)) {
1615 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1616 goto done;
1619 if (!NT_STATUS_IS_OK(result)) {
1620 status = result;
1621 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1622 goto done;
1625 status = dcerpc_samr_OpenDomain(b, mem_ctx,
1626 &connect_pol,
1627 MAXIMUM_ALLOWED_ACCESS,
1628 discard_const_p(struct dom_sid2, domain_sid),
1629 &domain_pol,
1630 &result);
1631 if (!NT_STATUS_IS_OK(status)) {
1632 d_fprintf(stderr, _("Request open_domain failed\n"));
1633 goto done;
1636 if (!NT_STATUS_IS_OK(result)) {
1637 status = result;
1638 d_fprintf(stderr, _("Request open_domain failed\n"));
1639 goto done;
1642 init_lsa_String(&lsa_acct_name, argv[0]);
1644 status = dcerpc_samr_LookupNames(b, mem_ctx,
1645 &domain_pol,
1647 &lsa_acct_name,
1648 &group_rids,
1649 &name_types,
1650 &result);
1651 if (!NT_STATUS_IS_OK(status)) {
1652 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1653 goto done;
1656 if (!NT_STATUS_IS_OK(result)) {
1657 status = result;
1658 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1659 goto done;
1662 switch (name_types.ids[0])
1664 case SID_NAME_DOM_GRP:
1665 status = dcerpc_samr_OpenGroup(b, mem_ctx,
1666 &domain_pol,
1667 MAXIMUM_ALLOWED_ACCESS,
1668 group_rids.ids[0],
1669 &group_pol,
1670 &result);
1671 if (!NT_STATUS_IS_OK(status)) {
1672 d_fprintf(stderr, _("Request open_group failed"));
1673 goto done;
1676 if (!NT_STATUS_IS_OK(result)) {
1677 status = result;
1678 d_fprintf(stderr, _("Request open_group failed"));
1679 goto done;
1682 group_rid = group_rids.ids[0];
1684 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
1685 &group_pol,
1686 &rids,
1687 &result);
1688 if (!NT_STATUS_IS_OK(status)) {
1689 d_fprintf(stderr,
1690 _("Unable to query group members of %s"),
1691 argv[0]);
1692 goto done;
1695 if (!NT_STATUS_IS_OK(result)) {
1696 status = result;
1697 d_fprintf(stderr,
1698 _("Unable to query group members of %s"),
1699 argv[0]);
1700 goto done;
1703 if (c->opt_verbose) {
1704 d_printf(
1705 _("Domain Group %s (rid: %d) has %d members\n"),
1706 argv[0],group_rid, rids->count);
1709 /* Check if group is anyone's primary group */
1710 for (i = 0; i < rids->count; i++)
1712 status = dcerpc_samr_OpenUser(b, mem_ctx,
1713 &domain_pol,
1714 MAXIMUM_ALLOWED_ACCESS,
1715 rids->rids[i],
1716 &user_pol,
1717 &result);
1718 if (!NT_STATUS_IS_OK(status)) {
1719 d_fprintf(stderr,
1720 _("Unable to open group member %d\n"),
1721 rids->rids[i]);
1722 goto done;
1725 if (!NT_STATUS_IS_OK(result)) {
1726 status = result;
1727 d_fprintf(stderr,
1728 _("Unable to open group member %d\n"),
1729 rids->rids[i]);
1730 goto done;
1733 status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1734 &user_pol,
1736 &info,
1737 &result);
1738 if (!NT_STATUS_IS_OK(status)) {
1739 d_fprintf(stderr,
1740 _("Unable to lookup userinfo for group "
1741 "member %d\n"),
1742 rids->rids[i]);
1743 goto done;
1746 if (!NT_STATUS_IS_OK(result)) {
1747 status = result;
1748 d_fprintf(stderr,
1749 _("Unable to lookup userinfo for group "
1750 "member %d\n"),
1751 rids->rids[i]);
1752 goto done;
1755 if (info->info21.primary_gid == group_rid) {
1756 if (c->opt_verbose) {
1757 d_printf(_("Group is primary group "
1758 "of %s\n"),
1759 info->info21.account_name.string);
1761 group_is_primary = true;
1764 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1767 if (group_is_primary) {
1768 d_fprintf(stderr, _("Unable to delete group because "
1769 "some of it's members have it as primary "
1770 "group\n"));
1771 status = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1772 goto done;
1775 /* remove all group members */
1776 for (i = 0; i < rids->count; i++)
1778 if (c->opt_verbose)
1779 d_printf(_("Remove group member %d..."),
1780 rids->rids[i]);
1781 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
1782 &group_pol,
1783 rids->rids[i],
1784 &result);
1785 if (!NT_STATUS_IS_OK(status)) {
1786 goto done;
1788 status = result;
1789 if (NT_STATUS_IS_OK(result)) {
1790 if (c->opt_verbose)
1791 d_printf(_("ok\n"));
1792 } else {
1793 if (c->opt_verbose)
1794 d_printf("%s\n", _("failed"));
1795 goto done;
1799 status = dcerpc_samr_DeleteDomainGroup(b, mem_ctx,
1800 &group_pol,
1801 &result);
1802 if (!NT_STATUS_IS_OK(status)) {
1803 break;
1806 status = result;
1808 break;
1809 /* removing a local group is easier... */
1810 case SID_NAME_ALIAS:
1811 status = dcerpc_samr_OpenAlias(b, mem_ctx,
1812 &domain_pol,
1813 MAXIMUM_ALLOWED_ACCESS,
1814 group_rids.ids[0],
1815 &group_pol,
1816 &result);
1817 if (!NT_STATUS_IS_OK(status)) {
1818 d_fprintf(stderr, _("Request open_alias failed\n"));
1819 goto done;
1821 if (!NT_STATUS_IS_OK(result)) {
1822 status = result;
1823 d_fprintf(stderr, _("Request open_alias failed\n"));
1824 goto done;
1827 status = dcerpc_samr_DeleteDomAlias(b, mem_ctx,
1828 &group_pol,
1829 &result);
1830 if (!NT_STATUS_IS_OK(status)) {
1831 break;
1834 status = result;
1836 break;
1837 default:
1838 d_fprintf(stderr, _("%s is of type %s. This command is only "
1839 "for deleting local or global groups\n"),
1840 argv[0],sid_type_lookup(name_types.ids[0]));
1841 status = NT_STATUS_UNSUCCESSFUL;
1842 goto done;
1845 if (NT_STATUS_IS_OK(status)) {
1846 if (c->opt_verbose)
1847 d_printf(_("Deleted %s '%s'\n"),
1848 sid_type_lookup(name_types.ids[0]), argv[0]);
1849 } else {
1850 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
1851 get_friendly_nt_error_msg(status));
1854 done:
1855 return status;
1859 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1861 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
1862 rpc_group_delete_internals, argc,argv);
1865 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1867 NET_API_STATUS status;
1868 struct GROUP_INFO_1 info1;
1869 uint32_t parm_error = 0;
1871 if (argc != 1 || c->display_usage) {
1872 rpc_group_usage(c, argc, argv);
1873 return 0;
1876 ZERO_STRUCT(info1);
1878 info1.grpi1_name = argv[0];
1879 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1880 info1.grpi1_comment = c->opt_comment;
1883 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1885 if (status != 0) {
1886 d_fprintf(stderr,
1887 _("Failed to add group '%s' with error: %s.\n"),
1888 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1889 status));
1890 return -1;
1891 } else {
1892 d_printf(_("Added group '%s'.\n"), argv[0]);
1895 return 0;
1898 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
1900 NET_API_STATUS status;
1901 struct LOCALGROUP_INFO_1 info1;
1902 uint32_t parm_error = 0;
1904 if (argc != 1 || c->display_usage) {
1905 rpc_group_usage(c, argc, argv);
1906 return 0;
1909 ZERO_STRUCT(info1);
1911 info1.lgrpi1_name = argv[0];
1912 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1913 info1.lgrpi1_comment = c->opt_comment;
1916 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1918 if (status != 0) {
1919 d_fprintf(stderr,
1920 _("Failed to add alias '%s' with error: %s.\n"),
1921 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1922 status));
1923 return -1;
1924 } else {
1925 d_printf(_("Added alias '%s'.\n"), argv[0]);
1928 return 0;
1931 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1933 if (c->opt_localgroup)
1934 return rpc_alias_add_internals(c, argc, argv);
1936 return rpc_group_add_internals(c, argc, argv);
1939 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1940 TALLOC_CTX *mem_ctx,
1941 const char *name,
1942 struct dom_sid *sid,
1943 enum lsa_SidType *type)
1945 struct dom_sid *sids = NULL;
1946 enum lsa_SidType *types = NULL;
1947 struct rpc_pipe_client *pipe_hnd = NULL;
1948 struct policy_handle lsa_pol;
1949 NTSTATUS status, result;
1950 struct dcerpc_binding_handle *b;
1952 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1953 &pipe_hnd);
1954 if (!NT_STATUS_IS_OK(status)) {
1955 goto done;
1958 b = pipe_hnd->binding_handle;
1960 status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1961 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1963 if (!NT_STATUS_IS_OK(status)) {
1964 goto done;
1967 status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1968 &name, NULL, 1, &sids, &types);
1970 if (NT_STATUS_IS_OK(status)) {
1971 sid_copy(sid, &sids[0]);
1972 *type = types[0];
1975 dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
1977 done:
1978 if (pipe_hnd) {
1979 TALLOC_FREE(pipe_hnd);
1982 if (!NT_STATUS_IS_OK(status) && (strncasecmp_m(name, "S-", 2) == 0)) {
1984 /* Try as S-1-5-whatever */
1986 struct dom_sid tmp_sid;
1988 if (string_to_sid(&tmp_sid, name)) {
1989 sid_copy(sid, &tmp_sid);
1990 *type = SID_NAME_UNKNOWN;
1991 status = NT_STATUS_OK;
1995 return status;
1998 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
1999 TALLOC_CTX *mem_ctx,
2000 const struct dom_sid *group_sid,
2001 const char *member)
2003 struct policy_handle connect_pol, domain_pol;
2004 NTSTATUS status, result;
2005 uint32 group_rid;
2006 struct policy_handle group_pol;
2007 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2009 struct samr_Ids rids, rid_types;
2010 struct lsa_String lsa_acct_name;
2012 struct dom_sid sid;
2014 sid_copy(&sid, group_sid);
2016 if (!sid_split_rid(&sid, &group_rid)) {
2017 return NT_STATUS_UNSUCCESSFUL;
2020 /* Get sam policy handle */
2021 status = dcerpc_samr_Connect2(b, mem_ctx,
2022 pipe_hnd->desthost,
2023 MAXIMUM_ALLOWED_ACCESS,
2024 &connect_pol,
2025 &result);
2026 if (!NT_STATUS_IS_OK(status)) {
2027 return status;
2029 if (!NT_STATUS_IS_OK(result)) {
2030 return result;
2033 /* Get domain policy handle */
2034 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2035 &connect_pol,
2036 MAXIMUM_ALLOWED_ACCESS,
2037 &sid,
2038 &domain_pol,
2039 &result);
2040 if (!NT_STATUS_IS_OK(status)) {
2041 return status;
2043 if (!NT_STATUS_IS_OK(result)) {
2044 return result;
2047 init_lsa_String(&lsa_acct_name, member);
2049 status = dcerpc_samr_LookupNames(b, mem_ctx,
2050 &domain_pol,
2052 &lsa_acct_name,
2053 &rids,
2054 &rid_types,
2055 &result);
2056 if (!NT_STATUS_IS_OK(status)) {
2057 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2058 member);
2059 goto done;
2062 if (!NT_STATUS_IS_OK(result)) {
2063 status = result;
2064 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2065 member);
2066 goto done;
2069 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2070 &domain_pol,
2071 MAXIMUM_ALLOWED_ACCESS,
2072 group_rid,
2073 &group_pol,
2074 &result);
2075 if (!NT_STATUS_IS_OK(status)) {
2076 goto done;
2079 if (!NT_STATUS_IS_OK(result)) {
2080 status = result;
2081 goto done;
2084 status = dcerpc_samr_AddGroupMember(b, mem_ctx,
2085 &group_pol,
2086 rids.ids[0],
2087 0x0005, /* unknown flags */
2088 &result);
2089 if (!NT_STATUS_IS_OK(status)) {
2090 goto done;
2093 status = result;
2095 done:
2096 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2097 return status;
2100 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2101 TALLOC_CTX *mem_ctx,
2102 const struct dom_sid *alias_sid,
2103 const char *member)
2105 struct policy_handle connect_pol, domain_pol;
2106 NTSTATUS status, result;
2107 uint32 alias_rid;
2108 struct policy_handle alias_pol;
2109 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2111 struct dom_sid member_sid;
2112 enum lsa_SidType member_type;
2114 struct dom_sid sid;
2116 sid_copy(&sid, alias_sid);
2118 if (!sid_split_rid(&sid, &alias_rid)) {
2119 return NT_STATUS_UNSUCCESSFUL;
2122 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2123 member, &member_sid, &member_type);
2125 if (!NT_STATUS_IS_OK(result)) {
2126 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2127 member);
2128 return result;
2131 /* Get sam policy handle */
2132 status = dcerpc_samr_Connect2(b, mem_ctx,
2133 pipe_hnd->desthost,
2134 MAXIMUM_ALLOWED_ACCESS,
2135 &connect_pol,
2136 &result);
2137 if (!NT_STATUS_IS_OK(status)) {
2138 goto done;
2140 if (!NT_STATUS_IS_OK(result)) {
2141 status = result;
2142 goto done;
2145 /* Get domain policy handle */
2146 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2147 &connect_pol,
2148 MAXIMUM_ALLOWED_ACCESS,
2149 &sid,
2150 &domain_pol,
2151 &result);
2152 if (!NT_STATUS_IS_OK(status)) {
2153 goto done;
2155 if (!NT_STATUS_IS_OK(result)) {
2156 status = result;
2157 goto done;
2160 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2161 &domain_pol,
2162 MAXIMUM_ALLOWED_ACCESS,
2163 alias_rid,
2164 &alias_pol,
2165 &result);
2166 if (!NT_STATUS_IS_OK(status)) {
2167 return status;
2169 if (!NT_STATUS_IS_OK(result)) {
2170 return result;
2173 status = dcerpc_samr_AddAliasMember(b, mem_ctx,
2174 &alias_pol,
2175 &member_sid,
2176 &result);
2177 if (!NT_STATUS_IS_OK(status)) {
2178 return status;
2181 status = result;
2183 done:
2184 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2185 return status;
2188 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2189 const struct dom_sid *domain_sid,
2190 const char *domain_name,
2191 struct cli_state *cli,
2192 struct rpc_pipe_client *pipe_hnd,
2193 TALLOC_CTX *mem_ctx,
2194 int argc,
2195 const char **argv)
2197 struct dom_sid group_sid;
2198 enum lsa_SidType group_type;
2200 if (argc != 2 || c->display_usage) {
2201 d_printf("%s\n%s",
2202 _("Usage:"),
2203 _("net rpc group addmem <group> <member>\n"
2204 " Add a member to a group\n"
2205 " group\tGroup to add member to\n"
2206 " member\tMember to add to group\n"));
2207 return NT_STATUS_UNSUCCESSFUL;
2210 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2211 &group_sid, &group_type))) {
2212 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2213 argv[0]);
2214 return NT_STATUS_UNSUCCESSFUL;
2217 if (group_type == SID_NAME_DOM_GRP) {
2218 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2219 &group_sid, argv[1]);
2221 if (!NT_STATUS_IS_OK(result)) {
2222 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2223 argv[1], argv[0], nt_errstr(result));
2225 return result;
2228 if (group_type == SID_NAME_ALIAS) {
2229 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2230 &group_sid, argv[1]);
2232 if (!NT_STATUS_IS_OK(result)) {
2233 d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2234 argv[1], argv[0], nt_errstr(result));
2236 return result;
2239 d_fprintf(stderr, _("Can only add members to global or local groups "
2240 "which %s is not\n"), argv[0]);
2242 return NT_STATUS_UNSUCCESSFUL;
2245 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2247 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2248 rpc_group_addmem_internals,
2249 argc, argv);
2252 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2253 struct rpc_pipe_client *pipe_hnd,
2254 TALLOC_CTX *mem_ctx,
2255 const struct dom_sid *group_sid,
2256 const char *member)
2258 struct policy_handle connect_pol, domain_pol;
2259 NTSTATUS status, result;
2260 uint32 group_rid;
2261 struct policy_handle group_pol;
2262 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2264 struct samr_Ids rids, rid_types;
2265 struct lsa_String lsa_acct_name;
2267 struct dom_sid sid;
2269 sid_copy(&sid, group_sid);
2271 if (!sid_split_rid(&sid, &group_rid))
2272 return NT_STATUS_UNSUCCESSFUL;
2274 /* Get sam policy handle */
2275 status = dcerpc_samr_Connect2(b, mem_ctx,
2276 pipe_hnd->desthost,
2277 MAXIMUM_ALLOWED_ACCESS,
2278 &connect_pol,
2279 &result);
2280 if (!NT_STATUS_IS_OK(status)) {
2281 return status;
2283 if (!NT_STATUS_IS_OK(result)) {
2284 return result;
2288 /* Get domain policy handle */
2289 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2290 &connect_pol,
2291 MAXIMUM_ALLOWED_ACCESS,
2292 &sid,
2293 &domain_pol,
2294 &result);
2295 if (!NT_STATUS_IS_OK(status)) {
2296 return status;
2298 if (!NT_STATUS_IS_OK(result)) {
2299 return result;
2302 init_lsa_String(&lsa_acct_name, member);
2304 status = dcerpc_samr_LookupNames(b, mem_ctx,
2305 &domain_pol,
2307 &lsa_acct_name,
2308 &rids,
2309 &rid_types,
2310 &result);
2311 if (!NT_STATUS_IS_OK(status)) {
2312 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2313 member);
2314 goto done;
2317 if (!NT_STATUS_IS_OK(result)) {
2318 status = result;
2319 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2320 member);
2321 goto done;
2324 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2325 &domain_pol,
2326 MAXIMUM_ALLOWED_ACCESS,
2327 group_rid,
2328 &group_pol,
2329 &result);
2330 if (!NT_STATUS_IS_OK(status)) {
2331 goto done;
2333 if (!NT_STATUS_IS_OK(result)) {
2334 status = result;
2335 goto done;
2338 status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2339 &group_pol,
2340 rids.ids[0],
2341 &result);
2342 if (!NT_STATUS_IS_OK(status)) {
2343 goto done;
2346 status = result;
2347 done:
2348 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2349 return status;
2352 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2353 TALLOC_CTX *mem_ctx,
2354 const struct dom_sid *alias_sid,
2355 const char *member)
2357 struct policy_handle connect_pol, domain_pol;
2358 NTSTATUS status, result;
2359 uint32 alias_rid;
2360 struct policy_handle alias_pol;
2361 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2363 struct dom_sid member_sid;
2364 enum lsa_SidType member_type;
2366 struct dom_sid sid;
2368 sid_copy(&sid, alias_sid);
2370 if (!sid_split_rid(&sid, &alias_rid))
2371 return NT_STATUS_UNSUCCESSFUL;
2373 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2374 member, &member_sid, &member_type);
2376 if (!NT_STATUS_IS_OK(result)) {
2377 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2378 member);
2379 return result;
2382 /* Get sam policy handle */
2383 status = dcerpc_samr_Connect2(b, mem_ctx,
2384 pipe_hnd->desthost,
2385 MAXIMUM_ALLOWED_ACCESS,
2386 &connect_pol,
2387 &result);
2388 if (!NT_STATUS_IS_OK(status)) {
2389 goto done;
2391 if (!NT_STATUS_IS_OK(result)) {
2392 status = result;
2393 goto done;
2396 /* Get domain policy handle */
2397 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2398 &connect_pol,
2399 MAXIMUM_ALLOWED_ACCESS,
2400 &sid,
2401 &domain_pol,
2402 &result);
2403 if (!NT_STATUS_IS_OK(status)) {
2404 goto done;
2406 if (!NT_STATUS_IS_OK(result)) {
2407 status = result;
2408 goto done;
2411 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2412 &domain_pol,
2413 MAXIMUM_ALLOWED_ACCESS,
2414 alias_rid,
2415 &alias_pol,
2416 &result);
2417 if (!NT_STATUS_IS_OK(status)) {
2418 return status;
2421 if (!NT_STATUS_IS_OK(result)) {
2422 return result;
2425 status = dcerpc_samr_DeleteAliasMember(b, mem_ctx,
2426 &alias_pol,
2427 &member_sid,
2428 &result);
2430 if (!NT_STATUS_IS_OK(status)) {
2431 return status;
2434 status = result;
2436 done:
2437 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2438 return status;
2441 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2442 const struct dom_sid *domain_sid,
2443 const char *domain_name,
2444 struct cli_state *cli,
2445 struct rpc_pipe_client *pipe_hnd,
2446 TALLOC_CTX *mem_ctx,
2447 int argc,
2448 const char **argv)
2450 struct dom_sid group_sid;
2451 enum lsa_SidType group_type;
2453 if (argc != 2 || c->display_usage) {
2454 d_printf("%s\n%s",
2455 _("Usage:"),
2456 _("net rpc group delmem <group> <member>\n"
2457 " Delete a member from a group\n"
2458 " group\tGroup to delete member from\n"
2459 " member\tMember to delete from group\n"));
2460 return NT_STATUS_UNSUCCESSFUL;
2463 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2464 &group_sid, &group_type))) {
2465 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2466 argv[0]);
2467 return NT_STATUS_UNSUCCESSFUL;
2470 if (group_type == SID_NAME_DOM_GRP) {
2471 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2472 &group_sid, argv[1]);
2474 if (!NT_STATUS_IS_OK(result)) {
2475 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2476 argv[1], argv[0], nt_errstr(result));
2478 return result;
2481 if (group_type == SID_NAME_ALIAS) {
2482 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2483 &group_sid, argv[1]);
2485 if (!NT_STATUS_IS_OK(result)) {
2486 d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2487 argv[1], argv[0], nt_errstr(result));
2489 return result;
2492 d_fprintf(stderr, _("Can only delete members from global or local "
2493 "groups which %s is not\n"), argv[0]);
2495 return NT_STATUS_UNSUCCESSFUL;
2498 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2500 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2501 rpc_group_delmem_internals,
2502 argc, argv);
2506 * List groups on a remote RPC server.
2508 * All parameters are provided by the run_rpc_command function, except for
2509 * argc, argv which are passes through.
2511 * @param domain_sid The domain sid acquired from the remote server.
2512 * @param cli A cli_state connected to the server.
2513 * @param mem_ctx Talloc context, destroyed on completion of the function.
2514 * @param argc Standard main() style argc.
2515 * @param argv Standard main() style argv. Initial components are already
2516 * stripped.
2518 * @return Normal NTSTATUS return.
2521 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2522 const struct dom_sid *domain_sid,
2523 const char *domain_name,
2524 struct cli_state *cli,
2525 struct rpc_pipe_client *pipe_hnd,
2526 TALLOC_CTX *mem_ctx,
2527 int argc,
2528 const char **argv)
2530 struct policy_handle connect_pol, domain_pol;
2531 NTSTATUS status, result;
2532 uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2533 struct samr_SamArray *groups = NULL;
2534 bool global = false;
2535 bool local = false;
2536 bool builtin = false;
2537 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2539 if (c->display_usage) {
2540 d_printf("%s\n%s",
2541 _("Usage:"),
2542 _("net rpc group list [global] [local] [builtin]\n"
2543 " List groups on RPC server\n"
2544 " global\tList global groups\n"
2545 " local\tList local groups\n"
2546 " builtin\tList builtin groups\n"
2547 " If none of global, local or builtin is "
2548 "specified, all three options are considered "
2549 "set\n"));
2550 return NT_STATUS_OK;
2553 if (argc == 0) {
2554 global = true;
2555 local = true;
2556 builtin = true;
2559 for (i=0; i<argc; i++) {
2560 if (strequal(argv[i], "global"))
2561 global = true;
2563 if (strequal(argv[i], "local"))
2564 local = true;
2566 if (strequal(argv[i], "builtin"))
2567 builtin = true;
2570 /* Get sam policy handle */
2572 status = dcerpc_samr_Connect2(b, mem_ctx,
2573 pipe_hnd->desthost,
2574 MAXIMUM_ALLOWED_ACCESS,
2575 &connect_pol,
2576 &result);
2577 if (!NT_STATUS_IS_OK(status)) {
2578 goto done;
2580 if (!NT_STATUS_IS_OK(result)) {
2581 status = result;
2582 goto done;
2585 /* Get domain policy handle */
2587 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2588 &connect_pol,
2589 MAXIMUM_ALLOWED_ACCESS,
2590 discard_const_p(struct dom_sid2, domain_sid),
2591 &domain_pol,
2592 &result);
2593 if (!NT_STATUS_IS_OK(status)) {
2594 goto done;
2596 if (!NT_STATUS_IS_OK(result)) {
2597 status = result;
2598 goto done;
2601 /* Query domain groups */
2602 if (c->opt_long_list_entries)
2603 d_printf(_("\nGroup name Comment"
2604 "\n-----------------------------\n"));
2605 do {
2606 uint32_t max_size, total_size, returned_size;
2607 union samr_DispInfo info;
2609 if (!global) break;
2611 dcerpc_get_query_dispinfo_params(
2612 loop_count, &max_entries, &max_size);
2614 status = dcerpc_samr_QueryDisplayInfo(b, mem_ctx,
2615 &domain_pol,
2617 start_idx,
2618 max_entries,
2619 max_size,
2620 &total_size,
2621 &returned_size,
2622 &info,
2623 &result);
2624 if (!NT_STATUS_IS_OK(status)) {
2625 goto done;
2627 num_entries = info.info3.count;
2628 start_idx += info.info3.count;
2630 if (!NT_STATUS_IS_OK(result) &&
2631 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2632 break;
2634 for (i = 0; i < num_entries; i++) {
2636 const char *group = NULL;
2637 const char *desc = NULL;
2639 group = info.info3.entries[i].account_name.string;
2640 desc = info.info3.entries[i].description.string;
2642 if (c->opt_long_list_entries)
2643 printf("%-21.21s %-50.50s\n",
2644 group, desc);
2645 else
2646 printf("%s\n", group);
2648 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2649 /* query domain aliases */
2650 start_idx = 0;
2651 do {
2652 if (!local) break;
2654 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2655 &domain_pol,
2656 &start_idx,
2657 &groups,
2658 0xffff,
2659 &num_entries,
2660 &result);
2661 if (!NT_STATUS_IS_OK(status)) {
2662 goto done;
2664 if (!NT_STATUS_IS_OK(result) &&
2665 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2666 break;
2668 for (i = 0; i < num_entries; i++) {
2670 const char *description = NULL;
2672 if (c->opt_long_list_entries) {
2674 struct policy_handle alias_pol;
2675 union samr_AliasInfo *info = NULL;
2676 NTSTATUS _result;
2678 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2679 &domain_pol,
2680 0x8,
2681 groups->entries[i].idx,
2682 &alias_pol,
2683 &_result);
2684 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2685 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2686 &alias_pol,
2688 &info,
2689 &_result);
2690 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2691 status = dcerpc_samr_Close(b, mem_ctx,
2692 &alias_pol,
2693 &_result);
2694 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2695 description = info->description.string;
2701 if (description != NULL) {
2702 printf("%-21.21s %-50.50s\n",
2703 groups->entries[i].name.string,
2704 description);
2705 } else {
2706 printf("%s\n", groups->entries[i].name.string);
2709 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2710 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
2711 /* Get builtin policy handle */
2713 status = dcerpc_samr_OpenDomain(b, mem_ctx,
2714 &connect_pol,
2715 MAXIMUM_ALLOWED_ACCESS,
2716 discard_const_p(struct dom_sid2, &global_sid_Builtin),
2717 &domain_pol,
2718 &result);
2719 if (!NT_STATUS_IS_OK(status)) {
2720 goto done;
2722 if (!NT_STATUS_IS_OK(result)) {
2723 status = result;
2724 goto done;
2727 /* query builtin aliases */
2728 start_idx = 0;
2729 do {
2730 if (!builtin) break;
2732 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2733 &domain_pol,
2734 &start_idx,
2735 &groups,
2736 max_entries,
2737 &num_entries,
2738 &result);
2739 if (!NT_STATUS_IS_OK(status)) {
2740 break;
2742 if (!NT_STATUS_IS_OK(result) &&
2743 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
2744 status = result;
2745 break;
2748 for (i = 0; i < num_entries; i++) {
2750 const char *description = NULL;
2752 if (c->opt_long_list_entries) {
2754 struct policy_handle alias_pol;
2755 union samr_AliasInfo *info = NULL;
2756 NTSTATUS _result;
2758 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2759 &domain_pol,
2760 0x8,
2761 groups->entries[i].idx,
2762 &alias_pol,
2763 &_result);
2764 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2765 status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2766 &alias_pol,
2768 &info,
2769 &_result);
2770 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2771 status = dcerpc_samr_Close(b, mem_ctx,
2772 &alias_pol,
2773 &_result);
2774 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2775 description = info->description.string;
2781 if (description != NULL) {
2782 printf("%-21.21s %-50.50s\n",
2783 groups->entries[i].name.string,
2784 description);
2785 } else {
2786 printf("%s\n", groups->entries[i].name.string);
2789 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2791 status = result;
2793 done:
2794 return status;
2797 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2799 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
2800 rpc_group_list_internals,
2801 argc, argv);
2804 static NTSTATUS rpc_list_group_members(struct net_context *c,
2805 struct rpc_pipe_client *pipe_hnd,
2806 TALLOC_CTX *mem_ctx,
2807 const char *domain_name,
2808 const struct dom_sid *domain_sid,
2809 struct policy_handle *domain_pol,
2810 uint32 rid)
2812 NTSTATUS result, status;
2813 struct policy_handle group_pol;
2814 uint32 num_members, *group_rids;
2815 int i;
2816 struct samr_RidAttrArray *rids = NULL;
2817 struct lsa_Strings names;
2818 struct samr_Ids types;
2819 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2821 fstring sid_str;
2822 sid_to_fstring(sid_str, domain_sid);
2824 status = dcerpc_samr_OpenGroup(b, mem_ctx,
2825 domain_pol,
2826 MAXIMUM_ALLOWED_ACCESS,
2827 rid,
2828 &group_pol,
2829 &result);
2830 if (!NT_STATUS_IS_OK(status)) {
2831 return status;
2833 if (!NT_STATUS_IS_OK(result)) {
2834 return result;
2837 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
2838 &group_pol,
2839 &rids,
2840 &result);
2841 if (!NT_STATUS_IS_OK(status)) {
2842 return status;
2844 if (!NT_STATUS_IS_OK(result)) {
2845 return result;
2848 num_members = rids->count;
2849 group_rids = rids->rids;
2851 while (num_members > 0) {
2852 int this_time = 512;
2854 if (num_members < this_time)
2855 this_time = num_members;
2857 status = dcerpc_samr_LookupRids(b, mem_ctx,
2858 domain_pol,
2859 this_time,
2860 group_rids,
2861 &names,
2862 &types,
2863 &result);
2864 if (!NT_STATUS_IS_OK(status)) {
2865 return status;
2867 if (!NT_STATUS_IS_OK(result)) {
2868 return result;
2871 /* We only have users as members, but make the output
2872 the same as the output of alias members */
2874 for (i = 0; i < this_time; i++) {
2876 if (c->opt_long_list_entries) {
2877 printf("%s-%d %s\\%s %d\n", sid_str,
2878 group_rids[i], domain_name,
2879 names.names[i].string,
2880 SID_NAME_USER);
2881 } else {
2882 printf("%s\\%s\n", domain_name,
2883 names.names[i].string);
2887 num_members -= this_time;
2888 group_rids += 512;
2891 return NT_STATUS_OK;
2894 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2895 struct rpc_pipe_client *pipe_hnd,
2896 TALLOC_CTX *mem_ctx,
2897 struct policy_handle *domain_pol,
2898 uint32 rid)
2900 NTSTATUS result, status;
2901 struct rpc_pipe_client *lsa_pipe;
2902 struct policy_handle alias_pol, lsa_pol;
2903 uint32 num_members;
2904 struct dom_sid *alias_sids;
2905 char **domains;
2906 char **names;
2907 enum lsa_SidType *types;
2908 int i;
2909 struct lsa_SidArray sid_array;
2910 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2912 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2913 domain_pol,
2914 MAXIMUM_ALLOWED_ACCESS,
2915 rid,
2916 &alias_pol,
2917 &result);
2918 if (!NT_STATUS_IS_OK(status)) {
2919 return status;
2921 if (!NT_STATUS_IS_OK(result)) {
2922 return result;
2925 status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
2926 &alias_pol,
2927 &sid_array,
2928 &result);
2929 if (!NT_STATUS_IS_OK(status)) {
2930 d_fprintf(stderr, _("Couldn't list alias members\n"));
2931 return status;
2933 if (!NT_STATUS_IS_OK(result)) {
2934 d_fprintf(stderr, _("Couldn't list alias members\n"));
2935 return result;
2938 num_members = sid_array.num_sids;
2940 if (num_members == 0) {
2941 return NT_STATUS_OK;
2944 result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2945 &ndr_table_lsarpc.syntax_id,
2946 &lsa_pipe);
2947 if (!NT_STATUS_IS_OK(result)) {
2948 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
2949 nt_errstr(result) );
2950 return result;
2953 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2954 SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2956 if (!NT_STATUS_IS_OK(result)) {
2957 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
2958 TALLOC_FREE(lsa_pipe);
2959 return result;
2962 alias_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
2963 if (!alias_sids) {
2964 d_fprintf(stderr, _("Out of memory\n"));
2965 TALLOC_FREE(lsa_pipe);
2966 return NT_STATUS_NO_MEMORY;
2969 for (i=0; i<num_members; i++) {
2970 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2973 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
2974 num_members, alias_sids,
2975 &domains, &names, &types);
2977 if (!NT_STATUS_IS_OK(result) &&
2978 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2979 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
2980 TALLOC_FREE(lsa_pipe);
2981 return result;
2984 for (i = 0; i < num_members; i++) {
2985 fstring sid_str;
2986 sid_to_fstring(sid_str, &alias_sids[i]);
2988 if (c->opt_long_list_entries) {
2989 printf("%s %s\\%s %d\n", sid_str,
2990 domains[i] ? domains[i] : _("*unknown*"),
2991 names[i] ? names[i] : _("*unknown*"), types[i]);
2992 } else {
2993 if (domains[i])
2994 printf("%s\\%s\n", domains[i], names[i]);
2995 else
2996 printf("%s\n", sid_str);
3000 TALLOC_FREE(lsa_pipe);
3001 return NT_STATUS_OK;
3004 static NTSTATUS rpc_group_members_internals(struct net_context *c,
3005 const struct dom_sid *domain_sid,
3006 const char *domain_name,
3007 struct cli_state *cli,
3008 struct rpc_pipe_client *pipe_hnd,
3009 TALLOC_CTX *mem_ctx,
3010 int argc,
3011 const char **argv)
3013 NTSTATUS result, status;
3014 struct policy_handle connect_pol, domain_pol;
3015 struct samr_Ids rids, rid_types;
3016 struct lsa_String lsa_acct_name;
3017 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3019 /* Get sam policy handle */
3021 status = dcerpc_samr_Connect2(b, mem_ctx,
3022 pipe_hnd->desthost,
3023 MAXIMUM_ALLOWED_ACCESS,
3024 &connect_pol,
3025 &result);
3026 if (!NT_STATUS_IS_OK(status)) {
3027 return status;
3029 if (!NT_STATUS_IS_OK(result)) {
3030 return result;
3033 /* Get domain policy handle */
3035 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3036 &connect_pol,
3037 MAXIMUM_ALLOWED_ACCESS,
3038 discard_const_p(struct dom_sid2, domain_sid),
3039 &domain_pol,
3040 &result);
3041 if (!NT_STATUS_IS_OK(status)) {
3042 return status;
3044 if (!NT_STATUS_IS_OK(result)) {
3045 return result;
3048 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
3050 status = dcerpc_samr_LookupNames(b, mem_ctx,
3051 &domain_pol,
3053 &lsa_acct_name,
3054 &rids,
3055 &rid_types,
3056 &result);
3057 if (!NT_STATUS_IS_OK(status)) {
3058 return status;
3061 if (!NT_STATUS_IS_OK(result)) {
3063 /* Ok, did not find it in the global sam, try with builtin */
3065 struct dom_sid sid_Builtin;
3067 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
3069 sid_copy(&sid_Builtin, &global_sid_Builtin);
3071 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3072 &connect_pol,
3073 MAXIMUM_ALLOWED_ACCESS,
3074 &sid_Builtin,
3075 &domain_pol,
3076 &result);
3077 if (!NT_STATUS_IS_OK(status)) {
3078 return status;
3080 if (!NT_STATUS_IS_OK(result)) {
3081 d_fprintf(stderr, _("Couldn't find group %s\n"),
3082 argv[0]);
3083 return result;
3086 status = dcerpc_samr_LookupNames(b, mem_ctx,
3087 &domain_pol,
3089 &lsa_acct_name,
3090 &rids,
3091 &rid_types,
3092 &result);
3093 if (!NT_STATUS_IS_OK(status)) {
3094 return status;
3096 if (!NT_STATUS_IS_OK(result)) {
3097 d_fprintf(stderr, _("Couldn't find group %s\n"),
3098 argv[0]);
3099 return result;
3103 if (rids.count != 1) {
3104 d_fprintf(stderr, _("Couldn't find group %s\n"),
3105 argv[0]);
3106 return result;
3109 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
3110 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
3111 domain_sid, &domain_pol,
3112 rids.ids[0]);
3115 if (rid_types.ids[0] == SID_NAME_ALIAS) {
3116 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
3117 rids.ids[0]);
3120 return NT_STATUS_NO_SUCH_GROUP;
3123 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
3125 if (argc != 1 || c->display_usage) {
3126 return rpc_group_usage(c, argc, argv);
3129 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3130 rpc_group_members_internals,
3131 argc, argv);
3134 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
3136 NET_API_STATUS status;
3137 struct GROUP_INFO_0 g0;
3138 uint32_t parm_err;
3140 if (argc != 2) {
3141 d_printf(_("Usage:\n"));
3142 d_printf("net rpc group rename group newname\n");
3143 return -1;
3146 g0.grpi0_name = argv[1];
3148 status = NetGroupSetInfo(c->opt_host,
3149 argv[0],
3151 (uint8_t *)&g0,
3152 &parm_err);
3154 if (status != 0) {
3155 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
3156 argv[0], libnetapi_get_error_string(c->netapi_ctx,
3157 status));
3158 return -1;
3161 return 0;
3164 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
3166 if (argc != 2 || c->display_usage) {
3167 return rpc_group_usage(c, argc, argv);
3170 return rpc_group_rename_internals(c, argc, argv);
3174 * 'net rpc group' entrypoint.
3175 * @param argc Standard main() style argc.
3176 * @param argv Standard main() style argv. Initial components are already
3177 * stripped.
3180 int net_rpc_group(struct net_context *c, int argc, const char **argv)
3182 NET_API_STATUS status;
3184 struct functable func[] = {
3186 "add",
3187 rpc_group_add,
3188 NET_TRANSPORT_RPC,
3189 N_("Create specified group"),
3190 N_("net rpc group add\n"
3191 " Create specified group")
3194 "delete",
3195 rpc_group_delete,
3196 NET_TRANSPORT_RPC,
3197 N_("Delete specified group"),
3198 N_("net rpc group delete\n"
3199 " Delete specified group")
3202 "addmem",
3203 rpc_group_addmem,
3204 NET_TRANSPORT_RPC,
3205 N_("Add member to group"),
3206 N_("net rpc group addmem\n"
3207 " Add member to group")
3210 "delmem",
3211 rpc_group_delmem,
3212 NET_TRANSPORT_RPC,
3213 N_("Remove member from group"),
3214 N_("net rpc group delmem\n"
3215 " Remove member from group")
3218 "list",
3219 rpc_group_list,
3220 NET_TRANSPORT_RPC,
3221 N_("List groups"),
3222 N_("net rpc group list\n"
3223 " List groups")
3226 "members",
3227 rpc_group_members,
3228 NET_TRANSPORT_RPC,
3229 N_("List group members"),
3230 N_("net rpc group members\n"
3231 " List group members")
3234 "rename",
3235 rpc_group_rename,
3236 NET_TRANSPORT_RPC,
3237 N_("Rename group"),
3238 N_("net rpc group rename\n"
3239 " Rename group")
3241 {NULL, NULL, 0, NULL, NULL}
3244 status = libnetapi_net_init(&c->netapi_ctx);
3245 if (status != 0) {
3246 return -1;
3248 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
3249 libnetapi_set_password(c->netapi_ctx, c->opt_password);
3250 if (c->opt_kerberos) {
3251 libnetapi_set_use_kerberos(c->netapi_ctx);
3254 if (argc == 0) {
3255 if (c->display_usage) {
3256 d_printf(_("Usage:\n"));
3257 d_printf(_("net rpc group\n"
3258 " Alias for net rpc group list global "
3259 "local builtin\n"));
3260 net_display_usage_from_functable(func);
3261 return 0;
3264 return run_rpc_command(c, NULL, &ndr_table_samr, 0,
3265 rpc_group_list_internals,
3266 argc, argv);
3269 return net_run_function(c, argc, argv, "net rpc group", func);
3272 /****************************************************************************/
3274 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
3276 return net_share_usage(c, argc, argv);
3280 * Add a share on a remote RPC server.
3282 * @param argc Standard main() style argc.
3283 * @param argv Standard main() style argv. Initial components are already
3284 * stripped.
3286 * @return A shell status integer (0 for success).
3289 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3291 NET_API_STATUS status;
3292 char *sharename;
3293 char *path;
3294 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3295 uint32 num_users=0, perms=0;
3296 char *password=NULL; /* don't allow a share password */
3297 struct SHARE_INFO_2 i2;
3298 uint32_t parm_error = 0;
3300 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3301 return rpc_share_usage(c, argc, argv);
3304 if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
3305 return -1;
3308 path = strchr(sharename, '=');
3309 if (!path) {
3310 return -1;
3313 *path++ = '\0';
3315 i2.shi2_netname = sharename;
3316 i2.shi2_type = type;
3317 i2.shi2_remark = c->opt_comment;
3318 i2.shi2_permissions = perms;
3319 i2.shi2_max_uses = c->opt_maxusers;
3320 i2.shi2_current_uses = num_users;
3321 i2.shi2_path = path;
3322 i2.shi2_passwd = password;
3324 status = NetShareAdd(c->opt_host,
3326 (uint8_t *)&i2,
3327 &parm_error);
3328 if (status != 0) {
3329 printf(_("NetShareAdd failed with: %s\n"),
3330 libnetapi_get_error_string(c->netapi_ctx, status));
3333 return status;
3337 * Delete a share on a remote RPC server.
3339 * @param domain_sid The domain sid acquired from the remote server.
3340 * @param argc Standard main() style argc.
3341 * @param argv Standard main() style argv. Initial components are already
3342 * stripped.
3344 * @return A shell status integer (0 for success).
3346 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3348 if (argc < 1 || c->display_usage) {
3349 return rpc_share_usage(c, argc, argv);
3352 return NetShareDel(c->opt_host, argv[0], 0);
3356 * Formatted print of share info
3358 * @param r pointer to SHARE_INFO_1 to format
3361 static void display_share_info_1(struct net_context *c,
3362 struct SHARE_INFO_1 *r)
3364 if (c->opt_long_list_entries) {
3365 d_printf("%-12s %-8.8s %-50s\n",
3366 r->shi1_netname,
3367 net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3368 r->shi1_remark);
3369 } else {
3370 d_printf("%s\n", r->shi1_netname);
3374 static WERROR get_share_info(struct net_context *c,
3375 struct rpc_pipe_client *pipe_hnd,
3376 TALLOC_CTX *mem_ctx,
3377 uint32 level,
3378 int argc,
3379 const char **argv,
3380 struct srvsvc_NetShareInfoCtr *info_ctr)
3382 WERROR result;
3383 NTSTATUS status;
3384 union srvsvc_NetShareInfo info;
3385 struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3387 /* no specific share requested, enumerate all */
3388 if (argc == 0) {
3390 uint32_t preferred_len = 0xffffffff;
3391 uint32_t total_entries = 0;
3392 uint32_t resume_handle = 0;
3394 info_ctr->level = level;
3396 status = dcerpc_srvsvc_NetShareEnumAll(b, mem_ctx,
3397 pipe_hnd->desthost,
3398 info_ctr,
3399 preferred_len,
3400 &total_entries,
3401 &resume_handle,
3402 &result);
3403 if (!NT_STATUS_IS_OK(status)) {
3404 return ntstatus_to_werror(status);
3406 return result;
3409 /* request just one share */
3410 status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
3411 pipe_hnd->desthost,
3412 argv[0],
3413 level,
3414 &info,
3415 &result);
3417 if (!NT_STATUS_IS_OK(status)) {
3418 result = ntstatus_to_werror(status);
3419 goto done;
3422 if (!W_ERROR_IS_OK(result)) {
3423 goto done;
3426 /* construct ctr */
3427 ZERO_STRUCTP(info_ctr);
3429 info_ctr->level = level;
3431 switch (level) {
3432 case 1:
3434 struct srvsvc_NetShareCtr1 *ctr1;
3436 ctr1 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr1);
3437 W_ERROR_HAVE_NO_MEMORY(ctr1);
3439 ctr1->count = 1;
3440 ctr1->array = info.info1;
3442 info_ctr->ctr.ctr1 = ctr1;
3444 break;
3446 case 2:
3448 struct srvsvc_NetShareCtr2 *ctr2;
3450 ctr2 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr2);
3451 W_ERROR_HAVE_NO_MEMORY(ctr2);
3453 ctr2->count = 1;
3454 ctr2->array = info.info2;
3456 info_ctr->ctr.ctr2 = ctr2;
3458 break;
3460 case 502:
3462 struct srvsvc_NetShareCtr502 *ctr502;
3464 ctr502 = talloc_zero(mem_ctx, struct srvsvc_NetShareCtr502);
3465 W_ERROR_HAVE_NO_MEMORY(ctr502);
3467 ctr502->count = 1;
3468 ctr502->array = info.info502;
3470 info_ctr->ctr.ctr502 = ctr502;
3472 break;
3474 } /* switch */
3475 done:
3476 return result;
3479 /***
3480 * 'net rpc share list' entrypoint.
3481 * @param argc Standard main() style argc.
3482 * @param argv Standard main() style argv. Initial components are already
3483 * stripped.
3485 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3487 NET_API_STATUS status;
3488 struct SHARE_INFO_1 *i1 = NULL;
3489 uint32_t entries_read = 0;
3490 uint32_t total_entries = 0;
3491 uint32_t resume_handle = 0;
3492 uint32_t i, level = 1;
3494 if (c->display_usage) {
3495 d_printf( "%s\n"
3496 "net rpc share list\n"
3497 " %s\n",
3498 _("Usage:"),
3499 _("List shares on remote server"));
3500 return 0;
3503 status = NetShareEnum(c->opt_host,
3504 level,
3505 (uint8_t **)(void *)&i1,
3506 (uint32_t)-1,
3507 &entries_read,
3508 &total_entries,
3509 &resume_handle);
3510 if (status != 0) {
3511 goto done;
3514 /* Display results */
3516 if (c->opt_long_list_entries) {
3517 d_printf(_(
3518 "\nEnumerating shared resources (exports) on remote server:\n\n"
3519 "\nShare name Type Description\n"
3520 "---------- ---- -----------\n"));
3522 for (i = 0; i < entries_read; i++)
3523 display_share_info_1(c, &i1[i]);
3524 done:
3525 return status;
3528 static bool check_share_availability(struct cli_state *cli, const char *netname)
3530 NTSTATUS status;
3532 status = cli_tree_connect(cli, netname, "A:", "", 0);
3533 if (!NT_STATUS_IS_OK(status)) {
3534 d_printf(_("skipping [%s]: not a file share.\n"), netname);
3535 return false;
3538 status = cli_tdis(cli);
3539 if (!NT_STATUS_IS_OK(status)) {
3540 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3541 return false;
3544 return true;
3547 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3548 const char *netname, uint32 type)
3550 /* only support disk shares */
3551 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3552 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3553 type);
3554 return false;
3557 /* skip builtin shares */
3558 /* FIXME: should print$ be added too ? */
3559 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3560 strequal(netname,"global"))
3561 return false;
3563 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3564 printf(_("excluding [%s]\n"), netname);
3565 return false;
3568 return check_share_availability(cli, netname);
3572 * Migrate shares from a remote RPC server to the local RPC server.
3574 * All parameters are provided by the run_rpc_command function, except for
3575 * argc, argv which are passed through.
3577 * @param domain_sid The domain sid acquired from the remote server.
3578 * @param cli A cli_state connected to the server.
3579 * @param mem_ctx Talloc context, destroyed on completion of the function.
3580 * @param argc Standard main() style argc.
3581 * @param argv Standard main() style argv. Initial components are already
3582 * stripped.
3584 * @return Normal NTSTATUS return.
3587 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3588 const struct dom_sid *domain_sid,
3589 const char *domain_name,
3590 struct cli_state *cli,
3591 struct rpc_pipe_client *pipe_hnd,
3592 TALLOC_CTX *mem_ctx,
3593 int argc,
3594 const char **argv)
3596 WERROR result;
3597 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3598 struct srvsvc_NetShareInfoCtr ctr_src;
3599 uint32 i;
3600 struct rpc_pipe_client *srvsvc_pipe = NULL;
3601 struct cli_state *cli_dst = NULL;
3602 uint32 level = 502; /* includes secdesc */
3603 uint32_t parm_error = 0;
3604 struct dcerpc_binding_handle *b;
3606 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3607 &ctr_src);
3608 if (!W_ERROR_IS_OK(result))
3609 goto done;
3611 /* connect destination PI_SRVSVC */
3612 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3613 &ndr_table_srvsvc.syntax_id);
3614 if (!NT_STATUS_IS_OK(nt_status))
3615 return nt_status;
3617 b = srvsvc_pipe->binding_handle;
3619 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3621 union srvsvc_NetShareInfo info;
3622 struct srvsvc_NetShareInfo502 info502 =
3623 ctr_src.ctr.ctr502->array[i];
3625 /* reset error-code */
3626 nt_status = NT_STATUS_UNSUCCESSFUL;
3628 if (!check_share_sanity(c, cli, info502.name, info502.type))
3629 continue;
3631 /* finally add the share on the dst server */
3633 printf(_("migrating: [%s], path: %s, comment: %s, without "
3634 "share-ACLs\n"),
3635 info502.name, info502.path, info502.comment);
3637 info.info502 = &info502;
3639 nt_status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
3640 srvsvc_pipe->desthost,
3641 502,
3642 &info,
3643 &parm_error,
3644 &result);
3645 if (!NT_STATUS_IS_OK(nt_status)) {
3646 printf(_("cannot add share: %s\n"),
3647 nt_errstr(nt_status));