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 Guenther Deschner (gd@samba.org)
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
21
22#include "includes.h"
23#include "utils/net.h"
24
25/**
26 * @file net_rpc.c
27 *
28 * @brief RPC based subcommands for the 'net' utility.
29 *
30 * This file should contain much of the functionality that used to
31 * be found in rpcclient, execpt that the commands should change
32 * less often, and the fucntionality should be sane (the user is not
33 * expected to know a rid/sid before they conduct an operation etc.)
34 *
35 * @todo Perhaps eventually these should be split out into a number
36 * of files, as this could get quite big.
37 **/
38
39
40/**
41 * Many of the RPC functions need the domain sid.  This function gets
42 *  it at the start of every run
43 *
44 * @param cli A cli_state already connected to the remote machine
45 *
46 * @return The Domain SID of the remote machine.
47 **/
48
49static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, char **domain_name)
50{
51	DOM_SID *domain_sid;
52	POLICY_HND pol;
53	NTSTATUS result = NT_STATUS_OK;
54	uint32 info_class = 5;
55
56	if (!cli_nt_session_open (cli, PI_LSARPC)) {
57		fprintf(stderr, "could not initialise lsa pipe\n");
58		goto error;
59	}
60
61	result = cli_lsa_open_policy(cli, mem_ctx, False,
62				     SEC_RIGHTS_MAXIMUM_ALLOWED,
63				     &pol);
64	if (!NT_STATUS_IS_OK(result)) {
65		goto error;
66	}
67
68	result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class,
69					   domain_name, &domain_sid);
70	if (!NT_STATUS_IS_OK(result)) {
71 error:
72		fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
73
74		if (!NT_STATUS_IS_OK(result)) {
75			fprintf(stderr, "error: %s\n", nt_errstr(result));
76		}
77
78		exit(1);
79	}
80
81	cli_lsa_close(cli, mem_ctx, &pol);
82	cli_nt_session_close(cli);
83
84	return domain_sid;
85}
86
87/**
88 * Run a single RPC command, from start to finish.
89 *
90 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
91 * @param conn_flag a NET_FLAG_ combination.  Passed to
92 *                   net_make_ipc_connection.
93 * @param argc  Standard main() style argc
94 * @param argc  Standard main() style argv.  Initial components are already
95 *              stripped
96 * @return A shell status integer (0 for success)
97 */
98
99int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int conn_flags,
100                           rpc_command_fn fn,
101                           int argc, const char **argv)
102{
103	struct cli_state *cli = NULL;
104	TALLOC_CTX *mem_ctx;
105	NTSTATUS nt_status;
106	DOM_SID *domain_sid;
107	char *domain_name;
108
109	/* make use of cli_state handed over as an argument, if possible */
110	if (!cli_arg)
111		cli = net_make_ipc_connection(conn_flags);
112	else
113		cli = cli_arg;
114
115	if (!cli) {
116		return -1;
117	}
118
119	/* Create mem_ctx */
120
121	if (!(mem_ctx = talloc_init("run_rpc_command"))) {
122		DEBUG(0, ("talloc_init() failed\n"));
123		cli_shutdown(cli);
124		return -1;
125	}
126
127	domain_sid = net_get_remote_domain_sid(cli, mem_ctx, &domain_name);
128
129	if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
130		if (!cli_nt_session_open(cli, pipe_idx)) {
131			DEBUG(0, ("Could not initialise pipe\n"));
132		}
133	}
134
135	nt_status = fn(domain_sid, domain_name, cli, mem_ctx, argc, argv);
136
137	if (!NT_STATUS_IS_OK(nt_status)) {
138		DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
139	} else {
140		DEBUG(5, ("rpc command function succedded\n"));
141	}
142
143	if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
144		if (cli->nt_pipe_fnum[cli->pipe_idx])
145			cli_nt_session_close(cli);
146	}
147
148	/* close the connection only if it was opened here */
149	if (!cli_arg)
150		cli_shutdown(cli);
151
152	talloc_destroy(mem_ctx);
153
154	return (!NT_STATUS_IS_OK(nt_status));
155}
156
157
158/****************************************************************************/
159
160
161/**
162 * Force a change of the trust acccount password.
163 *
164 * All parameters are provided by the run_rpc_command function, except for
165 * argc, argv which are passes through.
166 *
167 * @param domain_sid The domain sid aquired from the remote server
168 * @param cli A cli_state connected to the server.
169 * @param mem_ctx Talloc context, destoyed on compleation of the function.
170 * @param argc  Standard main() style argc
171 * @param argc  Standard main() style argv.  Initial components are already
172 *              stripped
173 *
174 * @return Normal NTSTATUS return.
175 **/
176
177static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, const char *domain_name,
178					    struct cli_state *cli, TALLOC_CTX *mem_ctx,
179					    int argc, const char **argv) {
180
181	return trust_pw_find_change_and_store_it(cli, mem_ctx, opt_target_workgroup);
182}
183
184/**
185 * Force a change of the trust acccount password.
186 *
187 * @param argc  Standard main() style argc
188 * @param argc  Standard main() style argv.  Initial components are already
189 *              stripped
190 *
191 * @return A shell status integer (0 for success)
192 **/
193
194int net_rpc_changetrustpw(int argc, const char **argv)
195{
196	return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
197			       rpc_changetrustpw_internals,
198			       argc, argv);
199}
200
201
202/****************************************************************************/
203
204
205/**
206 * Join a domain, the old way.
207 *
208 * This uses 'machinename' as the inital password, and changes it.
209 *
210 * The password should be created with 'server manager' or equiv first.
211 *
212 * All parameters are provided by the run_rpc_command function, except for
213 * argc, argv which are passes through.
214 *
215 * @param domain_sid The domain sid aquired from the remote server
216 * @param cli A cli_state connected to the server.
217 * @param mem_ctx Talloc context, destoyed on compleation of the function.
218 * @param argc  Standard main() style argc
219 * @param argc  Standard main() style argv.  Initial components are already
220 *              stripped
221 *
222 * @return Normal NTSTATUS return.
223 **/
224
225static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, const char *domain_name,
226				      struct cli_state *cli,
227				      TALLOC_CTX *mem_ctx,
228				      int argc, const char **argv) {
229
230	fstring trust_passwd;
231	unsigned char orig_trust_passwd_hash[16];
232	NTSTATUS result;
233	uint32 sec_channel_type;
234
235	/*
236	   check what type of join - if the user want's to join as
237	   a BDC, the server must agree that we are a BDC.
238	*/
239	if (argc >= 0) {
240		sec_channel_type = get_sec_channel_type(argv[0]);
241	} else {
242		sec_channel_type = get_sec_channel_type(NULL);
243	}
244
245	fstrcpy(trust_passwd, global_myname());
246	strlower_m(trust_passwd);
247
248	/*
249	 * Machine names can be 15 characters, but the max length on
250	 * a password is 14.  --jerry
251	 */
252
253	trust_passwd[14] = '\0';
254
255	E_md4hash(trust_passwd, orig_trust_passwd_hash);
256
257	result = trust_pw_change_and_store_it(cli, mem_ctx, opt_target_workgroup,
258					      orig_trust_passwd_hash,
259					      sec_channel_type);
260
261	if (NT_STATUS_IS_OK(result))
262		printf("Joined domain %s.\n",opt_target_workgroup);
263
264
265	if (!secrets_store_domain_sid(opt_target_workgroup, domain_sid)) {
266		DEBUG(0, ("error storing domain sid for %s\n", opt_target_workgroup));
267		result = NT_STATUS_UNSUCCESSFUL;
268	}
269
270	return result;
271}
272
273/**
274 * Join a domain, the old way.
275 *
276 * @param argc  Standard main() style argc
277 * @param argc  Standard main() style argv.  Initial components are already
278 *              stripped
279 *
280 * @return A shell status integer (0 for success)
281 **/
282
283static int net_rpc_perform_oldjoin(int argc, const char **argv)
284{
285	return run_rpc_command(NULL, PI_NETLOGON,
286			       NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
287			       rpc_oldjoin_internals,
288			       argc, argv);
289}
290
291/**
292 * Join a domain, the old way.  This function exists to allow
293 * the message to be displayed when oldjoin was explicitly
294 * requested, but not when it was implied by "net rpc join"
295 *
296 * @param argc  Standard main() style argc
297 * @param argc  Standard main() style argv.  Initial components are already
298 *              stripped
299 *
300 * @return A shell status integer (0 for success)
301 **/
302
303static int net_rpc_oldjoin(int argc, const char **argv)
304{
305	int rc = net_rpc_perform_oldjoin(argc, argv);
306
307	if (rc) {
308		d_printf("Failed to join domain\n");
309	}
310
311	return rc;
312}
313
314/**
315 * Basic usage function for 'net rpc join'
316 * @param argc  Standard main() style argc
317 * @param argc  Standard main() style argv.  Initial components are already
318 *              stripped
319 **/
320
321static int rpc_join_usage(int argc, const char **argv)
322{
323	d_printf("net rpc join -U <username>[%%password] <type>[options]\n"\
324		 "\t to join a domain with admin username & password\n"\
325		 "\t\t password will be prompted if needed and none is specified\n"\
326		 "\t <type> can be (default MEMBER)\n"\
327		 "\t\t BDC - Join as a BDC\n"\
328		 "\t\t PDC - Join as a PDC\n"\
329		 "\t\t MEMBER - Join as a MEMBER server\n");
330
331	net_common_flags_usage(argc, argv);
332	return -1;
333}
334
335/**
336 * 'net rpc join' entrypoint.
337 * @param argc  Standard main() style argc
338 * @param argc  Standard main() style argv.  Initial components are already
339 *              stripped
340 *
341 * Main 'net_rpc_join()' (where the admain username/password is used) is
342 * in net_rpc_join.c
343 * Try to just change the password, but if that doesn't work, use/prompt
344 * for a username/password.
345 **/
346
347int net_rpc_join(int argc, const char **argv)
348{
349	if ((net_rpc_perform_oldjoin(argc, argv) == 0))
350		return 0;
351
352	return net_rpc_join_newstyle(argc, argv);
353}
354
355
356
357/**
358 * display info about a rpc domain
359 *
360 * All parameters are provided by the run_rpc_command function, except for
361 * argc, argv which are passed through.
362 *
363 * @param domain_sid The domain sid acquired from the remote server
364 * @param cli A cli_state connected to the server.
365 * @param mem_ctx Talloc context, destoyed on completion of the function.
366 * @param argc  Standard main() style argc
367 * @param argv  Standard main() style argv.  Initial components are already
368 *              stripped
369 *
370 * @return Normal NTSTATUS return.
371 **/
372
373static NTSTATUS
374rpc_info_internals(const DOM_SID *domain_sid, const char *domain_name,
375		   struct cli_state *cli,
376		   TALLOC_CTX *mem_ctx, int argc, const char **argv)
377{
378	POLICY_HND connect_pol, domain_pol;
379	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
380	SAM_UNK_CTR ctr;
381	fstring sid_str;
382
383	sid_to_string(sid_str, domain_sid);
384
385	/* Get sam policy handle */
386	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
387				  &connect_pol);
388	if (!NT_STATUS_IS_OK(result)) {
389		goto done;
390	}
391
392	/* Get domain policy handle */
393	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
394				      MAXIMUM_ALLOWED_ACCESS,
395				      domain_sid, &domain_pol);
396	if (!NT_STATUS_IS_OK(result)) {
397		goto done;
398	}
399
400	ZERO_STRUCT(ctr);
401	result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
402					 2, &ctr);
403	if (NT_STATUS_IS_OK(result)) {
404		TALLOC_CTX *ctx = talloc_init("rpc_info_internals");
405		d_printf("Domain Name: %s\n", unistr2_tdup(ctx, &ctr.info.inf2.uni_domain));
406		d_printf("Domain SID: %s\n", sid_str);
407		d_printf("Sequence number: %u\n", ctr.info.inf2.seq_num.low);
408		d_printf("Num users: %u\n", ctr.info.inf2.num_domain_usrs);
409		d_printf("Num domain groups: %u\n", ctr.info.inf2.num_domain_grps);
410		d_printf("Num local groups: %u\n", ctr.info.inf2.num_local_grps);
411		talloc_destroy(ctx);
412	}
413
414 done:
415	return result;
416}
417
418
419/**
420 * 'net rpc info' entrypoint.
421 * @param argc  Standard main() style argc
422 * @param argc  Standard main() style argv.  Initial components are already
423 *              stripped
424 **/
425int net_rpc_info(int argc, const char **argv)
426{
427	return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
428			       rpc_info_internals,
429			       argc, argv);
430}
431
432
433/**
434 * Fetch domain SID into the local secrets.tdb
435 *
436 * All parameters are provided by the run_rpc_command function, except for
437 * argc, argv which are passes through.
438 *
439 * @param domain_sid The domain sid acquired from the remote server
440 * @param cli A cli_state connected to the server.
441 * @param mem_ctx Talloc context, destoyed on completion of the function.
442 * @param argc  Standard main() style argc
443 * @param argv  Standard main() style argv.  Initial components are already
444 *              stripped
445 *
446 * @return Normal NTSTATUS return.
447 **/
448
449static NTSTATUS
450rpc_getsid_internals(const DOM_SID *domain_sid, const char *domain_name,
451		     struct cli_state *cli,
452		     TALLOC_CTX *mem_ctx, int argc, const char **argv)
453{
454	fstring sid_str;
455
456	sid_to_string(sid_str, domain_sid);
457	d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
458		 sid_str, domain_name);
459
460	if (!secrets_store_domain_sid(domain_name, domain_sid)) {
461		DEBUG(0,("Can't store domain SID\n"));
462		return NT_STATUS_UNSUCCESSFUL;
463	}
464
465	return NT_STATUS_OK;
466}
467
468
469/**
470 * 'net rpc getsid' entrypoint.
471 * @param argc  Standard main() style argc
472 * @param argc  Standard main() style argv.  Initial components are already
473 *              stripped
474 **/
475int net_rpc_getsid(int argc, const char **argv)
476{
477	return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
478			       rpc_getsid_internals,
479			       argc, argv);
480}
481
482
483/****************************************************************************/
484
485/**
486 * Basic usage function for 'net rpc user'
487 * @param argc	Standard main() style argc.
488 * @param argv	Standard main() style argv.  Initial components are already
489 *		stripped.
490 **/
491
492static int rpc_user_usage(int argc, const char **argv)
493{
494	return net_help_user(argc, argv);
495}
496
497/**
498 * Add a new user to a remote RPC server
499 *
500 * All parameters are provided by the run_rpc_command function, except for
501 * argc, argv which are passes through.
502 *
503 * @param domain_sid The domain sid acquired from the remote server
504 * @param cli A cli_state connected to the server.
505 * @param mem_ctx Talloc context, destoyed on completion of the function.
506 * @param argc  Standard main() style argc
507 * @param argv  Standard main() style argv.  Initial components are already
508 *              stripped
509 *
510 * @return Normal NTSTATUS return.
511 **/
512
513static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, const char *domain_name,
514				       struct cli_state *cli, TALLOC_CTX *mem_ctx,
515				       int argc, const char **argv) {
516
517	POLICY_HND connect_pol, domain_pol, user_pol;
518	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
519	const char *acct_name;
520	uint16 acb_info;
521	uint32 unknown, user_rid;
522
523	if (argc != 1) {
524		d_printf("User must be specified\n");
525		rpc_user_usage(argc, argv);
526		return NT_STATUS_OK;
527	}
528
529	acct_name = argv[0];
530
531	/* Get sam policy handle */
532
533	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
534				  &connect_pol);
535	if (!NT_STATUS_IS_OK(result)) {
536		goto done;
537	}
538
539	/* Get domain policy handle */
540
541	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
542				      MAXIMUM_ALLOWED_ACCESS,
543				      domain_sid, &domain_pol);
544	if (!NT_STATUS_IS_OK(result)) {
545		goto done;
546	}
547
548	/* Create domain user */
549
550	acb_info = ACB_NORMAL;
551	unknown = 0xe005000b; /* No idea what this is - a permission mask? */
552
553	result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
554					  acct_name, acb_info, unknown,
555					  &user_pol, &user_rid);
556	if (!NT_STATUS_IS_OK(result)) {
557		goto done;
558	}
559
560 done:
561	if (!NT_STATUS_IS_OK(result)) {
562		d_printf("Failed to add user %s - %s\n", acct_name,
563			 nt_errstr(result));
564	} else {
565		d_printf("Added user %s\n", acct_name);
566	}
567	return result;
568}
569
570/**
571 * Add a new user to a remote RPC server
572 *
573 * @param argc  Standard main() style argc
574 * @param argv  Standard main() style argv.  Initial components are already
575 *              stripped
576 *
577 * @return A shell status integer (0 for success)
578 **/
579
580static int rpc_user_add(int argc, const char **argv)
581{
582	return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_add_internals,
583			       argc, argv);
584}
585
586/**
587 * Delete a user from a remote RPC server
588 *
589 * All parameters are provided by the run_rpc_command function, except for
590 * argc, argv which are passes through.
591 *
592 * @param domain_sid The domain sid acquired from the remote server
593 * @param cli A cli_state connected to the server.
594 * @param mem_ctx Talloc context, destoyed on completion of the function.
595 * @param argc  Standard main() style argc
596 * @param argv  Standard main() style argv.  Initial components are already
597 *              stripped
598 *
599 * @return Normal NTSTATUS return.
600 **/
601
602static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
603				       const char *domain_name,
604				       struct cli_state *cli,
605				       TALLOC_CTX *mem_ctx,
606				       int argc, const char **argv)
607{
608	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
609	POLICY_HND connect_pol, domain_pol, user_pol;
610
611	if (argc < 1) {
612		d_printf("User must be specified\n");
613		rpc_user_usage(argc, argv);
614		return NT_STATUS_OK;
615	}
616	/* Get sam policy and domain handles */
617
618	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
619				  &connect_pol);
620
621	if (!NT_STATUS_IS_OK(result)) {
622		goto done;
623	}
624
625	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
626				      MAXIMUM_ALLOWED_ACCESS,
627				      domain_sid, &domain_pol);
628
629	if (!NT_STATUS_IS_OK(result)) {
630		goto done;
631	}
632
633	/* Get handle on user */
634
635	{
636		uint32 *user_rids, num_rids, *name_types;
637		uint32 flags = 0x000003e8; /* Unknown */
638
639		result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
640					       flags, 1, &argv[0],
641					       &num_rids, &user_rids,
642					       &name_types);
643
644		if (!NT_STATUS_IS_OK(result)) {
645			goto done;
646		}
647
648		result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
649					    MAXIMUM_ALLOWED_ACCESS,
650					    user_rids[0], &user_pol);
651
652		if (!NT_STATUS_IS_OK(result)) {
653			goto done;
654		}
655	}
656
657	/* Delete user */
658
659	result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
660
661	if (!NT_STATUS_IS_OK(result)) {
662		goto done;
663	}
664
665	/* Display results */
666
667 done:
668	return result;
669
670}
671
672/**
673 * Rename a user on a remote RPC server
674 *
675 * All parameters are provided by the run_rpc_command function, except for
676 * argc, argv which are passes through.
677 *
678 * @param domain_sid The domain sid acquired from the remote server
679 * @param cli A cli_state connected to the server.
680 * @param mem_ctx Talloc context, destoyed on completion of the function.
681 * @param argc  Standard main() style argc
682 * @param argv  Standard main() style argv.  Initial components are already
683 *              stripped
684 *
685 * @return Normal NTSTATUS return.
686 **/
687
688static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char *domain_name,
689					  struct cli_state *cli, TALLOC_CTX *mem_ctx,
690					  int argc, const char **argv) {
691
692	POLICY_HND connect_pol, domain_pol, user_pol;
693	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
694	uint32 info_level = 7;
695	const char *old_name, *new_name;
696	uint32 *user_rid;
697	uint32 flags = 0x000003e8; /* Unknown */
698	uint32 num_rids, *name_types;
699	uint32 num_names = 1;
700	const char **names;
701	SAM_USERINFO_CTR *user_ctr;
702	SAM_USERINFO_CTR ctr;
703	SAM_USER_INFO_7 info7;
704
705	if (argc != 2) {
706		d_printf("New and old username must be specified\n");
707		rpc_user_usage(argc, argv);
708		return NT_STATUS_OK;
709	}
710
711	old_name = argv[0];
712	new_name = argv[1];
713
714	ZERO_STRUCT(ctr);
715	ZERO_STRUCT(user_ctr);
716
717	/* Get sam policy handle */
718
719	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
720				  &connect_pol);
721	if (!NT_STATUS_IS_OK(result)) {
722		goto done;
723	}
724
725	/* Get domain policy handle */
726
727	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
728				      MAXIMUM_ALLOWED_ACCESS,
729				      domain_sid, &domain_pol);
730	if (!NT_STATUS_IS_OK(result)) {
731		goto done;
732	}
733
734	names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
735	names[0] = old_name;
736	result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
737				       flags, num_names, names,
738				       &num_rids, &user_rid, &name_types);
739	if (!NT_STATUS_IS_OK(result)) {
740		goto done;
741	}
742
743	/* Open domain user */
744	result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
745				    MAXIMUM_ALLOWED_ACCESS, user_rid[0], &user_pol);
746
747	if (!NT_STATUS_IS_OK(result)) {
748		goto done;
749	}
750
751	/* Query user info */
752	result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol,
753					 info_level, &user_ctr);
754
755	if (!NT_STATUS_IS_OK(result)) {
756		goto done;
757	}
758
759	ctr.switch_value = info_level;
760	ctr.info.id7 = &info7;
761
762	init_sam_user_info7(&info7, new_name);
763
764	/* Set new name */
765	result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol,
766				       info_level, &cli->user_session_key, &ctr);
767
768	if (!NT_STATUS_IS_OK(result)) {
769		goto done;
770	}
771
772 done:
773	if (!NT_STATUS_IS_OK(result)) {
774		d_printf("Failed to rename user from %s to %s - %s\n", old_name, new_name,
775			 nt_errstr(result));
776	} else {
777		d_printf("Renamed user from %s to %s\n", old_name, new_name);
778	}
779	return result;
780}
781
782
783/**
784 * Rename a user on a remote RPC server
785 *
786 * @param argc  Standard main() style argc
787 * @param argv  Standard main() style argv.  Initial components are already
788 *              stripped
789 *
790 * @return A shell status integer (0 for success)
791 **/
792
793static int rpc_user_rename(int argc, const char **argv)
794{
795	return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_rename_internals,
796			       argc, argv);
797}
798
799/**
800 * Delete a user from a remote RPC server
801 *
802 * @param argc  Standard main() style argc
803 * @param argv  Standard main() style argv.  Initial components are already
804 *              stripped
805 *
806 * @return A shell status integer (0 for success)
807 **/
808
809static int rpc_user_delete(int argc, const char **argv)
810{
811	return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_del_internals,
812			       argc, argv);
813}
814
815/**
816 * Set a password for a user on a remote RPC server
817 *
818 * All parameters are provided by the run_rpc_command function, except for
819 * argc, argv which are passes through.
820 *
821 * @param domain_sid The domain sid acquired from the remote server
822 * @param cli A cli_state connected to the server.
823 * @param mem_ctx Talloc context, destoyed on completion of the function.
824 * @param argc  Standard main() style argc
825 * @param argv  Standard main() style argv.  Initial components are already
826 *              stripped
827 *
828 * @return Normal NTSTATUS return.
829 **/
830
831static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid,
832					    const char *domain_name,
833					    struct cli_state *cli,
834					    TALLOC_CTX *mem_ctx,
835					    int argc, const char **argv)
836{
837	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
838	POLICY_HND connect_pol, domain_pol, user_pol;
839	SAM_USERINFO_CTR ctr;
840	SAM_USER_INFO_24 p24;
841	uchar pwbuf[516];
842	const char *user;
843	const char *new_password;
844	char *prompt = NULL;
845
846	if (argc < 1) {
847		d_printf("User must be specified\n");
848		rpc_user_usage(argc, argv);
849		return NT_STATUS_OK;
850	}
851
852	user = argv[0];
853
854	if (argv[1]) {
855		new_password = argv[1];
856	} else {
857		asprintf(&prompt, "Enter new password for %s:", user);
858		new_password = getpass(prompt);
859		SAFE_FREE(prompt);
860	}
861
862	/* Get sam policy and domain handles */
863
864	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
865				  &connect_pol);
866
867	if (!NT_STATUS_IS_OK(result)) {
868		goto done;
869	}
870
871	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
872				      MAXIMUM_ALLOWED_ACCESS,
873				      domain_sid, &domain_pol);
874
875	if (!NT_STATUS_IS_OK(result)) {
876		goto done;
877	}
878
879	/* Get handle on user */
880
881	{
882		uint32 *user_rids, num_rids, *name_types;
883		uint32 flags = 0x000003e8; /* Unknown */
884
885		result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
886					       flags, 1, &user,
887					       &num_rids, &user_rids,
888					       &name_types);
889
890		if (!NT_STATUS_IS_OK(result)) {
891			goto done;
892		}
893
894		result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
895					    MAXIMUM_ALLOWED_ACCESS,
896					    user_rids[0], &user_pol);
897
898		if (!NT_STATUS_IS_OK(result)) {
899			goto done;
900		}
901	}
902
903	/* Set password on account */
904
905	ZERO_STRUCT(ctr);
906	ZERO_STRUCT(p24);
907
908	encode_pw_buffer(pwbuf, new_password, STR_UNICODE);
909
910	init_sam_user_info24(&p24, (char *)pwbuf,24);
911
912	ctr.switch_value = 24;
913	ctr.info.id24 = &p24;
914
915	result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24,
916				       &cli->user_session_key, &ctr);
917
918	if (!NT_STATUS_IS_OK(result)) {
919		goto done;
920	}
921
922	/* Display results */
923
924 done:
925	return result;
926
927}
928
929/**
930 * Set a user's password on a remote RPC server
931 *
932 * @param argc  Standard main() style argc
933 * @param argv  Standard main() style argv.  Initial components are already
934 *              stripped
935 *
936 * @return A shell status integer (0 for success)
937 **/
938
939static int rpc_user_password(int argc, const char **argv)
940{
941	return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_password_internals,
942			       argc, argv);
943}
944
945/**
946 * List user's groups on a remote RPC server
947 *
948 * All parameters are provided by the run_rpc_command function, except for
949 * argc, argv which are passes through.
950 *
951 * @param domain_sid The domain sid acquired from the remote server
952 * @param cli A cli_state connected to the server.
953 * @param mem_ctx Talloc context, destoyed on completion of the function.
954 * @param argc  Standard main() style argc
955 * @param argv  Standard main() style argv.  Initial components are already
956 *              stripped
957 *
958 * @return Normal NTSTATUS return.
959 **/
960
961static NTSTATUS
962rpc_user_info_internals(const DOM_SID *domain_sid, const char *domain_name,
963			struct cli_state *cli,
964			TALLOC_CTX *mem_ctx, int argc, const char **argv)
965{
966	POLICY_HND connect_pol, domain_pol, user_pol;
967	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
968	uint32 *rids, num_rids, *name_types, num_names;
969	uint32 flags = 0x000003e8; /* Unknown */
970	int i;
971	char **names;
972	DOM_GID *user_gids;
973
974	if (argc < 1) {
975		d_printf("User must be specified\n");
976		rpc_user_usage(argc, argv);
977		return NT_STATUS_OK;
978	}
979	/* Get sam policy handle */
980
981	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
982				  &connect_pol);
983	if (!NT_STATUS_IS_OK(result)) goto done;
984
985	/* Get domain policy handle */
986
987	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
988				      MAXIMUM_ALLOWED_ACCESS,
989				      domain_sid, &domain_pol);
990	if (!NT_STATUS_IS_OK(result)) goto done;
991
992	/* Get handle on user */
993
994	result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
995				       flags, 1, &argv[0],
996				       &num_rids, &rids, &name_types);
997
998	if (!NT_STATUS_IS_OK(result)) goto done;
999
1000	result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
1001				    MAXIMUM_ALLOWED_ACCESS,
1002				    rids[0], &user_pol);
1003	if (!NT_STATUS_IS_OK(result)) goto done;
1004
1005	result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
1006					   &num_rids, &user_gids);
1007
1008	if (!NT_STATUS_IS_OK(result)) goto done;
1009
1010	/* Look up rids */
1011
1012	if (num_rids) {
1013		rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
1014
1015		for (i = 0; i < num_rids; i++)
1016                	rids[i] = user_gids[i].g_rid;
1017
1018		result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
1019				      	      num_rids, rids,
1020				      	      &num_names, &names, &name_types);
1021
1022		if (!NT_STATUS_IS_OK(result)) {
1023			goto done;
1024		}
1025
1026		/* Display results */
1027
1028		for (i = 0; i < num_names; i++)
1029			printf("%s\n", names[i]);
1030	}
1031 done:
1032	return result;
1033}
1034
1035/**
1036 * List a user's groups from a remote RPC server
1037 *
1038 * @param argc  Standard main() style argc
1039 * @param argv  Standard main() style argv.  Initial components are already
1040 *              stripped
1041 *
1042 * @return A shell status integer (0 for success)
1043 **/
1044
1045static int rpc_user_info(int argc, const char **argv)
1046{
1047	return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_info_internals,
1048			       argc, argv);
1049}
1050
1051/**
1052 * List users on a remote RPC server
1053 *
1054 * All parameters are provided by the run_rpc_command function, except for
1055 * argc, argv which are passes through.
1056 *
1057 * @param domain_sid The domain sid acquired from the remote server
1058 * @param cli A cli_state connected to the server.
1059 * @param mem_ctx Talloc context, destoyed on completion of the function.
1060 * @param argc  Standard main() style argc
1061 * @param argv  Standard main() style argv.  Initial components are already
1062 *              stripped
1063 *
1064 * @return Normal NTSTATUS return.
1065 **/
1066
1067static NTSTATUS
1068rpc_user_list_internals(const DOM_SID *domain_sid, const char *domain_name,
1069			struct cli_state *cli,
1070			TALLOC_CTX *mem_ctx, int argc, const char **argv)
1071{
1072	POLICY_HND connect_pol, domain_pol;
1073	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1074	uint32 start_idx=0, num_entries, i, loop_count = 0;
1075	SAM_DISPINFO_CTR ctr;
1076	SAM_DISPINFO_1 info1;
1077
1078	/* Get sam policy handle */
1079
1080	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1081				  &connect_pol);
1082	if (!NT_STATUS_IS_OK(result)) {
1083		goto done;
1084	}
1085
1086	/* Get domain policy handle */
1087
1088	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1089				      MAXIMUM_ALLOWED_ACCESS,
1090				      domain_sid, &domain_pol);
1091	if (!NT_STATUS_IS_OK(result)) {
1092		goto done;
1093	}
1094
1095	/* Query domain users */
1096	ZERO_STRUCT(ctr);
1097	ZERO_STRUCT(info1);
1098	ctr.sam.info1 = &info1;
1099	if (opt_long_list_entries)
1100		d_printf("\nUser name             Comment"\
1101			 "\n-----------------------------\n");
1102	do {
1103		fstring user, desc;
1104		uint32 max_entries, max_size;
1105
1106		get_query_dispinfo_params(
1107			loop_count, &max_entries, &max_size);
1108
1109		result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
1110						 &start_idx, 1, &num_entries,
1111						 max_entries, max_size, &ctr);
1112		loop_count++;
1113
1114		for (i = 0; i < num_entries; i++) {
1115			unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user)-1);
1116			if (opt_long_list_entries)
1117				unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1);
1118
1119			if (opt_long_list_entries)
1120				printf("%-21.21s %s\n", user, desc);
1121			else
1122				printf("%s\n", user);
1123		}
1124	} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1125
1126 done:
1127	return result;
1128}
1129
1130/**
1131 * 'net rpc user' entrypoint.
1132 * @param argc  Standard main() style argc
1133 * @param argc  Standard main() style argv.  Initial components are already
1134 *              stripped
1135 **/
1136
1137int net_rpc_user(int argc, const char **argv)
1138{
1139	struct functable func[] = {
1140		{"add", rpc_user_add},
1141		{"info", rpc_user_info},
1142		{"delete", rpc_user_delete},
1143		{"password", rpc_user_password},
1144		{"rename", rpc_user_rename},
1145		{NULL, NULL}
1146	};
1147
1148	if (argc == 0) {
1149		if (opt_long_list_entries) {
1150		} else {
1151		}
1152			return run_rpc_command(NULL,PI_SAMR, 0,
1153					       rpc_user_list_internals,
1154					       argc, argv);
1155	}
1156
1157	return net_run_function(argc, argv, func, rpc_user_usage);
1158}
1159
1160
1161/****************************************************************************/
1162
1163/**
1164 * Basic usage function for 'net rpc group'
1165 * @param argc	Standard main() style argc.
1166 * @param argv	Standard main() style argv.  Initial components are already
1167 *		stripped.
1168 **/
1169
1170static int rpc_group_usage(int argc, const char **argv)
1171{
1172	return net_help_group(argc, argv);
1173}
1174
1175/**
1176 * Delete group on a remote RPC server
1177 *
1178 * All parameters are provided by the run_rpc_command function, except for
1179 * argc, argv which are passes through.
1180 *
1181 * @param domain_sid The domain sid acquired from the remote server
1182 * @param cli A cli_state connected to the server.
1183 * @param mem_ctx Talloc context, destoyed on completion of the function.
1184 * @param argc  Standard main() style argc
1185 * @param argv  Standard main() style argv.  Initial components are already
1186 *              stripped
1187 *
1188 * @return Normal NTSTATUS return.
1189 **/
1190
1191static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
1192                                           const char *domain_name,
1193                                           struct cli_state *cli,
1194                                           TALLOC_CTX *mem_ctx,
1195                                           int argc, const char **argv)
1196{
1197	POLICY_HND connect_pol, domain_pol, group_pol, user_pol;
1198	BOOL group_is_primary = False;
1199	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1200
1201	uint32 *group_rids, num_rids, *name_types, num_members,
1202               *group_attrs, group_rid;
1203	uint32 flags = 0x000003e8; /* Unknown */
1204	/* char **names; */
1205	int i;
1206	/* DOM_GID *user_gids; */
1207	SAM_USERINFO_CTR *user_ctr;
1208	fstring temp;
1209
1210	if (argc < 1) {
1211        	d_printf("specify group\n");
1212		rpc_group_usage(argc,argv);
1213		return NT_STATUS_OK; /* ok? */
1214	}
1215
1216        result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1217                                  &connect_pol);
1218
1219        if (!NT_STATUS_IS_OK(result)) {
1220		d_printf("Request samr_connect failed\n");
1221        	goto done;
1222        }
1223
1224        result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1225                                      MAXIMUM_ALLOWED_ACCESS,
1226                                      domain_sid, &domain_pol);
1227
1228        if (!NT_STATUS_IS_OK(result)) {
1229		d_printf("Request open_domain failed\n");
1230        	goto done;
1231        }
1232
1233	result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
1234				       flags, 1, &argv[0],
1235				       &num_rids, &group_rids,
1236				       &name_types);
1237
1238	if (!NT_STATUS_IS_OK(result)) {
1239		d_printf("Lookup of '%s' failed\n",argv[0]);
1240   		goto done;
1241	}
1242
1243	switch (name_types[0])
1244	{
1245	case SID_NAME_DOM_GRP:
1246		result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
1247					     MAXIMUM_ALLOWED_ACCESS,
1248					     group_rids[0], &group_pol);
1249		if (!NT_STATUS_IS_OK(result)) {
1250			d_printf("Request open_group failed");
1251   			goto done;
1252		}
1253
1254		group_rid = group_rids[0];
1255
1256		result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
1257                                 &num_members, &group_rids,
1258                                 &group_attrs);
1259
1260		if (!NT_STATUS_IS_OK(result)) {
1261			d_printf("Unable to query group members of %s",argv[0]);
1262   			goto done;
1263		}
1264
1265		if (opt_verbose) {
1266			d_printf("Domain Group %s (rid: %d) has %d members\n",
1267				argv[0],group_rid,num_members);
1268		}
1269
1270		/* Check if group is anyone's primary group */
1271                for (i = 0; i < num_members; i++)
1272		{
1273	                result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
1274					            MAXIMUM_ALLOWED_ACCESS,
1275					            group_rids[i], &user_pol);
1276
1277	        	if (!NT_STATUS_IS_OK(result)) {
1278				d_printf("Unable to open group member %d\n",group_rids[i]);
1279	           		goto done;
1280	        	}
1281
1282	                ZERO_STRUCT(user_ctr);
1283
1284	                result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol,
1285	                                                 21, &user_ctr);
1286
1287	        	if (!NT_STATUS_IS_OK(result)) {
1288				d_printf("Unable to lookup userinfo for group member %d\n",group_rids[i]);
1289	           		goto done;
1290	        	}
1291
1292			if (user_ctr->info.id21->group_rid == group_rid) {
1293				unistr2_to_ascii(temp, &(user_ctr->info.id21)->uni_user_name,
1294						sizeof(temp)-1);
1295				if (opt_verbose)
1296					d_printf("Group is primary group of %s\n",temp);
1297				group_is_primary = True;
1298                        }
1299
1300			cli_samr_close(cli, mem_ctx, &user_pol);
1301		}
1302
1303		if (group_is_primary) {
1304			d_printf("Unable to delete group because some of it's "
1305				 "members have it as primary group\n");
1306			result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1307			goto done;
1308		}
1309
1310		/* remove all group members */
1311		for (i = 0; i < num_members; i++)
1312		{
1313			if (opt_verbose)
1314				d_printf("Remove group member %d...",group_rids[i]);
1315			result = cli_samr_del_groupmem(cli, mem_ctx, &group_pol, group_rids[i]);
1316
1317			if (NT_STATUS_IS_OK(result)) {
1318				if (opt_verbose)
1319					d_printf("ok\n");
1320			} else {
1321				if (opt_verbose)
1322					d_printf("failed\n");
1323				goto done;
1324			}
1325		}
1326
1327		result = cli_samr_delete_dom_group(cli, mem_ctx, &group_pol);
1328
1329		break;
1330	/* removing a local group is easier... */
1331	case SID_NAME_ALIAS:
1332		result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
1333					     MAXIMUM_ALLOWED_ACCESS,
1334					     group_rids[0], &group_pol);
1335
1336		if (!NT_STATUS_IS_OK(result)) {
1337			d_printf("Request open_alias failed\n");
1338   			goto done;
1339		}
1340
1341		result = cli_samr_delete_dom_alias(cli, mem_ctx, &group_pol);
1342		break;
1343	default:
1344		d_printf("%s is of type %s. This command is only for deleting local or global groups\n",
1345			argv[0],sid_type_lookup(name_types[0]));
1346		result = NT_STATUS_UNSUCCESSFUL;
1347		goto done;
1348	}
1349
1350
1351	if (NT_STATUS_IS_OK(result)) {
1352		if (opt_verbose)
1353			d_printf("Deleted %s '%s'\n",sid_type_lookup(name_types[0]),argv[0]);
1354	} else {
1355		d_printf("Deleting of %s failed: %s\n",argv[0],
1356			get_friendly_nt_error_msg(result));
1357	}
1358
1359 done:
1360	return result;
1361
1362}
1363
1364static int rpc_group_delete(int argc, const char **argv)
1365{
1366	return run_rpc_command(NULL, PI_SAMR, 0, rpc_group_delete_internals,
1367                               argc,argv);
1368}
1369
1370static NTSTATUS
1371rpc_group_add_internals(const DOM_SID *domain_sid, const char *domain_name,
1372			struct cli_state *cli,
1373			TALLOC_CTX *mem_ctx, int argc, const char **argv)
1374{
1375	POLICY_HND connect_pol, domain_pol, group_pol;
1376	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1377	GROUP_INFO_CTR group_info;
1378
1379	if (argc != 1) {
1380		d_printf("Group name must be specified\n");
1381		rpc_group_usage(argc, argv);
1382		return NT_STATUS_OK;
1383	}
1384
1385	/* Get sam policy handle */
1386
1387	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1388				  &connect_pol);
1389	if (!NT_STATUS_IS_OK(result)) goto done;
1390
1391	/* Get domain policy handle */
1392
1393	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1394				      MAXIMUM_ALLOWED_ACCESS,
1395				      domain_sid, &domain_pol);
1396	if (!NT_STATUS_IS_OK(result)) goto done;
1397
1398	/* Create the group */
1399
1400	result = cli_samr_create_dom_group(cli, mem_ctx, &domain_pol,
1401					   argv[0], MAXIMUM_ALLOWED_ACCESS,
1402					   &group_pol);
1403	if (!NT_STATUS_IS_OK(result)) goto done;
1404
1405	if (strlen(opt_comment) == 0) goto done;
1406
1407	/* We've got a comment to set */
1408
1409	group_info.switch_value1 = 4;
1410	init_samr_group_info4(&group_info.group.info4, opt_comment);
1411
1412	result = cli_samr_set_groupinfo(cli, mem_ctx, &group_pol, &group_info);
1413	if (!NT_STATUS_IS_OK(result)) goto done;
1414
1415 done:
1416	if (NT_STATUS_IS_OK(result))
1417		DEBUG(5, ("add group succeeded\n"));
1418	else
1419		d_printf("add group failed: %s\n", nt_errstr(result));
1420
1421	return result;
1422}
1423
1424static NTSTATUS
1425rpc_alias_add_internals(const DOM_SID *domain_sid, const char *domain_name,
1426			struct cli_state *cli,
1427			TALLOC_CTX *mem_ctx, int argc, const char **argv)
1428{
1429	POLICY_HND connect_pol, domain_pol, alias_pol;
1430	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1431	ALIAS_INFO_CTR alias_info;
1432
1433	if (argc != 1) {
1434		d_printf("Alias name must be specified\n");
1435		rpc_group_usage(argc, argv);
1436		return NT_STATUS_OK;
1437	}
1438
1439	/* Get sam policy handle */
1440
1441	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1442				  &connect_pol);
1443	if (!NT_STATUS_IS_OK(result)) goto done;
1444
1445	/* Get domain policy handle */
1446
1447	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1448				      MAXIMUM_ALLOWED_ACCESS,
1449				      domain_sid, &domain_pol);
1450	if (!NT_STATUS_IS_OK(result)) goto done;
1451
1452	/* Create the group */
1453
1454	result = cli_samr_create_dom_alias(cli, mem_ctx, &domain_pol,
1455					   argv[0], &alias_pol);
1456	if (!NT_STATUS_IS_OK(result)) goto done;
1457
1458	if (strlen(opt_comment) == 0) goto done;
1459
1460	/* We've got a comment to set */
1461
1462	alias_info.switch_value1 = 3;
1463	alias_info.switch_value2 = 3;
1464	init_samr_alias_info3(&alias_info.alias.info3, opt_comment);
1465
1466	result = cli_samr_set_aliasinfo(cli, mem_ctx, &alias_pol, &alias_info);
1467	if (!NT_STATUS_IS_OK(result)) goto done;
1468
1469 done:
1470	if (NT_STATUS_IS_OK(result))
1471		DEBUG(5, ("add alias succeeded\n"));
1472	else
1473		d_printf("add alias failed: %s\n", nt_errstr(result));
1474
1475	return result;
1476}
1477
1478static int rpc_group_add(int argc, const char **argv)
1479{
1480	if (opt_localgroup)
1481		return run_rpc_command(NULL, PI_SAMR, 0,
1482				       rpc_alias_add_internals,
1483				       argc, argv);
1484
1485	return run_rpc_command(NULL, PI_SAMR, 0,
1486			       rpc_group_add_internals,
1487			       argc, argv);
1488}
1489
1490static NTSTATUS
1491get_sid_from_name(struct cli_state *cli, TALLOC_CTX *mem_ctx, const char *name,
1492		  DOM_SID *sid, enum SID_NAME_USE *type)
1493{
1494	int current_pipe = cli->pipe_idx;
1495
1496	DOM_SID *sids = NULL;
1497	uint32 *types = NULL;
1498	POLICY_HND lsa_pol;
1499	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1500
1501	if (current_pipe != PI_LSARPC) {
1502
1503		if (current_pipe != -1)
1504			cli_nt_session_close(cli);
1505
1506		if (!cli_nt_session_open(cli, PI_LSARPC))
1507			goto done;
1508	}
1509
1510	result = cli_lsa_open_policy(cli, mem_ctx, False,
1511				     SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
1512
1513	if (!NT_STATUS_IS_OK(result))
1514		goto done;
1515
1516	result = cli_lsa_lookup_names(cli, mem_ctx, &lsa_pol, 1,
1517				      &name, &sids, &types);
1518
1519	if (NT_STATUS_IS_OK(result)) {
1520		sid_copy(sid, &sids[0]);
1521		*type = types[0];
1522	}
1523
1524	cli_lsa_close(cli, mem_ctx, &lsa_pol);
1525
1526 done:
1527	if (current_pipe != PI_LSARPC) {
1528		cli_nt_session_close(cli);
1529		if (current_pipe != -1)
1530			cli_nt_session_open(cli, current_pipe);
1531	}
1532
1533	if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
1534
1535		/* Try as S-1-5-whatever */
1536
1537		DOM_SID tmp_sid;
1538
1539		if (string_to_sid(&tmp_sid, name)) {
1540			sid_copy(sid, &tmp_sid);
1541			*type = SID_NAME_UNKNOWN;
1542			result = NT_STATUS_OK;
1543		}
1544	}
1545
1546	return result;
1547}
1548
1549static NTSTATUS
1550rpc_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1551		 const DOM_SID *group_sid, const char *member)
1552{
1553	POLICY_HND connect_pol, domain_pol;
1554	NTSTATUS result;
1555	uint32 group_rid;
1556	POLICY_HND group_pol;
1557
1558	uint32 num_rids;
1559	uint32 *rids = NULL;
1560	uint32 *rid_types = NULL;
1561
1562	DOM_SID sid;
1563
1564	sid_copy(&sid, group_sid);
1565
1566	if (!sid_split_rid(&sid, &group_rid))
1567		return NT_STATUS_UNSUCCESSFUL;
1568
1569	/* Get sam policy handle */
1570	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1571				  &connect_pol);
1572	if (!NT_STATUS_IS_OK(result))
1573		return result;
1574
1575	/* Get domain policy handle */
1576	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1577				      MAXIMUM_ALLOWED_ACCESS,
1578				      &sid, &domain_pol);
1579	if (!NT_STATUS_IS_OK(result))
1580		return result;
1581
1582	result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
1583				       1, &member,
1584				       &num_rids, &rids, &rid_types);
1585
1586	if (!NT_STATUS_IS_OK(result)) {
1587		d_printf("Could not lookup up group member %s\n", member);
1588		goto done;
1589	}
1590
1591	result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
1592				     MAXIMUM_ALLOWED_ACCESS,
1593				     group_rid, &group_pol);
1594
1595	if (!NT_STATUS_IS_OK(result))
1596		goto done;
1597
1598	result = cli_samr_add_groupmem(cli, mem_ctx, &group_pol, rids[0]);
1599
1600 done:
1601	cli_samr_close(cli, mem_ctx, &connect_pol);
1602	return result;
1603}
1604
1605static NTSTATUS
1606rpc_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1607		 const DOM_SID *alias_sid, const char *member)
1608{
1609	POLICY_HND connect_pol, domain_pol;
1610	NTSTATUS result;
1611	uint32 alias_rid;
1612	POLICY_HND alias_pol;
1613
1614	DOM_SID member_sid;
1615	enum SID_NAME_USE member_type;
1616
1617	DOM_SID sid;
1618
1619	sid_copy(&sid, alias_sid);
1620
1621	if (!sid_split_rid(&sid, &alias_rid))
1622		return NT_STATUS_UNSUCCESSFUL;
1623
1624	result = get_sid_from_name(cli, mem_ctx, member,
1625				   &member_sid, &member_type);
1626
1627	if (!NT_STATUS_IS_OK(result)) {
1628		d_printf("Could not lookup up group member %s\n", member);
1629		return result;
1630	}
1631
1632	/* Get sam policy handle */
1633	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1634				  &connect_pol);
1635	if (!NT_STATUS_IS_OK(result)) {
1636		goto done;
1637	}
1638
1639	/* Get domain policy handle */
1640	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1641				      MAXIMUM_ALLOWED_ACCESS,
1642				      &sid, &domain_pol);
1643	if (!NT_STATUS_IS_OK(result)) {
1644		goto done;
1645	}
1646
1647	result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
1648				     MAXIMUM_ALLOWED_ACCESS,
1649				     alias_rid, &alias_pol);
1650
1651	if (!NT_STATUS_IS_OK(result))
1652		return result;
1653
1654	result = cli_samr_add_aliasmem(cli, mem_ctx, &alias_pol, &member_sid);
1655
1656	if (!NT_STATUS_IS_OK(result))
1657		return result;
1658
1659 done:
1660	cli_samr_close(cli, mem_ctx, &connect_pol);
1661	return result;
1662}
1663
1664static NTSTATUS
1665rpc_group_addmem_internals(const DOM_SID *domain_sid, const char *domain_name,
1666			   struct cli_state *cli,
1667			   TALLOC_CTX *mem_ctx, int argc, const char **argv)
1668{
1669	DOM_SID group_sid;
1670	enum SID_NAME_USE group_type;
1671
1672	if (argc != 2) {
1673		d_printf("Usage: 'net rpc group addmem <group> <member>\n");
1674		return NT_STATUS_UNSUCCESSFUL;
1675	}
1676
1677	if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
1678					       &group_sid, &group_type))) {
1679		d_printf("Could not lookup group name %s\n", argv[0]);
1680		return NT_STATUS_UNSUCCESSFUL;
1681	}
1682
1683	if (group_type == SID_NAME_DOM_GRP) {
1684		NTSTATUS result = rpc_add_groupmem(cli, mem_ctx,
1685						   &group_sid, argv[1]);
1686
1687		if (!NT_STATUS_IS_OK(result)) {
1688			d_printf("Could not add %s to %s: %s\n",
1689				 argv[1], argv[0], nt_errstr(result));
1690		}
1691		return result;
1692	}
1693
1694	if (group_type == SID_NAME_ALIAS) {
1695		NTSTATUS result = rpc_add_aliasmem(cli, mem_ctx,
1696						   &group_sid, argv[1]);
1697
1698		if (!NT_STATUS_IS_OK(result)) {
1699			d_printf("Could not add %s to %s: %s\n",
1700				 argv[1], argv[0], nt_errstr(result));
1701		}
1702		return result;
1703	}
1704
1705	d_printf("Can only add members to global or local groups which "
1706		 "%s is not\n", argv[0]);
1707
1708	return NT_STATUS_UNSUCCESSFUL;
1709}
1710
1711static int rpc_group_addmem(int argc, const char **argv)
1712{
1713	return run_rpc_command(NULL, PI_SAMR, 0,
1714			       rpc_group_addmem_internals,
1715			       argc, argv);
1716}
1717
1718static NTSTATUS
1719rpc_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1720		 const DOM_SID *group_sid, const char *member)
1721{
1722	POLICY_HND connect_pol, domain_pol;
1723	NTSTATUS result;
1724	uint32 group_rid;
1725	POLICY_HND group_pol;
1726
1727	uint32 num_rids;
1728	uint32 *rids = NULL;
1729	uint32 *rid_types = NULL;
1730
1731	DOM_SID sid;
1732
1733	sid_copy(&sid, group_sid);
1734
1735	if (!sid_split_rid(&sid, &group_rid))
1736		return NT_STATUS_UNSUCCESSFUL;
1737
1738	/* Get sam policy handle */
1739	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1740				  &connect_pol);
1741	if (!NT_STATUS_IS_OK(result))
1742		return result;
1743
1744	/* Get domain policy handle */
1745	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1746				      MAXIMUM_ALLOWED_ACCESS,
1747				      &sid, &domain_pol);
1748	if (!NT_STATUS_IS_OK(result))
1749		return result;
1750
1751	result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
1752				       1, &member,
1753				       &num_rids, &rids, &rid_types);
1754
1755	if (!NT_STATUS_IS_OK(result)) {
1756		d_printf("Could not lookup up group member %s\n", member);
1757		goto done;
1758	}
1759
1760	result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
1761				     MAXIMUM_ALLOWED_ACCESS,
1762				     group_rid, &group_pol);
1763
1764	if (!NT_STATUS_IS_OK(result))
1765		goto done;
1766
1767	result = cli_samr_del_groupmem(cli, mem_ctx, &group_pol, rids[0]);
1768
1769 done:
1770	cli_samr_close(cli, mem_ctx, &connect_pol);
1771	return result;
1772}
1773
1774static NTSTATUS
1775rpc_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
1776		 const DOM_SID *alias_sid, const char *member)
1777{
1778	POLICY_HND connect_pol, domain_pol;
1779	NTSTATUS result;
1780	uint32 alias_rid;
1781	POLICY_HND alias_pol;
1782
1783	DOM_SID member_sid;
1784	enum SID_NAME_USE member_type;
1785
1786	DOM_SID sid;
1787
1788	sid_copy(&sid, alias_sid);
1789
1790	if (!sid_split_rid(&sid, &alias_rid))
1791		return NT_STATUS_UNSUCCESSFUL;
1792
1793	result = get_sid_from_name(cli, mem_ctx, member,
1794				   &member_sid, &member_type);
1795
1796	if (!NT_STATUS_IS_OK(result)) {
1797		d_printf("Could not lookup up group member %s\n", member);
1798		return result;
1799	}
1800
1801	/* Get sam policy handle */
1802	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1803				  &connect_pol);
1804	if (!NT_STATUS_IS_OK(result)) {
1805		goto done;
1806	}
1807
1808	/* Get domain policy handle */
1809	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1810				      MAXIMUM_ALLOWED_ACCESS,
1811				      &sid, &domain_pol);
1812	if (!NT_STATUS_IS_OK(result)) {
1813		goto done;
1814	}
1815
1816	result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
1817				     MAXIMUM_ALLOWED_ACCESS,
1818				     alias_rid, &alias_pol);
1819
1820	if (!NT_STATUS_IS_OK(result))
1821		return result;
1822
1823	result = cli_samr_del_aliasmem(cli, mem_ctx, &alias_pol, &member_sid);
1824
1825	if (!NT_STATUS_IS_OK(result))
1826		return result;
1827
1828 done:
1829	cli_samr_close(cli, mem_ctx, &connect_pol);
1830	return result;
1831}
1832
1833static NTSTATUS
1834rpc_group_delmem_internals(const DOM_SID *domain_sid, const char *domain_name,
1835			   struct cli_state *cli,
1836			   TALLOC_CTX *mem_ctx, int argc, const char **argv)
1837{
1838	DOM_SID group_sid;
1839	enum SID_NAME_USE group_type;
1840
1841	if (argc != 2) {
1842		d_printf("Usage: 'net rpc group delmem <group> <member>\n");
1843		return NT_STATUS_UNSUCCESSFUL;
1844	}
1845
1846	if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
1847					       &group_sid, &group_type))) {
1848		d_printf("Could not lookup group name %s\n", argv[0]);
1849		return NT_STATUS_UNSUCCESSFUL;
1850	}
1851
1852	if (group_type == SID_NAME_DOM_GRP) {
1853		NTSTATUS result = rpc_del_groupmem(cli, mem_ctx,
1854						   &group_sid, argv[1]);
1855
1856		if (!NT_STATUS_IS_OK(result)) {
1857			d_printf("Could not del %s from %s: %s\n",
1858				 argv[1], argv[0], nt_errstr(result));
1859		}
1860		return result;
1861	}
1862
1863	if (group_type == SID_NAME_ALIAS) {
1864		NTSTATUS result = rpc_del_aliasmem(cli, mem_ctx,
1865						   &group_sid, argv[1]);
1866
1867		if (!NT_STATUS_IS_OK(result)) {
1868			d_printf("Could not del %s from %s: %s\n",
1869				 argv[1], argv[0], nt_errstr(result));
1870		}
1871		return result;
1872	}
1873
1874	d_printf("Can only delete members from global or local groups which "
1875		 "%s is not\n", argv[0]);
1876
1877	return NT_STATUS_UNSUCCESSFUL;
1878}
1879
1880static int rpc_group_delmem(int argc, const char **argv)
1881{
1882	return run_rpc_command(NULL, PI_SAMR, 0,
1883			       rpc_group_delmem_internals,
1884			       argc, argv);
1885}
1886
1887/**
1888 * List groups on a remote RPC server
1889 *
1890 * All parameters are provided by the run_rpc_command function, except for
1891 * argc, argv which are passes through.
1892 *
1893 * @param domain_sid The domain sid acquired from the remote server
1894 * @param cli A cli_state connected to the server.
1895 * @param mem_ctx Talloc context, destoyed on completion of the function.
1896 * @param argc  Standard main() style argc
1897 * @param argv  Standard main() style argv.  Initial components are already
1898 *              stripped
1899 *
1900 * @return Normal NTSTATUS return.
1901 **/
1902
1903static NTSTATUS
1904rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name,
1905			 struct cli_state *cli,
1906			 TALLOC_CTX *mem_ctx, int argc, const char **argv)
1907{
1908	POLICY_HND connect_pol, domain_pol;
1909	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1910	uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
1911	struct acct_info *groups;
1912	DOM_SID global_sid_Builtin;
1913	BOOL global = False;
1914	BOOL local = False;
1915	BOOL builtin = False;
1916
1917	if (argc == 0) {
1918		global = True;
1919		local = True;
1920		builtin = True;
1921	}
1922
1923	for (i=0; i<argc; i++) {
1924		if (strequal(argv[i], "global"))
1925			global = True;
1926
1927		if (strequal(argv[i], "local"))
1928			local = True;
1929
1930		if (strequal(argv[i], "builtin"))
1931			builtin = True;
1932	}
1933
1934	string_to_sid(&global_sid_Builtin, "S-1-5-32");
1935
1936	/* Get sam policy handle */
1937
1938	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1939				  &connect_pol);
1940	if (!NT_STATUS_IS_OK(result)) {
1941		goto done;
1942	}
1943
1944	/* Get domain policy handle */
1945
1946	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1947				      MAXIMUM_ALLOWED_ACCESS,
1948				      domain_sid, &domain_pol);
1949	if (!NT_STATUS_IS_OK(result)) {
1950		goto done;
1951	}
1952
1953	/* Query domain groups */
1954	if (opt_long_list_entries)
1955		d_printf("\nGroup name            Comment"\
1956			 "\n-----------------------------\n");
1957	do {
1958		SAM_DISPINFO_CTR ctr;
1959		SAM_DISPINFO_3 info3;
1960		uint32 max_size;
1961
1962		ZERO_STRUCT(ctr);
1963		ZERO_STRUCT(info3);
1964		ctr.sam.info3 = &info3;
1965
1966		if (!global) break;
1967
1968		get_query_dispinfo_params(
1969			loop_count, &max_entries, &max_size);
1970
1971		result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
1972						 &start_idx, 3, &num_entries,
1973						 max_entries, max_size, &ctr);
1974
1975		if (!NT_STATUS_IS_OK(result) &&
1976		    !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
1977			break;
1978
1979		for (i = 0; i < num_entries; i++) {
1980
1981			fstring group, desc;
1982
1983			unistr2_to_ascii(group, &(&ctr.sam.info3->str[i])->uni_grp_name, sizeof(group)-1);
1984			unistr2_to_ascii(desc, &(&ctr.sam.info3->str[i])->uni_grp_desc, sizeof(desc)-1);
1985
1986			if (opt_long_list_entries)
1987				printf("%-21.21s %-50.50s\n",
1988				       group, desc);
1989			else
1990				printf("%s\n", group);
1991		}
1992	} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1993	/* query domain aliases */
1994	start_idx = 0;
1995	do {
1996		if (!local) break;
1997
1998		/* The max_size field in cli_samr_enum_als_groups is more like
1999		 * an account_control field with indiviual bits what to
2000		 * retrieve. Set this to 0xffff as NT4 usrmgr.exe does to get
2001		 * everything. I'm too lazy (sorry) to get this through to
2002		 * rpc_parse/ etc.  Volker */
2003
2004		result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
2005						  &start_idx, 0xffff,
2006						  &groups, &num_entries);
2007
2008		if (!NT_STATUS_IS_OK(result) &&
2009		    !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2010			break;
2011
2012		for (i = 0; i < num_entries; i++) {
2013
2014			char *description = NULL;
2015
2016			if (opt_long_list_entries) {
2017
2018				POLICY_HND alias_pol;
2019				ALIAS_INFO_CTR ctr;
2020
2021				if ((NT_STATUS_IS_OK(cli_samr_open_alias(cli, mem_ctx,
2022									 &domain_pol,
2023									 0x8,
2024									 groups[i].rid,
2025									 &alias_pol))) &&
2026				    (NT_STATUS_IS_OK(cli_samr_query_alias_info(cli, mem_ctx,
2027									       &alias_pol, 3,
2028									       &ctr))) &&
2029				    (NT_STATUS_IS_OK(cli_samr_close(cli, mem_ctx,
2030								    &alias_pol)))) {
2031					description = unistr2_tdup(mem_ctx,
2032								   &ctr.alias.info3.uni_acct_desc);
2033				}
2034			}
2035
2036			if (description != NULL) {
2037				printf("%-21.21s %-50.50s\n",
2038				       groups[i].acct_name,
2039				       description);
2040			} else {
2041				printf("%s\n", groups[i].acct_name);
2042			}
2043		}
2044	} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2045	cli_samr_close(cli, mem_ctx, &domain_pol);
2046	/* Get builtin policy handle */
2047
2048	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
2049				      MAXIMUM_ALLOWED_ACCESS,
2050				      &global_sid_Builtin, &domain_pol);
2051	if (!NT_STATUS_IS_OK(result)) {
2052		goto done;
2053	}
2054	/* query builtin aliases */
2055	start_idx = 0;
2056	do {
2057		if (!builtin) break;
2058
2059		result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
2060						  &start_idx, max_entries,
2061						  &groups, &num_entries);
2062
2063		if (!NT_STATUS_IS_OK(result) &&
2064		    !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2065			break;
2066
2067		for (i = 0; i < num_entries; i++) {
2068
2069			char *description = NULL;
2070
2071			if (opt_long_list_entries) {
2072
2073				POLICY_HND alias_pol;
2074				ALIAS_INFO_CTR ctr;
2075
2076				if ((NT_STATUS_IS_OK(cli_samr_open_alias(cli, mem_ctx,
2077									 &domain_pol,
2078									 0x8,
2079									 groups[i].rid,
2080									 &alias_pol))) &&
2081				    (NT_STATUS_IS_OK(cli_samr_query_alias_info(cli, mem_ctx,
2082									       &alias_pol, 3,
2083									       &ctr))) &&
2084				    (NT_STATUS_IS_OK(cli_samr_close(cli, mem_ctx,
2085								    &alias_pol)))) {
2086					description = unistr2_tdup(mem_ctx,
2087								   &ctr.alias.info3.uni_acct_desc);
2088				}
2089			}
2090
2091			if (description != NULL) {
2092				printf("%-21.21s %-50.50s\n",
2093				       groups[i].acct_name,
2094				       description);
2095			} else {
2096				printf("%s\n", groups[i].acct_name);
2097			}
2098		}
2099	} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2100
2101 done:
2102	return result;
2103}
2104
2105static int rpc_group_list(int argc, const char **argv)
2106{
2107	return run_rpc_command(NULL, PI_SAMR, 0,
2108			       rpc_group_list_internals,
2109			       argc, argv);
2110}
2111
2112static NTSTATUS
2113rpc_list_group_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
2114		       const char *domain_name, const DOM_SID *domain_sid,
2115		       POLICY_HND *domain_pol, uint32 rid)
2116{
2117	NTSTATUS result;
2118	POLICY_HND group_pol;
2119	uint32 num_members, *group_rids, *group_attrs;
2120	uint32 num_names;
2121	char **names;
2122	uint32 *name_types;
2123	int i;
2124
2125	fstring sid_str;
2126	sid_to_string(sid_str, domain_sid);
2127
2128	result = cli_samr_open_group(cli, mem_ctx, domain_pol,
2129				     MAXIMUM_ALLOWED_ACCESS,
2130				     rid, &group_pol);
2131
2132	if (!NT_STATUS_IS_OK(result))
2133		return result;
2134
2135	result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
2136					 &num_members, &group_rids,
2137					 &group_attrs);
2138
2139	if (!NT_STATUS_IS_OK(result))
2140		return result;
2141
2142	while (num_members > 0) {
2143		int this_time = 512;
2144
2145		if (num_members < this_time)
2146			this_time = num_members;
2147
2148		result = cli_samr_lookup_rids(cli, mem_ctx, domain_pol,
2149					      this_time, group_rids,
2150					      &num_names, &names, &name_types);
2151
2152		if (!NT_STATUS_IS_OK(result))
2153			return result;
2154
2155		/* We only have users as members, but make the output
2156		   the same as the output of alias members */
2157
2158		for (i = 0; i < this_time; i++) {
2159
2160			if (opt_long_list_entries) {
2161				printf("%s-%d %s\\%s %d\n", sid_str,
2162				       group_rids[i], domain_name, names[i],
2163				       SID_NAME_USER);
2164			} else {
2165				printf("%s\\%s\n", domain_name, names[i]);
2166			}
2167		}
2168
2169		num_members -= this_time;
2170		group_rids += 512;
2171	}
2172
2173	return NT_STATUS_OK;
2174}
2175
2176static NTSTATUS
2177rpc_list_alias_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
2178		       POLICY_HND *domain_pol, uint32 rid)
2179{
2180	NTSTATUS result;
2181	POLICY_HND alias_pol, lsa_pol;
2182	uint32 num_members;
2183	DOM_SID *alias_sids;
2184	char **domains;
2185	char **names;
2186	uint32 *types;
2187	int i;
2188
2189	result = cli_samr_open_alias(cli, mem_ctx, domain_pol,
2190				     MAXIMUM_ALLOWED_ACCESS, rid, &alias_pol);
2191
2192	if (!NT_STATUS_IS_OK(result))
2193		return result;
2194
2195	result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
2196					 &num_members, &alias_sids);
2197
2198	if (!NT_STATUS_IS_OK(result)) {
2199		d_printf("Couldn't list alias members\n");
2200		return result;
2201	}
2202
2203	if (num_members == 0) {
2204		return NT_STATUS_OK;
2205	}
2206
2207	cli_nt_session_close(cli);
2208
2209	if (!cli_nt_session_open(cli, PI_LSARPC)) {
2210		d_printf("Couldn't open LSA pipe\n");
2211		return result;
2212	}
2213
2214	result = cli_lsa_open_policy(cli, mem_ctx, True,
2215				     SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
2216
2217	if (!NT_STATUS_IS_OK(result)) {
2218		d_printf("Couldn't open LSA policy handle\n");
2219		return result;
2220	}
2221
2222	result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol, num_members,
2223				     alias_sids,
2224				     &domains, &names, &types);
2225
2226	if (!NT_STATUS_IS_OK(result) &&
2227	    !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2228		d_printf("Couldn't lookup SIDs\n");
2229		return result;
2230	}
2231
2232	for (i = 0; i < num_members; i++) {
2233		fstring sid_str;
2234		sid_to_string(sid_str, &alias_sids[i]);
2235
2236		if (opt_long_list_entries) {
2237			printf("%s %s\\%s %d\n", sid_str,
2238			       domains[i] ? domains[i] : "*unknown*",
2239			       names[i] ? names[i] : "*unknown*", types[i]);
2240		} else {
2241			if (domains[i])
2242				printf("%s\\%s\n", domains[i], names[i]);
2243			else
2244				printf("%s\n", sid_str);
2245		}
2246	}
2247
2248	return NT_STATUS_OK;
2249}
2250
2251static NTSTATUS
2252rpc_group_members_internals(const DOM_SID *domain_sid,
2253			    const char *domain_name,
2254			    struct cli_state *cli,
2255			    TALLOC_CTX *mem_ctx, int argc, const char **argv)
2256{
2257	NTSTATUS result;
2258	POLICY_HND connect_pol, domain_pol;
2259	uint32 num_rids, *rids, *rid_types;
2260
2261	/* Get sam policy handle */
2262
2263	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2264				  &connect_pol);
2265
2266	if (!NT_STATUS_IS_OK(result))
2267		return result;
2268
2269	/* Get domain policy handle */
2270
2271	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
2272				      MAXIMUM_ALLOWED_ACCESS,
2273				      domain_sid, &domain_pol);
2274
2275	if (!NT_STATUS_IS_OK(result))
2276		return result;
2277
2278	result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
2279				       1, argv, &num_rids, &rids, &rid_types);
2280
2281	if (!NT_STATUS_IS_OK(result)) {
2282
2283		/* Ok, did not find it in the global sam, try with builtin */
2284
2285		DOM_SID sid_Builtin;
2286
2287		cli_samr_close(cli, mem_ctx, &domain_pol);
2288
2289		string_to_sid(&sid_Builtin, "S-1-5-32");
2290
2291		result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
2292					      MAXIMUM_ALLOWED_ACCESS,
2293					      &sid_Builtin, &domain_pol);
2294
2295		if (!NT_STATUS_IS_OK(result)) {
2296			d_printf("Couldn't find group %s\n", argv[0]);
2297			return result;
2298		}
2299
2300		result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
2301					       1, argv, &num_rids,
2302					       &rids, &rid_types);
2303
2304		if (!NT_STATUS_IS_OK(result)) {
2305			d_printf("Couldn't find group %s\n", argv[0]);
2306			return result;
2307		}
2308	}
2309
2310	if (num_rids != 1) {
2311		d_printf("Couldn't find group %s\n", argv[0]);
2312		return result;
2313	}
2314
2315	if (rid_types[0] == SID_NAME_DOM_GRP) {
2316		return rpc_list_group_members(cli, mem_ctx, domain_name,
2317					      domain_sid, &domain_pol,
2318					      rids[0]);
2319	}
2320
2321	if (rid_types[0] == SID_NAME_ALIAS) {
2322		return rpc_list_alias_members(cli, mem_ctx, &domain_pol,
2323					      rids[0]);
2324	}
2325
2326	return NT_STATUS_NO_SUCH_GROUP;
2327}
2328
2329static int rpc_group_members(int argc, const char **argv)
2330{
2331	if (argc != 1) {
2332		return rpc_group_usage(argc, argv);
2333	}
2334
2335	return run_rpc_command(NULL, PI_SAMR, 0,
2336			       rpc_group_members_internals,
2337			       argc, argv);
2338}
2339
2340static NTSTATUS
2341rpc_group_rename_internals(const DOM_SID *domain_sid,
2342			    const char *domain_name,
2343			    struct cli_state *cli,
2344			    TALLOC_CTX *mem_ctx, int argc, const char **argv)
2345{
2346	NTSTATUS result;
2347	POLICY_HND connect_pol, domain_pol, group_pol;
2348	uint32 num_rids, *rids, *rid_types;
2349	GROUP_INFO_CTR ctr;
2350
2351	if (argc != 2) {
2352		d_printf("Usage: 'net rpc group rename group newname'\n");
2353		return NT_STATUS_UNSUCCESSFUL;
2354	}
2355
2356	/* Get sam policy handle */
2357
2358	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
2359				  &connect_pol);
2360
2361	if (!NT_STATUS_IS_OK(result))
2362		return result;
2363
2364	/* Get domain policy handle */
2365
2366	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
2367				      MAXIMUM_ALLOWED_ACCESS,
2368				      domain_sid, &domain_pol);
2369
2370	if (!NT_STATUS_IS_OK(result))
2371		return result;
2372
2373	result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
2374				       1, argv, &num_rids, &rids, &rid_types);
2375
2376	if (num_rids != 1) {
2377		d_printf("Couldn't find group %s\n", argv[0]);
2378		return result;
2379	}
2380
2381	if (rid_types[0] != SID_NAME_DOM_GRP) {
2382		d_printf("Can only rename domain groups\n");
2383		return NT_STATUS_UNSUCCESSFUL;
2384	}
2385
2386	result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
2387				     MAXIMUM_ALLOWED_ACCESS,
2388				     rids[0], &group_pol);
2389
2390	if (!NT_STATUS_IS_OK(result))
2391		return result;
2392
2393	ZERO_STRUCT(ctr);
2394
2395	ctr.switch_value1 = 2;
2396	init_samr_group_info2(&ctr.group.info2, argv[1]);
2397
2398	result = cli_samr_set_groupinfo(cli, mem_ctx, &group_pol, &ctr);
2399
2400	if (!NT_STATUS_IS_OK(result))
2401		return result;
2402
2403	return NT_STATUS_NO_SUCH_GROUP;
2404}
2405
2406static int rpc_group_rename(int argc, const char **argv)
2407{
2408	if (argc != 2) {
2409		return rpc_group_usage(argc, argv);
2410	}
2411
2412	return run_rpc_command(NULL, PI_SAMR, 0,
2413			       rpc_group_rename_internals,
2414			       argc, argv);
2415}
2416
2417/**
2418 * 'net rpc group' entrypoint.
2419 * @param argc  Standard main() style argc
2420 * @param argc  Standard main() style argv.  Initial components are already
2421 *              stripped
2422 **/
2423
2424int net_rpc_group(int argc, const char **argv)
2425{
2426	struct functable func[] = {
2427		{"add", rpc_group_add},
2428		{"delete", rpc_group_delete},
2429		{"addmem", rpc_group_addmem},
2430		{"delmem", rpc_group_delmem},
2431		{"list", rpc_group_list},
2432		{"members", rpc_group_members},
2433		{"rename", rpc_group_rename},
2434		{NULL, NULL}
2435	};
2436
2437	if (argc == 0) {
2438		if (opt_long_list_entries) {
2439		} else {
2440		}
2441		return run_rpc_command(NULL, PI_SAMR, 0,
2442				       rpc_group_list_internals,
2443				       argc, argv);
2444	}
2445
2446	return net_run_function(argc, argv, func, rpc_group_usage);
2447}
2448
2449/****************************************************************************/
2450
2451static int rpc_share_usage(int argc, const char **argv)
2452{
2453	return net_help_share(argc, argv);
2454}
2455
2456/**
2457 * Add a share on a remote RPC server
2458 *
2459 * All parameters are provided by the run_rpc_command function, except for
2460 * argc, argv which are passes through.
2461 *
2462 * @param domain_sid The domain sid acquired from the remote server
2463 * @param cli A cli_state connected to the server.
2464 * @param mem_ctx Talloc context, destoyed on completion of the function.
2465 * @param argc  Standard main() style argc
2466 * @param argv  Standard main() style argv.  Initial components are already
2467 *              stripped
2468 *
2469 * @return Normal NTSTATUS return.
2470 **/
2471static NTSTATUS
2472rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name,
2473			struct cli_state *cli,
2474			TALLOC_CTX *mem_ctx,int argc, const char **argv)
2475{
2476	WERROR result;
2477	char *sharename=talloc_strdup(mem_ctx, argv[0]);
2478	char *path;
2479	uint32 type=0; /* only allow disk shares to be added */
2480	uint32 num_users=0, perms=0;
2481	char *password=NULL; /* don't allow a share password */
2482	uint32 level = 2;
2483
2484	path = strchr(sharename, '=');
2485	if (!path)
2486		return NT_STATUS_UNSUCCESSFUL;
2487	*path++ = '\0';
2488
2489	result = cli_srvsvc_net_share_add(cli, mem_ctx, sharename, type,
2490					  opt_comment, perms, opt_maxusers,
2491					  num_users, path, password,
2492					  level, NULL);
2493	return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
2494}
2495
2496static int rpc_share_add(int argc, const char **argv)
2497{
2498	if ((argc < 1) || !strchr(argv[0], '=')) {
2499		DEBUG(1,("Sharename or path not specified on add\n"));
2500		return rpc_share_usage(argc, argv);
2501	}
2502	return run_rpc_command(NULL, PI_SRVSVC, 0,
2503			       rpc_share_add_internals,
2504			       argc, argv);
2505}
2506
2507/**
2508 * Delete a share on a remote RPC server
2509 *
2510 * All parameters are provided by the run_rpc_command function, except for
2511 * argc, argv which are passes through.
2512 *
2513 * @param domain_sid The domain sid acquired from the remote server
2514 * @param cli A cli_state connected to the server.
2515 * @param mem_ctx Talloc context, destoyed on completion of the function.
2516 * @param argc  Standard main() style argc
2517 * @param argv  Standard main() style argv.  Initial components are already
2518 *              stripped
2519 *
2520 * @return Normal NTSTATUS return.
2521 **/
2522static NTSTATUS
2523rpc_share_del_internals(const DOM_SID *domain_sid, const char *domain_name,
2524			struct cli_state *cli,
2525			TALLOC_CTX *mem_ctx,int argc, const char **argv)
2526{
2527	WERROR result;
2528
2529	result = cli_srvsvc_net_share_del(cli, mem_ctx, argv[0]);
2530	return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
2531}
2532
2533/**
2534 * Delete a share on a remote RPC server
2535 *
2536 * @param domain_sid The domain sid acquired from the remote server
2537 * @param argc  Standard main() style argc
2538 * @param argv  Standard main() style argv.  Initial components are already
2539 *              stripped
2540 *
2541 * @return A shell status integer (0 for success)
2542 **/
2543static int rpc_share_delete(int argc, const char **argv)
2544{
2545	if (argc < 1) {
2546		DEBUG(1,("Sharename not specified on delete\n"));
2547		return rpc_share_usage(argc, argv);
2548	}
2549	return run_rpc_command(NULL, PI_SRVSVC, 0,
2550			       rpc_share_del_internals,
2551			       argc, argv);
2552}
2553
2554/**
2555 * Formatted print of share info
2556 *
2557 * @param info1  pointer to SRV_SHARE_INFO_1 to format
2558 **/
2559
2560static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
2561{
2562	fstring netname = "", remark = "";
2563
2564	rpcstr_pull_unistr2_fstring(netname, &info1->info_1_str.uni_netname);
2565	rpcstr_pull_unistr2_fstring(remark, &info1->info_1_str.uni_remark);
2566
2567	if (opt_long_list_entries) {
2568		d_printf("%-12s %-8.8s %-50s\n",
2569			 netname, share_type[info1->info_1.type], remark);
2570	} else {
2571		d_printf("%s\n", netname);
2572	}
2573
2574}
2575
2576/**
2577 * List shares on a remote RPC server
2578 *
2579 * All parameters are provided by the run_rpc_command function, except for
2580 * argc, argv which are passes through.
2581 *
2582 * @param domain_sid The domain sid acquired from the remote server
2583 * @param cli A cli_state connected to the server.
2584 * @param mem_ctx Talloc context, destoyed on completion of the function.
2585 * @param argc  Standard main() style argc
2586 * @param argv  Standard main() style argv.  Initial components are already
2587 *              stripped
2588 *
2589 * @return Normal NTSTATUS return.
2590 **/
2591
2592static NTSTATUS
2593rpc_share_list_internals(const DOM_SID *domain_sid, const char *domain_name,
2594			 struct cli_state *cli,
2595			 TALLOC_CTX *mem_ctx, int argc, const char **argv)
2596{
2597	SRV_SHARE_INFO_CTR ctr;
2598	WERROR result;
2599	ENUM_HND hnd;
2600	uint32 preferred_len = 0xffffffff, i;
2601
2602	init_enum_hnd(&hnd, 0);
2603
2604	result = cli_srvsvc_net_share_enum(
2605		cli, mem_ctx, 1, &ctr, preferred_len, &hnd);
2606
2607	if (!W_ERROR_IS_OK(result))
2608		goto done;
2609
2610	/* Display results */
2611
2612	if (opt_long_list_entries) {
2613		d_printf(
2614	"\nEnumerating shared resources (exports) on remote server:\n\n"\
2615	"\nShare name   Type     Description\n"\
2616	"----------   ----     -----------\n");
2617	}
2618	for (i = 0; i < ctr.num_entries; i++)
2619		display_share_info_1(&ctr.share.info1[i]);
2620 done:
2621	return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
2622}
2623
2624/**
2625 * Migrate shares from a remote RPC server to the local RPC srever
2626 *
2627 * All parameters are provided by the run_rpc_command function, except for
2628 * argc, argv which are passes through.
2629 *
2630 * @param domain_sid The domain sid acquired from the remote server
2631 * @param cli A cli_state connected to the server.
2632 * @param mem_ctx Talloc context, destoyed on completion of the function.
2633 * @param argc  Standard main() style argc
2634 * @param argv  Standard main() style argv.  Initial components are already
2635 *              stripped
2636 *
2637 * @return Normal NTSTATUS return.
2638 **/
2639static NTSTATUS
2640rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain_name,
2641				   struct cli_state *cli, TALLOC_CTX *mem_ctx,
2642				   int argc, const char **argv)
2643{
2644	WERROR result;
2645	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2646	SRV_SHARE_INFO_CTR ctr_src;
2647	ENUM_HND hnd;
2648	uint32 type = 0; /* only allow disk shares to be added */
2649	uint32 num_uses = 0, perms = 0, max_uses = 0;
2650	char *password = NULL; /* don't allow a share password */
2651	uint32 preferred_len = 0xffffffff, i;
2652	BOOL got_dst_srvsvc_pipe = False;
2653	struct cli_state *cli_dst = NULL;
2654	uint32 level = 502; /* includes secdesc */
2655	SEC_DESC *share_sd = NULL;
2656
2657	init_enum_hnd(&hnd, 0);
2658
2659	result = cli_srvsvc_net_share_enum(
2660			cli, mem_ctx, level, &ctr_src, preferred_len, &hnd);
2661	if (!W_ERROR_IS_OK(result))
2662		goto done;
2663
2664	/* connect local PI_SRVSVC */
2665        nt_status = connect_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe);
2666        if (!NT_STATUS_IS_OK(nt_status))
2667                return nt_status;
2668
2669
2670	for (i = 0; i < ctr_src.num_entries; i++) {
2671
2672		fstring netname = "", remark = "", path = "";
2673		/* reset error-code */
2674		nt_status = NT_STATUS_UNSUCCESSFUL;
2675
2676		rpcstr_pull_unistr2_fstring(
2677			netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
2678		rpcstr_pull_unistr2_fstring(
2679			remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
2680		rpcstr_pull_unistr2_fstring(
2681			path, &ctr_src.share.info502[i].info_502_str.uni_path);
2682		num_uses 	= ctr_src.share.info502[i].info_502.num_uses;
2683		max_uses 	= ctr_src.share.info502[i].info_502.max_uses;
2684		perms		= ctr_src.share.info502[i].info_502.perms;
2685
2686
2687		if (opt_acls)
2688			share_sd = dup_sec_desc(
2689				mem_ctx, ctr_src.share.info502[i].info_502_str.sd);
2690
2691		/* since we do not have NetShareGetInfo implemented in samba3 we
2692		   only can skip inside the enum-ctr_src */
2693		if (argc == 1) {
2694			char *one_share = talloc_strdup(mem_ctx, argv[0]);
2695			if (!strequal(netname, one_share))
2696				continue;
2697		}
2698
2699		/* skip builtin shares */
2700		/* FIXME: should print$ be added too ? */
2701		if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
2702		    strequal(netname,"global"))
2703			continue;
2704
2705		/* only work with file-shares */
2706		if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
2707			d_printf("skipping   [%s]: not a file share.\n", netname);
2708			continue;
2709		}
2710
2711		if (!cli_tdis(cli))
2712			goto done;
2713
2714
2715		/* finallly add the share on the dst server
2716		   please note that samba currently does not allow to
2717		   add a share without existing directory */
2718
2719		printf("migrating: [%s], path: %s, comment: %s, %s share-ACLs\n",
2720			netname, path, remark, opt_acls ? "including" : "without" );
2721
2722		if (opt_verbose && opt_acls)
2723			display_sec_desc(share_sd);
2724
2725		result = cli_srvsvc_net_share_add(cli_dst, mem_ctx, netname, type,
2726						  remark, perms, max_uses,
2727						  num_uses, path, password,
2728						  level, share_sd);
2729
2730                if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
2731			printf("           [%s] does already exist\n", netname);
2732			continue;
2733		}
2734
2735		if (!W_ERROR_IS_OK(result)) {
2736			printf("cannot add share: %s\n", dos_errstr(result));
2737			goto done;
2738		}
2739
2740	}
2741
2742	nt_status = NT_STATUS_OK;
2743
2744done:
2745	if (got_dst_srvsvc_pipe) {
2746		cli_nt_session_close(cli_dst);
2747		cli_shutdown(cli_dst);
2748	}
2749
2750	return nt_status;
2751
2752}
2753
2754/**
2755 * Migrate shares from a rpc-server to another
2756 *
2757 * @param argc  Standard main() style argc
2758 * @param argv  Standard main() style argv.  Initial components are already
2759 *              stripped
2760 *
2761 * @return A shell status integer (0 for success)
2762 **/
2763static int rpc_share_migrate_shares(int argc, const char **argv)
2764{
2765
2766	if (!opt_host) {
2767		printf("no server to migrate\n");
2768		return -1;
2769	}
2770
2771	return run_rpc_command(NULL, PI_SRVSVC, 0,
2772			       rpc_share_migrate_shares_internals,
2773			       argc, argv);
2774}
2775
2776typedef struct copy_clistate {
2777	TALLOC_CTX *mem_ctx;
2778	struct cli_state *cli_share_src;
2779	struct cli_state *cli_share_dst;
2780	const char *cwd;
2781} copy_clistate;
2782
2783
2784/**
2785 * Copy a file/dir
2786 *
2787 * @param f	file_info
2788 * @param mask	current search mask
2789 * @param state	arg-pointer
2790 *
2791 **/
2792static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state)
2793{
2794	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2795	struct copy_clistate *local_state = (struct copy_clistate *)state;
2796	fstring filename, new_mask, dir;
2797
2798	if (strequal(f->name, ".") || strequal(f->name, ".."))
2799		return;
2800
2801	DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
2802
2803	/* DIRECTORY */
2804	if (f->mode & aDIR) {
2805
2806		DEBUG(3,("got dir: %s\n", f->name));
2807
2808		fstrcpy(dir, local_state->cwd);
2809		fstrcat(dir, "\\");
2810		fstrcat(dir, f->name);
2811
2812		/* create that directory */
2813		nt_status = net_copy_file(local_state->mem_ctx,
2814					  local_state->cli_share_src,
2815					  local_state->cli_share_dst,
2816					  dir, dir,
2817					  opt_acls? True : False,
2818					  opt_attrs? True : False,
2819					  opt_timestamps? True : False,
2820					  False);
2821
2822		if (!NT_STATUS_IS_OK(nt_status))
2823			printf("could not copy dir %s: %s\n",
2824				dir, nt_errstr(nt_status));
2825
2826		/* search below that directory */
2827		fstrcpy(new_mask, dir);
2828		fstrcat(new_mask, "\\*");
2829
2830		if (!sync_files(local_state->mem_ctx,
2831				local_state->cli_share_src,
2832				local_state->cli_share_dst,
2833				new_mask, dir))
2834
2835			printf("could not sync files\n");
2836
2837		return;
2838	}
2839
2840
2841	/* FILE */
2842	fstrcpy(filename, local_state->cwd);
2843	fstrcat(filename, "\\");
2844	fstrcat(filename, f->name);
2845
2846	DEBUG(3,("got file: %s\n", filename));
2847
2848	nt_status = net_copy_file(local_state->mem_ctx,
2849				  local_state->cli_share_src,
2850				  local_state->cli_share_dst,
2851				  filename, filename,
2852				  opt_acls? True : False,
2853				  opt_attrs? True : False,
2854				  opt_timestamps? True: False,
2855				  True);
2856
2857	if (!NT_STATUS_IS_OK(nt_status))
2858		printf("could not copy file %s: %s\n",
2859			filename, nt_errstr(nt_status));
2860
2861}
2862
2863/**
2864 * sync files, can be called recursivly to list files
2865 * and then call copy_fn for each file
2866 *
2867 * @param mem_ctx	TALLOC_CTX
2868 * @param cli_share_src	a connected share on the originating server
2869 * @param cli_share_dst	a connected share on the destination server
2870 * @param mask		the current search mask
2871 * @param cwd		the current path
2872 *
2873 * @return 		Boolean result
2874 **/
2875BOOL sync_files(TALLOC_CTX *mem_ctx,
2876		struct cli_state *cli_share_src,
2877		struct cli_state *cli_share_dst,
2878		pstring mask, fstring cwd)
2879
2880{
2881
2882	uint16 attribute = aSYSTEM | aHIDDEN | aDIR;
2883	struct copy_clistate clistate;
2884
2885	clistate.mem_ctx 	= mem_ctx;
2886	clistate.cli_share_src 	= cli_share_src;
2887	clistate.cli_share_dst 	= cli_share_dst;
2888	clistate.cwd 		= cwd;
2889
2890	DEBUG(3,("calling cli_list with mask: %s\n", mask));
2891
2892	if (cli_list(cli_share_src, mask, attribute, copy_fn, &clistate) == -1) {
2893		d_printf("listing %s failed with error: %s\n",
2894			mask, cli_errstr(cli_share_src));
2895		return False;
2896	}
2897
2898	return True;
2899}
2900
2901
2902/**
2903 * Sync all files inside a remote share to another share (over smb)
2904 *
2905 * All parameters are provided by the run_rpc_command function, except for
2906 * argc, argv which are passes through.
2907 *
2908 * @param domain_sid The domain sid acquired from the remote server
2909 * @param cli A cli_state connected to the server.
2910 * @param mem_ctx Talloc context, destoyed on completion of the function.
2911 * @param argc  Standard main() style argc
2912 * @param argv  Standard main() style argv.  Initial components are already
2913 *              stripped
2914 *
2915 * @return Normal NTSTATUS return.
2916 **/
2917static NTSTATUS
2918rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_name,
2919				  struct cli_state *cli, TALLOC_CTX *mem_ctx,
2920				  int argc, const char **argv)
2921{
2922	WERROR result;
2923	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2924	SRV_SHARE_INFO_CTR ctr_src;
2925	ENUM_HND hnd;
2926	uint32 preferred_len = 0xffffffff, i;
2927	uint32 level = 2;
2928	struct cli_state *cli_share_src = NULL;
2929	struct cli_state *cli_share_dst = NULL;
2930	BOOL got_src_share = False;
2931	BOOL got_dst_share = False;
2932	pstring mask;
2933	char *dst = NULL;
2934
2935	dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1");
2936
2937	init_enum_hnd(&hnd, 0);
2938
2939	result = cli_srvsvc_net_share_enum(
2940			cli, mem_ctx, level, &ctr_src, preferred_len, &hnd);
2941
2942	if (!W_ERROR_IS_OK(result))
2943		goto done;
2944
2945	for (i = 0; i < ctr_src.num_entries; i++) {
2946
2947		fstring netname = "", remark = "", path = "";
2948
2949		rpcstr_pull_unistr2_fstring(
2950			netname, &ctr_src.share.info2[i].info_2_str.uni_netname);
2951		rpcstr_pull_unistr2_fstring(
2952			remark, &ctr_src.share.info2[i].info_2_str.uni_remark);
2953		rpcstr_pull_unistr2_fstring(
2954			path, &ctr_src.share.info2[i].info_2_str.uni_path);
2955
2956		/* since we do not have NetShareGetInfo implemented in samba3 we
2957		   only can skip inside the enum-ctr_src */
2958		if (argc == 1) {
2959			char *one_share = talloc_strdup(mem_ctx, argv[0]);
2960			if (!strequal(netname, one_share))
2961				continue;
2962		}
2963
2964		/* skip builtin and hidden shares
2965		   In particular, one might not want to mirror whole discs :) */
2966		if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$"))
2967			continue;
2968
2969		if (strequal(netname, "print$") || netname[1] == '$') {
2970			d_printf("skipping   [%s]: builtin/hidden share\n", netname);
2971			continue;
2972		}
2973
2974		if (opt_exclude && in_list(netname, (char *)opt_exclude, False)) {
2975			printf("excluding  [%s]\n", netname);
2976			continue;
2977		}
2978
2979		/* only work with file-shares */
2980		if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
2981			d_printf("skipping   [%s]: not a file share.\n", netname);
2982			continue;
2983		}
2984
2985		if (!cli_tdis(cli))
2986			return NT_STATUS_UNSUCCESSFUL;
2987
2988		printf("syncing    [%s] files and directories %s ACLs, %s DOS Attributes %s\n",
2989			netname,
2990			opt_acls ? "including" : "without",
2991			opt_attrs ? "including" : "without",
2992			opt_timestamps ? "(preserving timestamps)" : "");
2993
2994
2995	        /* open share source */
2996		nt_status = connect_to_service(&cli_share_src, &cli->dest_ip,
2997					       cli->desthost, netname, "A:");
2998		if (!NT_STATUS_IS_OK(nt_status))
2999			goto done;
3000
3001		got_src_share = True;
3002
3003
3004	        /* open share destination */
3005		nt_status = connect_to_service(&cli_share_dst, NULL,
3006					       dst, netname, "A:");
3007		if (!NT_STATUS_IS_OK(nt_status))
3008			goto done;
3009
3010		got_dst_share = True;
3011
3012
3013		/* now call the filesync */
3014		pstrcpy(mask, "\\*");
3015
3016		if (!sync_files(mem_ctx, cli_share_src, cli_share_dst, mask, NULL)) {
3017			d_printf("could not sync files for share: %s\n", netname);
3018			nt_status = NT_STATUS_UNSUCCESSFUL;
3019			goto done;
3020		}
3021
3022	}
3023
3024	nt_status = NT_STATUS_OK;
3025
3026done:
3027
3028	if (got_src_share)
3029		cli_shutdown(cli_share_src);
3030
3031	if (got_dst_share)
3032		cli_shutdown(cli_share_dst);
3033
3034	return nt_status;
3035
3036}
3037
3038static int rpc_share_migrate_files(int argc, const char **argv)
3039{
3040
3041	if (!opt_host) {
3042		printf("no server to migrate\n");
3043		return -1;
3044	}
3045
3046	return run_rpc_command(NULL, PI_SRVSVC, 0,
3047			       rpc_share_migrate_files_internals,
3048			       argc, argv);
3049}
3050
3051/**
3052 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3053 * from one server to another
3054 *
3055 * @param argc  Standard main() style argc
3056 * @param argv  Standard main() style argv.  Initial components are already
3057 *              stripped
3058 *
3059 * @return A shell status integer (0 for success)
3060 *
3061 **/
3062static int rpc_share_migrate_all(int argc, const char **argv)
3063{
3064	int ret;
3065
3066	if (!opt_host) {
3067		printf("no server to migrate\n");
3068		return -1;
3069	}
3070
3071	ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
3072	if (ret)
3073		return ret;
3074#if 0
3075	ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_security_internals, argc, argv);
3076	if (ret)
3077		return ret;
3078#endif
3079	return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
3080}
3081
3082
3083/**
3084 * 'net rpc share migrate' entrypoint.
3085 * @param argc  Standard main() style argc
3086 * @param argv  Standard main() style argv.  Initial components are already
3087 *              stripped
3088 **/
3089static int rpc_share_migrate(int argc, const char **argv)
3090{
3091
3092	struct functable func[] = {
3093		{"all", 	rpc_share_migrate_all},
3094		{"files", 	rpc_share_migrate_files},
3095		{"help",	rpc_share_usage},
3096/*		{"security", 	rpc_share_migrate_security},*/
3097		{"shares", 	rpc_share_migrate_shares},
3098		{NULL, NULL}
3099	};
3100
3101	return net_run_function(argc, argv, func, rpc_share_usage);
3102}
3103
3104struct full_alias {
3105	DOM_SID sid;
3106	int num_members;
3107	DOM_SID *members;
3108};
3109
3110static int num_server_aliases;
3111static struct full_alias *server_aliases;
3112
3113/*
3114 * Add an alias to the static list.
3115 */
3116static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
3117{
3118	if (server_aliases == NULL)
3119		server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
3120
3121	server_aliases[num_server_aliases] = *alias;
3122	num_server_aliases += 1;
3123}
3124
3125/*
3126 * For a specific domain on the server, fetch all the aliases
3127 * and their members. Add all of them to the server_aliases.
3128 */
3129static NTSTATUS
3130rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx,
3131			 POLICY_HND *connect_pol,
3132			 const DOM_SID *domain_sid)
3133{
3134	uint32 start_idx, max_entries, num_entries, i;
3135	struct acct_info *groups;
3136	NTSTATUS result;
3137	POLICY_HND domain_pol;
3138
3139	/* Get domain policy handle */
3140
3141	result = cli_samr_open_domain(cli, mem_ctx, connect_pol,
3142				      MAXIMUM_ALLOWED_ACCESS,
3143				      domain_sid, &domain_pol);
3144	if (!NT_STATUS_IS_OK(result))
3145		return result;
3146
3147	start_idx = 0;
3148	max_entries = 250;
3149
3150	do {
3151		result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
3152						  &start_idx, max_entries,
3153						  &groups, &num_entries);
3154
3155		for (i = 0; i < num_entries; i++) {
3156
3157			POLICY_HND alias_pol;
3158			struct full_alias alias;
3159			DOM_SID *members;
3160			int j;
3161
3162			result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
3163						     MAXIMUM_ALLOWED_ACCESS,
3164						     groups[i].rid,
3165						     &alias_pol);
3166			if (!NT_STATUS_IS_OK(result))
3167				goto done;
3168
3169			result = cli_samr_query_aliasmem(cli, mem_ctx,
3170							 &alias_pol,
3171							 &alias.num_members,
3172							 &members);
3173			if (!NT_STATUS_IS_OK(result))
3174				goto done;
3175
3176			result = cli_samr_close(cli, mem_ctx, &alias_pol);
3177			if (!NT_STATUS_IS_OK(result))
3178				goto done;
3179
3180			alias.members = NULL;
3181
3182			if (alias.num_members > 0) {
3183				alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
3184
3185				for (j = 0; j < alias.num_members; j++)
3186					sid_copy(&alias.members[j],
3187						 &members[j]);
3188			}
3189
3190			sid_copy(&alias.sid, domain_sid);
3191			sid_append_rid(&alias.sid, groups[i].rid);
3192
3193			push_alias(mem_ctx, &alias);
3194		}
3195	} while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3196
3197	result = NT_STATUS_OK;
3198
3199 done:
3200	cli_samr_close(cli, mem_ctx, &domain_pol);
3201
3202	return result;
3203}
3204
3205/*
3206 * Dump server_aliases as names for debugging purposes.
3207 */
3208static NTSTATUS
3209rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name,
3210		   struct cli_state *cli, TALLOC_CTX *mem_ctx,
3211		   int argc, const char **argv)
3212{
3213	int i;
3214	NTSTATUS result;
3215	POLICY_HND lsa_pol;
3216
3217	result = cli_lsa_open_policy(cli, mem_ctx, True,
3218				     SEC_RIGHTS_MAXIMUM_ALLOWED,
3219				     &lsa_pol);
3220	if (!NT_STATUS_IS_OK(result))
3221		return result;
3222
3223	for (i=0; i<num_server_aliases; i++) {
3224		char **names;
3225		char **domains;
3226		uint32 *types;
3227		int j;
3228
3229		struct full_alias *alias = &server_aliases[i];
3230
3231		result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol, 1,
3232					     &alias->sid,
3233					     &domains, &names, &types);
3234		if (!NT_STATUS_IS_OK(result))
3235			continue;
3236
3237		DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
3238
3239		if (alias->num_members == 0) {
3240			DEBUG(1, ("\n"));
3241			continue;
3242		}
3243
3244		result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol,
3245					     alias->num_members,
3246					     alias->members,
3247					     &domains, &names, &types);
3248
3249		if (!NT_STATUS_IS_OK(result) &&
3250		    !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
3251			continue;
3252
3253		for (j=0; j<alias->num_members; j++)
3254			DEBUG(1, ("%s\\%s (%d); ",
3255				  domains[j] ? domains[j] : "*unknown*",
3256				  names[j] ? names[j] : "*unknown*",types[j]));
3257		DEBUG(1, ("\n"));
3258	}
3259
3260	cli_lsa_close(cli, mem_ctx, &lsa_pol);
3261
3262	return NT_STATUS_OK;
3263}
3264
3265/*
3266 * Fetch a list of all server aliases and their members into
3267 * server_aliases.
3268 */
3269static NTSTATUS
3270rpc_aliaslist_internals(const DOM_SID *domain_sid, const char *domain_name,
3271			struct cli_state *cli, TALLOC_CTX *mem_ctx,
3272			int argc, const char **argv)
3273{
3274	NTSTATUS result;
3275	POLICY_HND connect_pol;
3276	DOM_SID global_sid_Builtin;
3277
3278	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
3279				  &connect_pol);
3280
3281	if (!NT_STATUS_IS_OK(result))
3282		goto done;
3283
3284	string_to_sid(&global_sid_Builtin, "S-1-5-32");
3285
3286	result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol,
3287					  &global_sid_Builtin);
3288
3289	if (!NT_STATUS_IS_OK(result))
3290		goto done;
3291
3292	result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol,
3293					  domain_sid);
3294
3295	cli_samr_close(cli, mem_ctx, &connect_pol);
3296 done:
3297	return result;
3298}
3299
3300static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
3301{
3302	DOM_SID global_sid_World;
3303	DOM_SID global_sid_Network;
3304	DOM_SID global_sid_Authenticated_Users;
3305
3306	string_to_sid(&global_sid_World, "S-1-1-0");
3307	string_to_sid(&global_sid_Network, "S-1-5-2");
3308	string_to_sid(&global_sid_Authenticated_Users, "S-1-5-11");
3309
3310	token->num_sids = 4;
3311
3312	token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4);
3313
3314	token->user_sids[0] = *user_sid;
3315	sid_copy(&token->user_sids[1], &global_sid_World);
3316	sid_copy(&token->user_sids[2], &global_sid_Network);
3317	sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
3318}
3319
3320static void free_user_token(NT_USER_TOKEN *token)
3321{
3322	SAFE_FREE(token->user_sids);
3323}
3324
3325static BOOL is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
3326{
3327	int i;
3328
3329	for (i=0; i<token->num_sids; i++) {
3330		if (sid_compare(sid, &token->user_sids[i]) == 0)
3331			return True;
3332	}
3333	return False;
3334}
3335
3336static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
3337{
3338	if (is_sid_in_token(token, sid))
3339		return;
3340
3341	token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
3342
3343	sid_copy(&token->user_sids[token->num_sids], sid);
3344
3345	token->num_sids += 1;
3346}
3347
3348struct user_token {
3349	fstring name;
3350	NT_USER_TOKEN token;
3351};
3352
3353static void dump_user_token(struct user_token *token)
3354{
3355	int i;
3356
3357	d_printf("%s\n", token->name);
3358
3359	for (i=0; i<token->token.num_sids; i++) {
3360		d_printf(" %s\n", sid_string_static(&token->token.user_sids[i]));
3361	}
3362}
3363
3364static BOOL is_alias_member(DOM_SID *sid, struct full_alias *alias)
3365{
3366	int i;
3367
3368	for (i=0; i<alias->num_members; i++) {
3369		if (sid_compare(sid, &alias->members[i]) == 0)
3370			return True;
3371	}
3372
3373	return False;
3374}
3375
3376static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
3377{
3378	int i;
3379
3380	for (i=0; i<num_server_aliases; i++) {
3381		if (is_alias_member(&sid, &server_aliases[i]))
3382			add_sid_to_token(token, &server_aliases[i].sid);
3383	}
3384}
3385
3386/*
3387 * We got a user token with all the SIDs we can know about without asking the
3388 * server directly. These are the user and domain group sids. All of these can
3389 * be members of aliases. So scan the list of aliases for each of the SIDs and
3390 * add them to the token.
3391 */
3392
3393static void collect_alias_memberships(NT_USER_TOKEN *token)
3394{
3395	int num_global_sids = token->num_sids;
3396	int i;
3397
3398	for (i=0; i<num_global_sids; i++) {
3399		collect_sid_memberships(token, token->user_sids[i]);
3400	}
3401}
3402
3403static BOOL get_user_sids(const char *domain, const char *user,
3404			  NT_USER_TOKEN *token)
3405{
3406	struct winbindd_request request;
3407	struct winbindd_response response;
3408	fstring full_name;
3409	NSS_STATUS result;
3410
3411	DOM_SID user_sid;
3412
3413	int i;
3414
3415	fstr_sprintf(full_name, "%s%c%s",
3416		     domain, *lp_winbind_separator(), user);
3417
3418	/* First let's find out the user sid */
3419
3420	ZERO_STRUCT(request);
3421	ZERO_STRUCT(response);
3422
3423	fstrcpy(request.data.name.dom_name, domain);
3424	fstrcpy(request.data.name.name, user);
3425
3426	result = winbindd_request(WINBINDD_LOOKUPNAME, &request, &response);
3427
3428	if (result != NSS_STATUS_SUCCESS) {
3429		DEBUG(1, ("winbind could not find %s\n", full_name));
3430		return False;
3431	}
3432
3433	if (response.data.sid.type != SID_NAME_USER) {
3434		DEBUG(1, ("%s is not a user\n", full_name));
3435		return False;
3436	}
3437
3438	string_to_sid(&user_sid, response.data.sid.sid);
3439
3440	init_user_token(token, &user_sid);
3441
3442	/* And now the groups winbind knows about */
3443
3444	ZERO_STRUCT(response);
3445
3446	fstrcpy(request.data.username, full_name);
3447
3448	result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
3449
3450	if (result != NSS_STATUS_SUCCESS) {
3451		DEBUG(1, ("winbind could not get groups of %s\n", full_name));
3452		return False;
3453	}
3454
3455	for (i = 0; i < response.data.num_entries; i++) {
3456		gid_t gid = ((gid_t *)response.extra_data)[i];
3457		DOM_SID sid;
3458
3459		struct winbindd_request sidrequest;
3460		struct winbindd_response sidresponse;
3461
3462		ZERO_STRUCT(sidrequest);
3463		ZERO_STRUCT(sidresponse);
3464
3465		sidrequest.data.gid = gid;
3466
3467		result = winbindd_request(WINBINDD_GID_TO_SID,
3468					  &sidrequest, &sidresponse);
3469
3470		if (result != NSS_STATUS_SUCCESS) {
3471			DEBUG(1, ("winbind could not find SID of gid %d\n",
3472				  gid));
3473			return False;
3474		}
3475
3476		DEBUG(3, (" %s\n", sidresponse.data.sid.sid));
3477
3478		string_to_sid(&sid, sidresponse.data.sid.sid);
3479		add_sid_to_token(token, &sid);
3480	}
3481
3482	SAFE_FREE(response.extra_data);
3483
3484	return True;
3485}
3486
3487/**
3488 * Get a list of all user tokens we want to look at
3489 **/
3490static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens)
3491{
3492	struct winbindd_request request;
3493	struct winbindd_response response;
3494	const char *extra_data;
3495	fstring name;
3496	int i;
3497	struct user_token *result;
3498
3499	/* Send request to winbind daemon */
3500
3501	ZERO_STRUCT(request);
3502	ZERO_STRUCT(response);
3503
3504	if (winbindd_request(WINBINDD_LIST_USERS, &request, &response) !=
3505	    NSS_STATUS_SUCCESS)
3506		return False;
3507
3508	/* Look through extra data */
3509
3510	if (!response.extra_data)
3511		return False;
3512
3513	extra_data = (const char *)response.extra_data;
3514	*num_tokens = 0;
3515
3516	while(next_token(&extra_data, name, ",", sizeof(fstring))) {
3517		*num_tokens += 1;
3518	}
3519
3520	result = SMB_MALLOC_ARRAY(struct user_token, *num_tokens);
3521
3522	if (result == NULL) {
3523		DEBUG(1, ("Could not malloc sid array\n"));
3524		return False;
3525	}
3526
3527	extra_data = (const char *)response.extra_data;
3528	i=0;
3529
3530	while(next_token(&extra_data, name, ",", sizeof(fstring))) {
3531
3532		fstring domain, user;
3533		char *p;
3534
3535		fstrcpy(result[i].name, name);
3536
3537		p = strchr(name, *lp_winbind_separator());
3538
3539		DEBUG(3, ("%s\n", name));
3540
3541		if (p == NULL)
3542			continue;
3543
3544		*p++ = '\0';
3545
3546		fstrcpy(domain, name);
3547		strupper_m(domain);
3548		fstrcpy(user, p);
3549
3550		get_user_sids(domain, user, &(result[i].token));
3551		i+=1;
3552	}
3553
3554	SAFE_FREE(response.extra_data);
3555
3556	*user_tokens = result;
3557
3558	return True;
3559}
3560
3561static BOOL get_user_tokens_from_file(FILE *f,
3562				      int *num_tokens,
3563				      struct user_token **tokens)
3564{
3565	struct user_token *token = NULL;
3566
3567	while (!feof(f)) {
3568		fstring line;
3569
3570		if (fgets(line, sizeof(line)-1, f) == NULL) {
3571			return True;
3572		}
3573
3574		if (line[strlen(line)-1] == '\n')
3575			line[strlen(line)-1] = '\0';
3576
3577		if (line[0] == ' ') {
3578			/* We have a SID */
3579
3580			DOM_SID sid;
3581			string_to_sid(&sid, &line[1]);
3582
3583			if (token == NULL) {
3584				DEBUG(0, ("File does not begin with username"));
3585				return False;
3586			}
3587
3588			add_sid_to_token(&token->token, &sid);
3589			continue;
3590		}
3591
3592		/* And a new user... */
3593
3594		*num_tokens += 1;
3595		*tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
3596		if (*tokens == NULL) {
3597			DEBUG(0, ("Could not realloc tokens\n"));
3598			return False;
3599		}
3600
3601		token = &((*tokens)[*num_tokens-1]);
3602
3603		fstrcpy(token->name, line);
3604		token->token.num_sids = 0;
3605		token->token.user_sids = NULL;
3606		continue;
3607	}
3608
3609	return False;
3610}
3611
3612
3613/*
3614 * Show the list of all users that have access to a share
3615 */
3616
3617static void show_userlist(struct cli_state *cli,
3618			  TALLOC_CTX *mem_ctx, const char *netname,
3619			  int num_tokens, struct user_token *tokens)
3620{
3621	int fnum;
3622	SEC_DESC *share_sd = NULL;
3623	SEC_DESC *root_sd = NULL;
3624	int i;
3625	SRV_SHARE_INFO info;
3626	WERROR result;
3627	uint16 cnum;
3628
3629	result = cli_srvsvc_net_share_get_info(cli, mem_ctx, netname,
3630					       502, &info);
3631
3632	if (!W_ERROR_IS_OK(result)) {
3633		DEBUG(1, ("Coult not query secdesc for share %s\n",
3634			  netname));
3635		return;
3636	}
3637
3638	share_sd = info.share.info502.info_502_str.sd;
3639	if (share_sd == NULL) {
3640		DEBUG(1, ("Got no secdesc for share %s\n",
3641			  netname));
3642	}
3643
3644	cnum = cli->cnum;
3645
3646	if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
3647		return;
3648	}
3649
3650	fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
3651
3652	if (fnum != -1) {
3653		root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
3654	}
3655
3656	for (i=0; i<num_tokens; i++) {
3657		uint32 acc_granted;
3658		NTSTATUS status;
3659
3660		if (share_sd != NULL) {
3661			if (!se_access_check(share_sd, &tokens[i].token,
3662					     1, &acc_granted, &status)) {
3663				DEBUG(1, ("Could not check share_sd for "
3664					  "user %s\n",
3665					  tokens[i].name));
3666				continue;
3667			}
3668
3669			if (!NT_STATUS_IS_OK(status))
3670				continue;
3671		}
3672
3673		if (root_sd == NULL) {
3674			d_printf(" %s\n", tokens[i].name);
3675			continue;
3676		}
3677
3678		if (!se_access_check(root_sd, &tokens[i].token,
3679				     1, &acc_granted, &status)) {
3680			DEBUG(1, ("Could not check root_sd for user %s\n",
3681				  tokens[i].name));
3682			continue;
3683		}
3684
3685		if (!NT_STATUS_IS_OK(status))
3686			continue;
3687
3688		d_printf(" %s\n", tokens[i].name);
3689	}
3690
3691	if (fnum != -1)
3692		cli_close(cli, fnum);
3693	cli_tdis(cli);
3694	cli->cnum = cnum;
3695
3696	return;
3697}
3698
3699struct share_list {
3700	int num_shares;
3701	char **shares;
3702};
3703
3704static void collect_share(const char *name, uint32 m,
3705			  const char *comment, void *state)
3706{
3707	struct share_list *share_list = (struct share_list *)state;
3708
3709	if (m != STYPE_DISKTREE)
3710		return;
3711
3712	share_list->num_shares += 1;
3713	share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
3714	share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
3715}
3716
3717static void rpc_share_userlist_usage(void)
3718{
3719	return;
3720}
3721
3722/**
3723 * List shares on a remote RPC server, including the security descriptors
3724 *
3725 * All parameters are provided by the run_rpc_command function, except for
3726 * argc, argv which are passes through.
3727 *
3728 * @param domain_sid The domain sid acquired from the remote server
3729 * @param cli A cli_state connected to the server.
3730 * @param mem_ctx Talloc context, destoyed on completion of the function.
3731 * @param argc  Standard main() style argc
3732 * @param argv  Standard main() style argv.  Initial components are already
3733 *              stripped
3734 *
3735 * @return Normal NTSTATUS return.
3736 **/
3737
3738static NTSTATUS
3739rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
3740				 const char *domain_name,
3741				 struct cli_state *cli,
3742				 TALLOC_CTX *mem_ctx,
3743				 int argc, const char **argv)
3744{
3745	int ret;
3746	BOOL r;
3747	ENUM_HND hnd;
3748	uint32 i;
3749	FILE *f;
3750
3751	struct user_token *tokens = NULL;
3752	int num_tokens = 0;
3753
3754	struct share_list share_list;
3755
3756	if (argc > 1) {
3757		rpc_share_userlist_usage();
3758		return NT_STATUS_UNSUCCESSFUL;
3759	}
3760
3761	if (argc == 0) {
3762		f = stdin;
3763	} else {
3764		f = fopen(argv[0], "r");
3765	}
3766
3767	if (f == NULL) {
3768		DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
3769		return NT_STATUS_UNSUCCESSFUL;
3770	}
3771
3772	r = get_user_tokens_from_file(f, &num_tokens, &tokens);
3773
3774	if (f != stdin)
3775		fclose(f);
3776
3777	if (!r) {
3778		DEBUG(0, ("Could not read users from file\n"));
3779		return NT_STATUS_UNSUCCESSFUL;
3780	}
3781
3782	for (i=0; i<num_tokens; i++)
3783		collect_alias_memberships(&tokens[i].token);
3784
3785	init_enum_hnd(&hnd, 0);
3786
3787	share_list.num_shares = 0;
3788	share_list.shares = NULL;
3789
3790	ret = cli_RNetShareEnum(cli, collect_share, &share_list);
3791
3792	if (ret == -1) {
3793		DEBUG(0, ("Error returning browse list: %s\n",
3794			  cli_errstr(cli)));
3795		goto done;
3796	}
3797
3798	for (i = 0; i < share_list.num_shares; i++) {
3799		char *netname = share_list.shares[i];
3800
3801		if (netname[strlen(netname)-1] == '$')
3802			continue;
3803
3804		d_printf("%s\n", netname);
3805
3806		show_userlist(cli, mem_ctx, netname,
3807			      num_tokens, tokens);
3808	}
3809 done:
3810	for (i=0; i<num_tokens; i++) {
3811		free_user_token(&tokens[i].token);
3812	}
3813	SAFE_FREE(tokens);
3814	SAFE_FREE(share_list.shares);
3815
3816	return NT_STATUS_OK;
3817}
3818
3819static int
3820rpc_share_allowedusers(int argc, const char **argv)
3821{
3822	int result;
3823
3824	result = run_rpc_command(NULL, PI_SAMR, 0,
3825				 rpc_aliaslist_internals,
3826				 argc, argv);
3827	if (result != 0)
3828		return result;
3829
3830	result = run_rpc_command(NULL, PI_LSARPC, 0,
3831				 rpc_aliaslist_dump,
3832				 argc, argv);
3833	if (result != 0)
3834		return result;
3835
3836	return run_rpc_command(NULL, PI_SRVSVC, 0,
3837			       rpc_share_allowedusers_internals,
3838			       argc, argv);
3839}
3840
3841int net_usersidlist(int argc, const char **argv)
3842{
3843	int num_tokens = 0;
3844	struct user_token *tokens = NULL;
3845	int i;
3846
3847	if (argc != 0) {
3848		net_usersidlist_usage(argc, argv);
3849		return 0;
3850	}
3851
3852	if (!get_user_tokens(&num_tokens, &tokens)) {
3853		DEBUG(0, ("Could not get the user/sid list\n"));
3854		return 0;
3855	}
3856
3857	for (i=0; i<num_tokens; i++) {
3858		dump_user_token(&tokens[i]);
3859		free_user_token(&tokens[i].token);
3860	}
3861
3862	SAFE_FREE(tokens);
3863	return 1;
3864}
3865
3866int net_usersidlist_usage(int argc, const char **argv)
3867{
3868	d_printf("net usersidlist\n"
3869		 "\tprints out a list of all users the running winbind knows\n"
3870		 "\tabout, together with all their SIDs. This is used as\n"
3871		 "\tinput to the 'net rpc share allowedusers' command.\n\n");
3872
3873	net_common_flags_usage(argc, argv);
3874	return -1;
3875}
3876
3877/**
3878 * 'net rpc share' entrypoint.
3879 * @param argc  Standard main() style argc
3880 * @param argv  Standard main() style argv.  Initial components are already
3881 *              stripped
3882 **/
3883
3884int net_rpc_share(int argc, const char **argv)
3885{
3886	struct functable func[] = {
3887		{"add", rpc_share_add},
3888		{"delete", rpc_share_delete},
3889		{"allowedusers", rpc_share_allowedusers},
3890		{"migrate", rpc_share_migrate},
3891		{NULL, NULL}
3892	};
3893
3894	if (argc == 0)
3895		return run_rpc_command(NULL, PI_SRVSVC, 0,
3896				       rpc_share_list_internals,
3897				       argc, argv);
3898
3899	return net_run_function(argc, argv, func, rpc_share_usage);
3900}
3901
3902/****************************************************************************/
3903
3904static int rpc_file_usage(int argc, const char **argv)
3905{
3906	return net_help_file(argc, argv);
3907}
3908
3909/**
3910 * Close a file on a remote RPC server
3911 *
3912 * All parameters are provided by the run_rpc_command function, except for
3913 * argc, argv which are passes through.
3914 *
3915 * @param domain_sid The domain sid acquired from the remote server
3916 * @param cli A cli_state connected to the server.
3917 * @param mem_ctx Talloc context, destoyed on completion of the function.
3918 * @param argc  Standard main() style argc
3919 * @param argv  Standard main() style argv.  Initial components are already
3920 *              stripped
3921 *
3922 * @return Normal NTSTATUS return.
3923 **/
3924static NTSTATUS
3925rpc_file_close_internals(const DOM_SID *domain_sid, const char *domain_name,
3926			 struct cli_state *cli,
3927			 TALLOC_CTX *mem_ctx, int argc, const char **argv)
3928{
3929	WERROR result;
3930	result = cli_srvsvc_net_file_close(cli, mem_ctx, atoi(argv[0]));
3931	return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3932}
3933
3934/**
3935 * Close a file on a remote RPC server
3936 *
3937 * @param argc  Standard main() style argc
3938 * @param argv  Standard main() style argv.  Initial components are already
3939 *              stripped
3940 *
3941 * @return A shell status integer (0 for success)
3942 **/
3943static int rpc_file_close(int argc, const char **argv)
3944{
3945	if (argc < 1) {
3946		DEBUG(1, ("No fileid given on close\n"));
3947		return(rpc_file_usage(argc, argv));
3948	}
3949
3950	return run_rpc_command(NULL, PI_SRVSVC, 0,
3951			       rpc_file_close_internals,
3952			       argc, argv);
3953}
3954
3955/**
3956 * Formatted print of open file info
3957 *
3958 * @param info3  FILE_INFO_3 contents
3959 * @param str3   strings for FILE_INFO_3
3960 **/
3961
3962static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
3963{
3964	fstring user = "", path = "";
3965
3966	rpcstr_pull_unistr2_fstring(user, &str3->uni_user_name);
3967	rpcstr_pull_unistr2_fstring(path, &str3->uni_path_name);
3968
3969	d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
3970		 info3->id, user, info3->perms, info3->num_locks, path);
3971}
3972
3973/**
3974 * List open files on a remote RPC server
3975 *
3976 * All parameters are provided by the run_rpc_command function, except for
3977 * argc, argv which are passes through.
3978 *
3979 * @param domain_sid The domain sid acquired from the remote server
3980 * @param cli A cli_state connected to the server.
3981 * @param mem_ctx Talloc context, destoyed on completion of the function.
3982 * @param argc  Standard main() style argc
3983 * @param argv  Standard main() style argv.  Initial components are already
3984 *              stripped
3985 *
3986 * @return Normal NTSTATUS return.
3987 **/
3988
3989static NTSTATUS
3990rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name,
3991			struct cli_state *cli,
3992			TALLOC_CTX *mem_ctx, int argc, const char **argv)
3993{
3994	SRV_FILE_INFO_CTR ctr;
3995	WERROR result;
3996	ENUM_HND hnd;
3997	uint32 preferred_len = 0xffffffff, i;
3998	const char *username=NULL;
3999
4000	init_enum_hnd(&hnd, 0);
4001
4002	/* if argc > 0, must be user command */
4003	if (argc > 0)
4004		username = smb_xstrdup(argv[0]);
4005
4006	result = cli_srvsvc_net_file_enum(
4007		cli, mem_ctx, 3, username, &ctr, preferred_len, &hnd);
4008
4009	if (!W_ERROR_IS_OK(result))
4010		goto done;
4011
4012	/* Display results */
4013
4014	d_printf(
4015		 "\nEnumerating open files on remote server:\n\n"\
4016		 "\nFileId  Opened by            Perms  Locks  Path"\
4017		 "\n------  ---------            -----  -----  ---- \n");
4018	for (i = 0; i < ctr.num_entries; i++)
4019		display_file_info_3(&ctr.file.info3[i].info_3,
4020				    &ctr.file.info3[i].info_3_str);
4021 done:
4022	return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
4023}
4024
4025
4026/**
4027 * List files for a user on a remote RPC server
4028 *
4029 * @param argc  Standard main() style argc
4030 * @param argv  Standard main() style argv.  Initial components are already
4031 *              stripped
4032 *
4033 * @return A shell status integer (0 for success)
4034 **/
4035static int rpc_file_user(int argc, const char **argv)
4036{
4037	if (argc < 1) {
4038		DEBUG(1, ("No username given\n"));
4039		return(rpc_file_usage(argc, argv));
4040	}
4041
4042	return run_rpc_command(NULL, PI_SRVSVC, 0,
4043			       rpc_file_list_internals,
4044			       argc, argv);
4045}
4046
4047
4048/**
4049 * 'net rpc file' entrypoint.
4050 * @param argc  Standard main() style argc
4051 * @param argv  Standard main() style argv.  Initial components are already
4052 *              stripped
4053 **/
4054
4055int net_rpc_file(int argc, const char **argv)
4056{
4057	struct functable func[] = {
4058		{"close", rpc_file_close},
4059		{"user", rpc_file_user},
4060#if 0
4061		{"info", rpc_file_info},
4062#endif
4063		{NULL, NULL}
4064	};
4065
4066	if (argc == 0)
4067		return run_rpc_command(NULL, PI_SRVSVC, 0,
4068				       rpc_file_list_internals,
4069				       argc, argv);
4070
4071	return net_run_function(argc, argv, func, rpc_file_usage);
4072}
4073
4074/****************************************************************************/
4075
4076
4077
4078/**
4079 * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
4080 *
4081 * All parameters are provided by the run_rpc_command function, except for
4082 * argc, argv which are passed through.
4083 *
4084 * @param domain_sid The domain sid aquired from the remote server
4085 * @param cli A cli_state connected to the server.
4086 * @param mem_ctx Talloc context, destoyed on compleation of the function.
4087 * @param argc  Standard main() style argc
4088 * @param argv  Standard main() style argv.  Initial components are already
4089 *              stripped
4090 *
4091 * @return Normal NTSTATUS return.
4092 **/
4093
4094static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid,
4095					     const char *domain_name,
4096					     struct cli_state *cli,
4097					     TALLOC_CTX *mem_ctx,
4098					     int argc, const char **argv)
4099{
4100	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4101
4102	result = cli_shutdown_abort(cli, mem_ctx);
4103
4104	if (NT_STATUS_IS_OK(result)) {
4105		d_printf("\nShutdown successfully aborted\n");
4106		DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
4107	} else
4108		DEBUG(5,("cmd_shutdown_abort: query failed\n"));
4109
4110	return result;
4111}
4112
4113
4114/**
4115 * ABORT the shutdown of a remote RPC Server,  over winreg pipe
4116 *
4117 * All parameters are provided by the run_rpc_command function, except for
4118 * argc, argv which are passed through.
4119 *
4120 * @param domain_sid The domain sid aquired from the remote server
4121 * @param cli A cli_state connected to the server.
4122 * @param mem_ctx Talloc context, destoyed on compleation of the function.
4123 * @param argc  Standard main() style argc
4124 * @param argv  Standard main() style argv.  Initial components are already
4125 *              stripped
4126 *
4127 * @return Normal NTSTATUS return.
4128 **/
4129
4130static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid,
4131						 const char *domain_name,
4132						 struct cli_state *cli,
4133						 TALLOC_CTX *mem_ctx,
4134						 int argc, const char **argv)
4135{
4136	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4137
4138	result = werror_to_ntstatus(cli_reg_abort_shutdown(cli, mem_ctx));
4139
4140	if (NT_STATUS_IS_OK(result)) {
4141		d_printf("\nShutdown successfully aborted\n");
4142		DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
4143	} else
4144		DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
4145
4146	return result;
4147}
4148
4149/**
4150 * ABORT the Shut down of a remote RPC server
4151 *
4152 * @param argc  Standard main() style argc
4153 * @param argv  Standard main() style argv.  Initial components are already
4154 *              stripped
4155 *
4156 * @return A shell status integer (0 for success)
4157 **/
4158
4159static int rpc_shutdown_abort(int argc, const char **argv)
4160{
4161	int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0,
4162				 rpc_shutdown_abort_internals,
4163				 argc, argv);
4164
4165	if (rc == 0)
4166		return rc;
4167
4168	DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
4169
4170	return run_rpc_command(NULL, PI_WINREG, 0,
4171			       rpc_reg_shutdown_abort_internals,
4172			       argc, argv);
4173}
4174
4175/**
4176 * Shut down a remote RPC Server via initshutdown pipe
4177 *
4178 * All parameters are provided by the run_rpc_command function, except for
4179 * argc, argv which are passes through.
4180 *
4181 * @param domain_sid The domain sid aquired from the remote server
4182 * @param cli A cli_state connected to the server.
4183 * @param mem_ctx Talloc context, destoyed on compleation of the function.
4184 * @param argc  Standard main() style argc
4185 * @param argc  Standard main() style argv.  Initial components are already
4186 *              stripped
4187 *
4188 * @return Normal NTSTATUS return.
4189 **/
4190
4191static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid,
4192					    const char *domain_name,
4193					    struct cli_state *cli,
4194					    TALLOC_CTX *mem_ctx,
4195					    int argc, const char **argv)
4196{
4197	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4198        const char *msg = "This machine will be shutdown shortly";
4199	uint32 timeout = 20;
4200
4201	if (opt_comment) {
4202		msg = opt_comment;
4203	}
4204	if (opt_timeout) {
4205		timeout = opt_timeout;
4206	}
4207
4208	/* create an entry */
4209	result = cli_shutdown_init(cli, mem_ctx, msg, timeout, opt_reboot,
4210				   opt_force);
4211
4212	if (NT_STATUS_IS_OK(result)) {
4213		d_printf("\nShutdown of remote machine succeeded\n");
4214		DEBUG(5,("Shutdown of remote machine succeeded\n"));
4215	} else
4216		DEBUG(0,("Shutdown of remote machine failed!\n"));
4217
4218	return result;
4219}
4220
4221/**
4222 * Shut down a remote RPC Server via winreg pipe
4223 *
4224 * All parameters are provided by the run_rpc_command function, except for
4225 * argc, argv which are passes through.
4226 *
4227 * @param domain_sid The domain sid aquired from the remote server
4228 * @param cli A cli_state connected to the server.
4229 * @param mem_ctx Talloc context, destoyed on compleation of the function.
4230 * @param argc  Standard main() style argc
4231 * @param argc  Standard main() style argv.  Initial components are already
4232 *              stripped
4233 *
4234 * @return Normal NTSTATUS return.
4235 **/
4236
4237static NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid,
4238					   const char *domain_name,
4239					   struct cli_state *cli,
4240					   TALLOC_CTX *mem_ctx,
4241					   int argc, const char **argv)
4242{
4243	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4244        const char *msg = "This machine will be shutdown shortly";
4245	uint32 timeout = 20;
4246#if 0
4247	poptContext pc;
4248	int rc;
4249
4250	struct poptOption long_options[] = {
4251		{"message",    'm', POPT_ARG_STRING, &msg},
4252		{"timeout",    't', POPT_ARG_INT,    &timeout},
4253		{"reboot",     'r', POPT_ARG_NONE,   &reboot},
4254		{"force",      'f', POPT_ARG_NONE,   &force},
4255		{ 0, 0, 0, 0}
4256	};
4257
4258	pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
4259			    POPT_CONTEXT_KEEP_FIRST);
4260
4261	rc = poptGetNextOpt(pc);
4262
4263	if (rc < -1) {
4264		/* an error occurred during option processing */
4265		DEBUG(0, ("%s: %s\n",
4266			  poptBadOption(pc, POPT_BADOPTION_NOALIAS),
4267			  poptStrerror(rc)));
4268		return NT_STATUS_INVALID_PARAMETER;
4269	}
4270#endif
4271	if (opt_comment) {
4272		msg = opt_comment;
4273	}
4274	if (opt_timeout) {
4275		timeout = opt_timeout;
4276	}
4277
4278	/* create an entry */
4279	result = werror_to_ntstatus(cli_reg_shutdown(cli, mem_ctx, msg, timeout, opt_reboot, opt_force));
4280
4281	if (NT_STATUS_IS_OK(result)) {
4282		d_printf("\nShutdown of remote machine succeeded\n");
4283		DEBUG(5,("Shutdown of remote machine succeeded\n"));
4284	}
4285	else
4286		DEBUG(0,("Shutdown of remote machine failed!\n"));
4287
4288	return result;
4289}
4290
4291/**
4292 * Shut down a remote RPC server
4293 *
4294 * @param argc  Standard main() style argc
4295 * @param argc  Standard main() style argv.  Initial components are already
4296 *              stripped
4297 *
4298 * @return A shell status integer (0 for success)
4299 **/
4300
4301static int rpc_shutdown(int argc, const char **argv)
4302{
4303	int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0,
4304				 rpc_init_shutdown_internals,
4305				 argc, argv);
4306	if (rc == 0)
4307		return rc;
4308
4309	DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
4310
4311	return run_rpc_command(NULL, PI_WINREG, 0, rpc_reg_shutdown_internals,
4312				       argc, argv);
4313}
4314
4315/***************************************************************************
4316  NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
4317
4318 ***************************************************************************/
4319
4320/**
4321 * Add interdomain trust account to the RPC server.
4322 * All parameters (except for argc and argv) are passed by run_rpc_command
4323 * function.
4324 *
4325 * @param domain_sid The domain sid acquired from the server
4326 * @param cli A cli_state connected to the server.
4327 * @param mem_ctx Talloc context, destoyed on completion of the function.
4328 * @param argc  Standard main() style argc
4329 * @param argc  Standard main() style argv.  Initial components are already
4330 *              stripped
4331 *
4332 * @return normal NTSTATUS return code
4333 */
4334
4335static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid,
4336					   const char *domain_name,
4337					   struct cli_state *cli, TALLOC_CTX *mem_ctx,
4338                                           int argc, const char **argv) {
4339
4340	POLICY_HND connect_pol, domain_pol, user_pol;
4341	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4342	char *acct_name;
4343	uint16 acb_info;
4344	uint32 unknown, user_rid;
4345
4346	if (argc != 2) {
4347		d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
4348		return NT_STATUS_INVALID_PARAMETER;
4349	}
4350
4351	/*
4352	 * Make valid trusting domain account (ie. uppercased and with '$' appended)
4353	 */
4354
4355	if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
4356		return NT_STATUS_NO_MEMORY;
4357	}
4358
4359	strupper_m(acct_name);
4360
4361	/* Get samr policy handle */
4362	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
4363				  &connect_pol);
4364	if (!NT_STATUS_IS_OK(result)) {
4365		goto done;
4366	}
4367
4368	/* Get domain policy handle */
4369	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
4370				      MAXIMUM_ALLOWED_ACCESS,
4371				      domain_sid, &domain_pol);
4372	if (!NT_STATUS_IS_OK(result)) {
4373		goto done;
4374	}
4375
4376	/* Create trusting domain's account */
4377	acb_info = ACB_NORMAL;
4378	unknown = 0xe00500b0; /* No idea what this is - a permission mask?
4379	                         mimir: yes, most probably it is */
4380
4381	result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
4382					  acct_name, acb_info, unknown,
4383					  &user_pol, &user_rid);
4384	if (!NT_STATUS_IS_OK(result)) {
4385		goto done;
4386	}
4387
4388	{
4389		SAM_USERINFO_CTR ctr;
4390		SAM_USER_INFO_23 p23;
4391		NTTIME notime;
4392		char nostr[] = "";
4393		LOGON_HRS hrs;
4394		uchar pwbuf[516];
4395
4396		encode_pw_buffer((char *)pwbuf, argv[1], STR_UNICODE);
4397
4398		ZERO_STRUCT(ctr);
4399		ZERO_STRUCT(p23);
4400		ZERO_STRUCT(notime);
4401		hrs.max_len = 1260;
4402		hrs.offset = 0;
4403		hrs.len = 21;
4404		memset(hrs.hours, 0xFF, sizeof(hrs.hours));
4405		acb_info = ACB_DOMTRUST;
4406
4407		init_sam_user_info23A(&p23, &notime, &notime, &notime,
4408				      &notime, &notime, &notime,
4409				      nostr, nostr, nostr, nostr, nostr,
4410				      nostr, nostr, nostr, nostr, nostr,
4411				      0, 0, acb_info, ACCT_FLAGS, 168, &hrs,
4412				      0, 0, (char *)pwbuf);
4413		ctr.switch_value = 23;
4414		ctr.info.id23 = &p23;
4415		p23.passmustchange = 0;
4416
4417		result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 23,
4418					       &cli->user_session_key, &ctr);
4419
4420		if (!NT_STATUS_IS_OK(result)) {
4421			DEBUG(0,("Could not set trust account password: %s\n",
4422				 nt_errstr(result)));
4423			goto done;
4424		}
4425	}
4426
4427 done:
4428	SAFE_FREE(acct_name);
4429	return result;
4430}
4431
4432/**
4433 * Create interdomain trust account for a remote domain.
4434 *
4435 * @param argc standard argc
4436 * @param argv standard argv without initial components
4437 *
4438 * @return Integer status (0 means success)
4439 **/
4440
4441static int rpc_trustdom_add(int argc, const char **argv)
4442{
4443	if (argc > 0) {
4444		return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
4445		                       argc, argv);
4446	} else {
4447		d_printf("Usage: net rpc trustdom add <domain>\n");
4448		return -1;
4449	}
4450}
4451
4452/**
4453 * Remove interdomain trust account from the RPC server.
4454 * All parameters (except for argc and argv) are passed by run_rpc_command
4455 * function.
4456 *
4457 * @param domain_sid The domain sid acquired from the server
4458 * @param cli A cli_state connected to the server.
4459 * @param mem_ctx Talloc context, destoyed on completion of the function.
4460 * @param argc  Standard main() style argc
4461 * @param argc  Standard main() style argv.  Initial components are already
4462 *              stripped
4463 *
4464 * @return normal NTSTATUS return code
4465 */
4466
4467static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid,
4468					   const char *domain_name,
4469					   struct cli_state *cli, TALLOC_CTX *mem_ctx,
4470                                           int argc, const char **argv) {
4471
4472	POLICY_HND connect_pol, domain_pol, user_pol;
4473	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4474	char *acct_name;
4475	DOM_SID trust_acct_sid;
4476	uint32 *user_rids, num_rids, *name_types;
4477	uint32 flags = 0x000003e8; /* Unknown */
4478
4479	if (argc != 1) {
4480		d_printf("Usage: net rpc trustdom del <domain_name>\n");
4481		return NT_STATUS_INVALID_PARAMETER;
4482	}
4483
4484	/*
4485	 * Make valid trusting domain account (ie. uppercased and with '$' appended)
4486	 */
4487
4488	if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
4489		return NT_STATUS_NO_MEMORY;
4490	}
4491
4492	strupper_m(acct_name);
4493
4494	/* Get samr policy handle */
4495	result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
4496				  &connect_pol);
4497	if (!NT_STATUS_IS_OK(result)) {
4498		goto done;
4499	}
4500
4501	/* Get domain policy handle */
4502	result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
4503				      MAXIMUM_ALLOWED_ACCESS,
4504				      domain_sid, &domain_pol);
4505	if (!NT_STATUS_IS_OK(result)) {
4506		goto done;
4507	}
4508
4509	result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, 1,
4510				       &acct_name, &num_rids, &user_rids,
4511				       &name_types);
4512
4513	if (!NT_STATUS_IS_OK(result)) {
4514		goto done;
4515	}
4516
4517	result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
4518				    MAXIMUM_ALLOWED_ACCESS,
4519				    user_rids[0], &user_pol);
4520
4521	if (!NT_STATUS_IS_OK(result)) {
4522		goto done;
4523	}
4524
4525	/* append the rid to the domain sid */
4526	sid_copy(&trust_acct_sid, domain_sid);
4527	if (!sid_append_rid(&trust_acct_sid, user_rids[0])) {
4528		goto done;
4529	}
4530
4531	/* remove the sid */
4532
4533	result = cli_samr_remove_sid_foreign_domain(cli, mem_ctx, &user_pol,
4534						    &trust_acct_sid);
4535
4536	if (!NT_STATUS_IS_OK(result)) {
4537		goto done;
4538	}
4539
4540	/* Delete user */
4541
4542	result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
4543
4544	if (!NT_STATUS_IS_OK(result)) {
4545		goto done;
4546	}
4547
4548	if (!NT_STATUS_IS_OK(result)) {
4549	  DEBUG(0,("Could not set trust account password: %s\n",
4550		   nt_errstr(result)));
4551	  goto done;
4552	}
4553
4554 done:
4555	SAFE_FREE(acct_name);
4556	return result;
4557}
4558
4559/**
4560 * Delete interdomain trust account for a remote domain.
4561 *
4562 * @param argc standard argc
4563 * @param argv standard argv without initial components
4564 *
4565 * @return Integer status (0 means success)
4566 **/
4567
4568static int rpc_trustdom_del(int argc, const char **argv)
4569{
4570	if (argc > 0) {
4571		return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_del_internals,
4572		                       argc, argv);
4573	} else {
4574		d_printf("Usage: net rpc trustdom del <domain>\n");
4575		return -1;
4576	}
4577}
4578
4579/**
4580 * Establish trust relationship to a trusting domain.
4581 * Interdomain account must already be created on remote PDC.
4582 *
4583 * @param argc standard argc
4584 * @param argv standard argv without initial components
4585 *
4586 * @return Integer status (0 means success)
4587 **/
4588
4589static int rpc_trustdom_establish(int argc, const char **argv)
4590{
4591	struct cli_state *cli;
4592	struct in_addr server_ip;
4593	POLICY_HND connect_hnd;
4594	TALLOC_CTX *mem_ctx;
4595	NTSTATUS nt_status;
4596	DOM_SID *domain_sid;
4597	WKS_INFO_100 wks_info;
4598
4599	char* domain_name;
4600	char* domain_name_pol;
4601	char* acct_name;
4602	fstring pdc_name;
4603
4604	/*
4605	 * Connect to \\server\ipc$ as 'our domain' account with password
4606	 */
4607
4608	if (argc != 1) {
4609		d_printf("Usage: net rpc trustdom establish <domain_name>\n");
4610		return -1;
4611	}
4612
4613	domain_name = smb_xstrdup(argv[0]);
4614	strupper_m(domain_name);
4615
4616	/* account name used at first is our domain's name with '$' */
4617	asprintf(&acct_name, "%s$", lp_workgroup());
4618	strupper_m(acct_name);
4619
4620	/*
4621	 * opt_workgroup will be used by connection functions further,
4622	 * hence it should be set to remote domain name instead of ours
4623	 */
4624	if (opt_workgroup) {
4625		opt_workgroup = smb_xstrdup(domain_name);
4626	};
4627
4628	opt_user_name = acct_name;
4629
4630	/* find the domain controller */
4631	if (!net_find_pdc(&server_ip, pdc_name, domain_name)) {
4632		DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
4633		return -1;
4634	}
4635
4636	/* connect to ipc$ as username/password */
4637	nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
4638	if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
4639
4640		/* Is it trusting domain account for sure ? */
4641		DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
4642			nt_errstr(nt_status)));
4643		return -1;
4644	}
4645
4646	/*
4647	 * Connect to \\server\ipc$ again (this time anonymously)
4648	 */
4649
4650	nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
4651
4652	if (NT_STATUS_IS_ERR(nt_status)) {
4653		DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
4654			domain_name, nt_errstr(nt_status)));
4655	}
4656
4657	/*
4658	 * Use NetServerEnum2 to make sure we're talking to a proper server
4659	 */
4660
4661	if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
4662		DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
4663			 for domain %s\n", domain_name));
4664	}
4665
4666	/*
4667	 * Call WksQueryInfo to check remote server's capabilities
4668	 * note: It is now used only to get unicode domain name
4669	 */
4670
4671	if (!cli_nt_session_open(cli, PI_WKSSVC)) {
4672		DEBUG(0, ("Couldn't not initialise wkssvc pipe\n"));
4673		return -1;
4674	}
4675
4676	if (!(mem_ctx = talloc_init("establishing trust relationship to domain %s",
4677	                domain_name))) {
4678		DEBUG(0, ("talloc_init() failed\n"));
4679		cli_shutdown(cli);
4680		return -1;
4681	}
4682
4683   	nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info);
4684
4685	if (NT_STATUS_IS_ERR(nt_status)) {
4686		DEBUG(0, ("WksQueryInfo call failed.\n"));
4687		return -1;
4688	}
4689
4690	if (cli->nt_pipe_fnum[cli->pipe_idx])
4691		cli_nt_session_close(cli);
4692
4693
4694	/*
4695	 * Call LsaOpenPolicy and LsaQueryInfo
4696	 */
4697
4698	if (!(mem_ctx = talloc_init("rpc_trustdom_establish"))) {
4699		DEBUG(0, ("talloc_init() failed\n"));
4700		cli_shutdown(cli);
4701		return -1;
4702	}
4703
4704	if (!cli_nt_session_open(cli, PI_LSARPC)) {
4705		DEBUG(0, ("Could not initialise lsa pipe\n"));
4706		cli_shutdown(cli);
4707		return -1;
4708	}
4709
4710	nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
4711	                                 &connect_hnd);
4712	if (NT_STATUS_IS_ERR(nt_status)) {
4713		DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
4714			nt_errstr(nt_status)));
4715		return -1;
4716	}
4717
4718	/* Querying info level 5 */
4719
4720	nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
4721	                                      5 /* info level */, &domain_name_pol,
4722	                                      &domain_sid);
4723	if (NT_STATUS_IS_ERR(nt_status)) {
4724		DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
4725			nt_errstr(nt_status)));
4726		return -1;
4727	}
4728
4729
4730
4731
4732	/* There should be actually query info level 3 (following nt serv behaviour),
4733	   but I still don't know if it's _really_ necessary */
4734
4735	/*
4736	 * Store the password in secrets db
4737	 */
4738
4739	if (!secrets_store_trusted_domain_password(domain_name, wks_info.uni_lan_grp.buffer,
4740						   wks_info.uni_lan_grp.uni_str_len, opt_password,
4741						   *domain_sid)) {
4742		DEBUG(0, ("Storing password for trusted domain failed.\n"));
4743		return -1;
4744	}
4745
4746	/*
4747	 * Close the pipes and clean up
4748	 */
4749
4750	nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
4751	if (NT_STATUS_IS_ERR(nt_status)) {
4752		DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
4753			nt_errstr(nt_status)));
4754		return -1;
4755	}
4756
4757	if (cli->nt_pipe_fnum[cli->pipe_idx])
4758		cli_nt_session_close(cli);
4759
4760	talloc_destroy(mem_ctx);
4761
4762	d_printf("Trust to domain %s established\n", domain_name);
4763	return 0;
4764}
4765
4766/**
4767 * Revoke trust relationship to the remote domain
4768 *
4769 * @param argc standard argc
4770 * @param argv standard argv without initial components
4771 *
4772 * @return Integer status (0 means success)
4773 **/
4774
4775static int rpc_trustdom_revoke(int argc, const char **argv)
4776{
4777	char* domain_name;
4778
4779	if (argc < 1) return -1;
4780
4781	/* generate upper cased domain name */
4782	domain_name = smb_xstrdup(argv[0]);
4783	strupper_m(domain_name);
4784
4785	/* delete password of the trust */
4786	if (!trusted_domain_password_delete(domain_name)) {
4787		DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
4788			  domain_name));
4789		return -1;
4790	};
4791
4792	return 0;
4793}
4794
4795/**
4796 * Usage for 'net rpc trustdom' command
4797 *
4798 * @param argc standard argc
4799 * @param argv standard argv without inital components
4800 *
4801 * @return Integer status returned to shell
4802 **/
4803
4804static int rpc_trustdom_usage(int argc, const char **argv)
4805{
4806	d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
4807	d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
4808	d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
4809	d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
4810	d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
4811	return -1;
4812}
4813
4814
4815static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid,
4816				     const char *domain_name,
4817				     struct cli_state *cli, TALLOC_CTX *mem_ctx,
4818				     int argc, const char **argv)
4819{
4820	fstring str_sid;
4821	sid_to_string(str_sid, domain_sid);
4822	d_printf("%s\n", str_sid);
4823	return NT_STATUS_OK;
4824}
4825
4826
4827static int rpc_trustdom_list(int argc, const char **argv)
4828{
4829	/* common variables */
4830	TALLOC_CTX* mem_ctx;
4831	struct cli_state *cli, *remote_cli;
4832	NTSTATUS nt_status;
4833	const char *domain_name = NULL;
4834	DOM_SID *queried_dom_sid;
4835	fstring ascii_sid, padding;
4836	int ascii_dom_name_len;
4837	POLICY_HND connect_hnd;
4838
4839	/* trusted domains listing variables */
4840	unsigned int num_domains, enum_ctx = 0;
4841	int i, pad_len, col_len = 20;
4842	DOM_SID *domain_sids;
4843	char **trusted_dom_names;
4844	fstring pdc_name;
4845	char *dummy;
4846
4847	/* trusting domains listing variables */
4848	POLICY_HND domain_hnd;
4849	char **trusting_dom_names;
4850	uint32 *trusting_dom_rids;
4851
4852	/*
4853	 * Listing trusted domains (stored in secrets.tdb, if local)
4854	 */
4855
4856	mem_ctx = talloc_init("trust relationships listing");
4857
4858	/*
4859	 * set domain and pdc name to local samba server (default)
4860	 * or to remote one given in command line
4861	 */
4862
4863	if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
4864		domain_name = opt_workgroup;
4865		opt_target_workgroup = opt_workgroup;
4866	} else {
4867		fstrcpy(pdc_name, global_myname());
4868		domain_name = talloc_strdup(mem_ctx, lp_workgroup());
4869		opt_target_workgroup = domain_name;
4870	};
4871
4872	/* open \PIPE\lsarpc and open policy handle */
4873	if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
4874		DEBUG(0, ("Couldn't connect to domain controller\n"));
4875		return -1;
4876	};
4877
4878	if (!cli_nt_session_open(cli, PI_LSARPC)) {
4879		DEBUG(0, ("Could not initialise lsa pipe\n"));
4880		return -1;
4881	};
4882
4883	nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
4884					&connect_hnd);
4885	if (NT_STATUS_IS_ERR(nt_status)) {
4886		DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
4887 			nt_errstr(nt_status)));
4888		return -1;
4889	};
4890
4891	/* query info level 5 to obtain sid of a domain being queried */
4892	nt_status = cli_lsa_query_info_policy(
4893		cli, mem_ctx, &connect_hnd, 5 /* info level */,
4894		&dummy, &queried_dom_sid);
4895
4896	if (NT_STATUS_IS_ERR(nt_status)) {
4897		DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
4898			nt_errstr(nt_status)));
4899		return -1;
4900	}
4901
4902	/*
4903	 * Keep calling LsaEnumTrustdom over opened pipe until
4904	 * the end of enumeration is reached
4905	 */
4906
4907	d_printf("Trusted domains list:\n\n");
4908
4909	do {
4910		nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx,
4911						   &num_domains,
4912						   &trusted_dom_names, &domain_sids);
4913
4914		if (NT_STATUS_IS_ERR(nt_status)) {
4915			DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
4916				nt_errstr(nt_status)));
4917			return -1;
4918		};
4919
4920		for (i = 0; i < num_domains; i++) {
4921			/* convert sid into ascii string */
4922			sid_to_string(ascii_sid, &(domain_sids[i]));
4923
4924			/* calculate padding space for d_printf to look nicer */
4925			pad_len = col_len - strlen(trusted_dom_names[i]);
4926			padding[pad_len] = 0;
4927			do padding[--pad_len] = ' '; while (pad_len);
4928
4929			d_printf("%s%s%s\n", trusted_dom_names[i], padding, ascii_sid);
4930		};
4931
4932		/*
4933		 * in case of no trusted domains say something rather
4934		 * than just display blank line
4935		 */
4936		if (!num_domains) d_printf("none\n");
4937
4938	} while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
4939
4940	/* close this connection before doing next one */
4941	nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
4942	if (NT_STATUS_IS_ERR(nt_status)) {
4943		DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
4944			nt_errstr(nt_status)));
4945		return -1;
4946	};
4947
4948	cli_nt_session_close(cli);
4949
4950	/*
4951	 * Listing trusting domains (stored in passdb backend, if local)
4952	 */
4953
4954	d_printf("\nTrusting domains list:\n\n");
4955
4956	/*
4957	 * Open \PIPE\samr and get needed policy handles
4958	 */
4959	if (!cli_nt_session_open(cli, PI_SAMR)) {
4960		DEBUG(0, ("Could not initialise samr pipe\n"));
4961		return -1;
4962	};
4963
4964	/* SamrConnect */
4965	nt_status = cli_samr_connect(cli, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN,
4966								 &connect_hnd);
4967	if (!NT_STATUS_IS_OK(nt_status)) {
4968		DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
4969			nt_errstr(nt_status)));
4970		return -1;
4971	};
4972
4973	/* SamrOpenDomain - we have to open domain policy handle in order to be
4974	   able to enumerate accounts*/
4975	nt_status = cli_samr_open_domain(cli, mem_ctx, &connect_hnd,
4976					 SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
4977					 queried_dom_sid, &domain_hnd);
4978	if (!NT_STATUS_IS_OK(nt_status)) {
4979		DEBUG(0, ("Couldn't open domain object. Error was %s\n",
4980			nt_errstr(nt_status)));
4981		return -1;
4982	};
4983
4984	/*
4985	 * perform actual enumeration
4986	 */
4987
4988	enum_ctx = 0;	/* reset enumeration context from last enumeration */
4989	do {
4990
4991		nt_status = cli_samr_enum_dom_users(cli, mem_ctx, &domain_hnd,
4992		                                    &enum_ctx, ACB_DOMTRUST, 0xffff,
4993		                                    &trusting_dom_names, &trusting_dom_rids,
4994		                                    &num_domains);
4995		if (NT_STATUS_IS_ERR(nt_status)) {
4996			DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
4997				nt_errstr(nt_status)));
4998			return -1;
4999		};
5000
5001		for (i = 0; i < num_domains; i++) {
5002
5003			/*
5004			 * get each single domain's sid (do we _really_ need this ?):
5005			 *  1) connect to domain's pdc
5006			 *  2) query the pdc for domain's sid
5007			 */
5008
5009			/* get rid of '$' tail */
5010			ascii_dom_name_len = strlen(trusting_dom_names[i]);
5011			if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
5012				trusting_dom_names[i][ascii_dom_name_len - 1] = '\0';
5013
5014			/* calculate padding space for d_printf to look nicer */
5015			pad_len = col_len - strlen(trusting_dom_names[i]);
5016			padding[pad_len] = 0;
5017			do padding[--pad_len] = ' '; while (pad_len);
5018
5019			/* set opt_* variables to remote domain */
5020			strupper_m(trusting_dom_names[i]);
5021			opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]);
5022			opt_target_workgroup = opt_workgroup;
5023
5024			d_printf("%s%s", trusting_dom_names[i], padding);
5025
5026			/* connect to remote domain controller */
5027			remote_cli = net_make_ipc_connection(NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS);
5028			if (remote_cli) {
5029				/* query for domain's sid */
5030				if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
5031					d_printf("couldn't get domain's sid\n");
5032
5033				cli_shutdown(remote_cli);
5034
5035			} else {
5036				d_printf("domain controller is not responding\n");
5037			};
5038		};
5039
5040		if (!num_domains) d_printf("none\n");
5041
5042	} while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
5043
5044	/* close opened samr and domain policy handles */
5045	nt_status = cli_samr_close(cli, mem_ctx, &domain_hnd);
5046	if (!NT_STATUS_IS_OK(nt_status)) {
5047		DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
5048	};
5049
5050	nt_status = cli_samr_close(cli, mem_ctx, &connect_hnd);
5051	if (!NT_STATUS_IS_OK(nt_status)) {
5052		DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
5053	};
5054
5055	/* close samr pipe and connection to IPC$ */
5056	cli_nt_session_close(cli);
5057	cli_shutdown(cli);
5058
5059	talloc_destroy(mem_ctx);
5060	return 0;
5061}
5062
5063/**
5064 * Entrypoint for 'net rpc trustdom' code
5065 *
5066 * @param argc standard argc
5067 * @param argv standard argv without initial components
5068 *
5069 * @return Integer status (0 means success)
5070 */
5071
5072static int rpc_trustdom(int argc, const char **argv)
5073{
5074	struct functable func[] = {
5075		{"add", rpc_trustdom_add},
5076		{"del", rpc_trustdom_del},
5077		{"establish", rpc_trustdom_establish},
5078		{"revoke", rpc_trustdom_revoke},
5079		{"help", rpc_trustdom_usage},
5080		{"list", rpc_trustdom_list},
5081		{NULL, NULL}
5082	};
5083
5084	if (argc == 0) {
5085		rpc_trustdom_usage(argc, argv);
5086		return -1;
5087	}
5088
5089	return (net_run_function(argc, argv, func, rpc_user_usage));
5090}
5091
5092/**
5093 * Check if a server will take rpc commands
5094 * @param flags	Type of server to connect to (PDC, DMB, localhost)
5095 *		if the host is not explicitly specified
5096 * @return  BOOL (true means rpc supported)
5097 */
5098BOOL net_rpc_check(unsigned flags)
5099{
5100	struct cli_state cli;
5101	BOOL ret = False;
5102	struct in_addr server_ip;
5103	char *server_name = NULL;
5104
5105	/* flags (i.e. server type) may depend on command */
5106	if (!net_find_server(flags, &server_ip, &server_name))
5107		return False;
5108
5109	ZERO_STRUCT(cli);
5110	if (cli_initialise(&cli) == False)
5111		return False;
5112
5113	if (!cli_connect(&cli, server_name, &server_ip))
5114		goto done;
5115	if (!attempt_netbios_session_request(&cli, global_myname(),
5116					     server_name, &server_ip))
5117		goto done;
5118	if (!cli_negprot(&cli))
5119		goto done;
5120	if (cli.protocol < PROTOCOL_NT1)
5121		goto done;
5122
5123	ret = True;
5124 done:
5125	cli_shutdown(&cli);
5126	return ret;
5127}
5128
5129/* dump sam database via samsync rpc calls */
5130static int rpc_samdump(int argc, const char **argv) {
5131	return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
5132			       argc, argv);
5133}
5134
5135/* syncronise sam database via samsync rpc calls */
5136static int rpc_vampire(int argc, const char **argv) {
5137	return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
5138			       argc, argv);
5139}
5140
5141/**
5142 * Migrate everything from a print-server
5143 *
5144 * @param argc  Standard main() style argc
5145 * @param argv  Standard main() style argv.  Initial components are already
5146 *              stripped
5147 *
5148 * @return A shell status integer (0 for success)
5149 *
5150 * The order is important !
5151 * To successfully add drivers the print-queues have to exist !
5152 * Applying ACLs should be the last step, because you're easily locked out
5153 *
5154 **/
5155static int rpc_printer_migrate_all(int argc, const char **argv)
5156{
5157	int ret;
5158
5159	if (!opt_host) {
5160		printf("no server to migrate\n");
5161		return -1;
5162	}
5163
5164	ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
5165	if (ret)
5166		return ret;
5167
5168	ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
5169	if (ret)
5170		return ret;
5171
5172	ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
5173	if (ret)
5174		return ret;
5175
5176	ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
5177	if (ret)
5178		return ret;
5179
5180	return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
5181
5182}
5183
5184/**
5185 * Migrate print-drivers from a print-server
5186 *
5187 * @param argc  Standard main() style argc
5188 * @param argv  Standard main() style argv.  Initial components are already
5189 *              stripped
5190 *
5191 * @return A shell status integer (0 for success)
5192 **/
5193static int rpc_printer_migrate_drivers(int argc, const char **argv)
5194{
5195	if (!opt_host) {
5196		printf("no server to migrate\n");
5197		return -1;
5198	}
5199
5200	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5201			       rpc_printer_migrate_drivers_internals,
5202			       argc, argv);
5203}
5204
5205/**
5206 * Migrate print-forms from a print-server
5207 *
5208 * @param argc  Standard main() style argc
5209 * @param argv  Standard main() style argv.  Initial components are already
5210 *              stripped
5211 *
5212 * @return A shell status integer (0 for success)
5213 **/
5214static int rpc_printer_migrate_forms(int argc, const char **argv)
5215{
5216	if (!opt_host) {
5217		printf("no server to migrate\n");
5218		return -1;
5219	}
5220
5221	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5222			       rpc_printer_migrate_forms_internals,
5223			       argc, argv);
5224}
5225
5226/**
5227 * Migrate printers from a print-server
5228 *
5229 * @param argc  Standard main() style argc
5230 * @param argv  Standard main() style argv.  Initial components are already
5231 *              stripped
5232 *
5233 * @return A shell status integer (0 for success)
5234 **/
5235static int rpc_printer_migrate_printers(int argc, const char **argv)
5236{
5237	if (!opt_host) {
5238		printf("no server to migrate\n");
5239		return -1;
5240	}
5241
5242	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5243			       rpc_printer_migrate_printers_internals,
5244			       argc, argv);
5245}
5246
5247/**
5248 * Migrate printer-ACLs from a print-server
5249 *
5250 * @param argc  Standard main() style argc
5251 * @param argv  Standard main() style argv.  Initial components are already
5252 *              stripped
5253 *
5254 * @return A shell status integer (0 for success)
5255 **/
5256static int rpc_printer_migrate_security(int argc, const char **argv)
5257{
5258	if (!opt_host) {
5259		printf("no server to migrate\n");
5260		return -1;
5261	}
5262
5263	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5264			       rpc_printer_migrate_security_internals,
5265			       argc, argv);
5266}
5267
5268/**
5269 * Migrate printer-settings from a print-server
5270 *
5271 * @param argc  Standard main() style argc
5272 * @param argv  Standard main() style argv.  Initial components are already
5273 *              stripped
5274 *
5275 * @return A shell status integer (0 for success)
5276 **/
5277static int rpc_printer_migrate_settings(int argc, const char **argv)
5278{
5279	if (!opt_host) {
5280		printf("no server to migrate\n");
5281		return -1;
5282	}
5283
5284	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5285			       rpc_printer_migrate_settings_internals,
5286			       argc, argv);
5287}
5288
5289/**
5290 * 'net rpc printer' entrypoint.
5291 * @param argc  Standard main() style argc
5292 * @param argv  Standard main() style argv.  Initial components are already
5293 *              stripped
5294 **/
5295
5296int rpc_printer_migrate(int argc, const char **argv)
5297{
5298
5299	/* ouch: when addriver and setdriver are called from within
5300	   rpc_printer_migrate_drivers_internals, the printer-queue already
5301	   *has* to exist */
5302
5303	struct functable func[] = {
5304		{"all", 	rpc_printer_migrate_all},
5305		{"drivers", 	rpc_printer_migrate_drivers},
5306		{"forms", 	rpc_printer_migrate_forms},
5307		{"help", 	rpc_printer_usage},
5308		{"printers", 	rpc_printer_migrate_printers},
5309		{"security", 	rpc_printer_migrate_security},
5310		{"settings", 	rpc_printer_migrate_settings},
5311		{NULL, NULL}
5312	};
5313
5314	return net_run_function(argc, argv, func, rpc_printer_usage);
5315}
5316
5317
5318/**
5319 * List printers on a remote RPC server
5320 *
5321 * @param argc  Standard main() style argc
5322 * @param argv  Standard main() style argv.  Initial components are already
5323 *              stripped
5324 *
5325 * @return A shell status integer (0 for success)
5326 **/
5327static int rpc_printer_list(int argc, const char **argv)
5328{
5329
5330	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5331			       rpc_printer_list_internals,
5332			       argc, argv);
5333}
5334
5335/**
5336 * List printer-drivers on a remote RPC server
5337 *
5338 * @param argc  Standard main() style argc
5339 * @param argv  Standard main() style argv.  Initial components are already
5340 *              stripped
5341 *
5342 * @return A shell status integer (0 for success)
5343 **/
5344static int rpc_printer_driver_list(int argc, const char **argv)
5345{
5346
5347	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5348			       rpc_printer_driver_list_internals,
5349			       argc, argv);
5350}
5351
5352/**
5353 * Publish printer in ADS via MSRPC
5354 *
5355 * @param argc  Standard main() style argc
5356 * @param argv  Standard main() style argv.  Initial components are already
5357 *              stripped
5358 *
5359 * @return A shell status integer (0 for success)
5360 **/
5361static int rpc_printer_publish_publish(int argc, const char **argv)
5362{
5363
5364	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5365			       rpc_printer_publish_publish_internals,
5366			       argc, argv);
5367}
5368
5369/**
5370 * Update printer in ADS via MSRPC
5371 *
5372 * @param argc  Standard main() style argc
5373 * @param argv  Standard main() style argv.  Initial components are already
5374 *              stripped
5375 *
5376 * @return A shell status integer (0 for success)
5377 **/
5378static int rpc_printer_publish_update(int argc, const char **argv)
5379{
5380
5381	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5382			       rpc_printer_publish_update_internals,
5383			       argc, argv);
5384}
5385
5386/**
5387 * UnPublish printer in ADS via MSRPC
5388 *
5389 * @param argc  Standard main() style argc
5390 * @param argv  Standard main() style argv.  Initial components are already
5391 *              stripped
5392 *
5393 * @return A shell status integer (0 for success)
5394 **/
5395static int rpc_printer_publish_unpublish(int argc, const char **argv)
5396{
5397
5398	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5399			       rpc_printer_publish_unpublish_internals,
5400			       argc, argv);
5401}
5402
5403/**
5404 * List published printers via MSRPC
5405 *
5406 * @param argc  Standard main() style argc
5407 * @param argv  Standard main() style argv.  Initial components are already
5408 *              stripped
5409 *
5410 * @return A shell status integer (0 for success)
5411 **/
5412static int rpc_printer_publish_list(int argc, const char **argv)
5413{
5414
5415	return run_rpc_command(NULL, PI_SPOOLSS, 0,
5416			       rpc_printer_publish_list_internals,
5417			       argc, argv);
5418}
5419
5420
5421/**
5422 * Publish printer in ADS
5423 *
5424 * @param argc  Standard main() style argc
5425 * @param argv  Standard main() style argv.  Initial components are already
5426 *              stripped
5427 *
5428 * @return A shell status integer (0 for success)
5429 **/
5430static int rpc_printer_publish(int argc, const char **argv)
5431{
5432
5433	struct functable func[] = {
5434		{"publish", 	rpc_printer_publish_publish},
5435		{"update", 	rpc_printer_publish_update},
5436		{"unpublish", 	rpc_printer_publish_unpublish},
5437		{"list", 	rpc_printer_publish_list},
5438		{"help", 	rpc_printer_usage},
5439		{NULL, NULL}
5440	};
5441
5442	if (argc == 0)
5443		return run_rpc_command(NULL, PI_SPOOLSS, 0,
5444			       rpc_printer_publish_list_internals,
5445			       argc, argv);
5446
5447	return net_run_function(argc, argv, func, rpc_printer_usage);
5448
5449}
5450
5451
5452/**
5453 * Display rpc printer help page.
5454 * @param argc  Standard main() style argc
5455 * @param argv  Standard main() style argv.  Initial components are already
5456 *              stripped
5457 **/
5458int rpc_printer_usage(int argc, const char **argv)
5459{
5460        return net_help_printer(argc, argv);
5461}
5462
5463/**
5464 * 'net rpc printer' entrypoint.
5465 * @param argc  Standard main() style argc
5466 * @param argv  Standard main() style argv.  Initial components are already
5467 *              stripped
5468 **/
5469int net_rpc_printer(int argc, const char **argv)
5470{
5471	struct functable func[] = {
5472		{"list", rpc_printer_list},
5473		{"migrate", rpc_printer_migrate},
5474		{"driver", rpc_printer_driver_list},
5475		{"publish", rpc_printer_publish},
5476		{NULL, NULL}
5477	};
5478
5479	if (argc == 0)
5480		return run_rpc_command(NULL, PI_SPOOLSS, 0,
5481			       rpc_printer_list_internals,
5482			       argc, argv);
5483
5484	return net_run_function(argc, argv, func, rpc_printer_usage);
5485}
5486
5487/****************************************************************************/
5488
5489
5490/**
5491 * Basic usage function for 'net rpc'
5492 * @param argc  Standard main() style argc
5493 * @param argv  Standard main() style argv.  Initial components are already
5494 *              stripped
5495 **/
5496
5497int net_rpc_usage(int argc, const char **argv)
5498{
5499	d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
5500	d_printf("  net rpc join \t\t\tto join a domain \n");
5501	d_printf("  net rpc oldjoin \t\t\tto join a domain created in server manager\n\n\n");
5502	d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
5503	d_printf("  net rpc user \t\t\tto add, delete and list users\n");
5504	d_printf("  net rpc password <username> [<password>] -Uadmin_username%%admin_pass\n");
5505	d_printf("  net rpc group \t\tto list groups\n");
5506	d_printf("  net rpc share \t\tto add, delete, list and migrate shares\n");
5507	d_printf("  net rpc printer \t\tto list and migrate printers\n");
5508	d_printf("  net rpc file \t\t\tto list open files\n");
5509	d_printf("  net rpc changetrustpw \tto change the trust account password\n");
5510	d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
5511	d_printf("  net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
5512	d_printf("  net rpc samdump \t\tdiplay an NT PDC's users, groups and other data\n");
5513	d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
5514	d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
5515	d_printf("  net rpc shutdown \t\tto shutdown a remote server\n");
5516	d_printf("  net rpc rights\t\tto manage privileges assigned to SIDs\n");
5517	d_printf("\n");
5518	d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
5519	d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
5520	d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
5521	d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
5522	d_printf("\t-c or --comment=<message>\ttext message to display on impending shutdown\n");
5523	return -1;
5524}
5525
5526
5527/**
5528 * Help function for 'net rpc'.  Calls command specific help if requested
5529 * or displays usage of net rpc
5530 * @param argc  Standard main() style argc
5531 * @param argv  Standard main() style argv.  Initial components are already
5532 *              stripped
5533 **/
5534
5535int net_rpc_help(int argc, const char **argv)
5536{
5537	struct functable func[] = {
5538		{"join", rpc_join_usage},
5539		{"user", rpc_user_usage},
5540		{"group", rpc_group_usage},
5541		{"share", rpc_share_usage},
5542		/*{"changetrustpw", rpc_changetrustpw_usage}, */
5543		{"trustdom", rpc_trustdom_usage},
5544		/*{"abortshutdown", rpc_shutdown_abort_usage},*/
5545		/*{"shutdown", rpc_shutdown_usage}, */
5546		{NULL, NULL}
5547	};
5548
5549	if (argc == 0) {
5550		net_rpc_usage(argc, argv);
5551		return -1;
5552	}
5553
5554	return (net_run_function(argc, argv, func, rpc_user_usage));
5555}
5556
5557
5558/**
5559 * 'net rpc' entrypoint.
5560 * @param argc  Standard main() style argc
5561 * @param argv  Standard main() style argv.  Initial components are already
5562 *              stripped
5563 **/
5564
5565int net_rpc(int argc, const char **argv)
5566{
5567	struct functable func[] = {
5568		{"info", net_rpc_info},
5569		{"join", net_rpc_join},
5570		{"oldjoin", net_rpc_oldjoin},
5571		{"testjoin", net_rpc_testjoin},
5572		{"user", net_rpc_user},
5573		{"password", rpc_user_password},
5574		{"group", net_rpc_group},
5575		{"share", net_rpc_share},
5576		{"file", net_rpc_file},
5577		{"printer", net_rpc_printer},
5578		{"changetrustpw", net_rpc_changetrustpw},
5579		{"trustdom", rpc_trustdom},
5580		{"abortshutdown", rpc_shutdown_abort},
5581		{"shutdown", rpc_shutdown},
5582		{"samdump", rpc_samdump},
5583		{"vampire", rpc_vampire},
5584		{"getsid", net_rpc_getsid},
5585		{"rights", net_rpc_rights},
5586		{"help", net_rpc_help},
5587		{NULL, NULL}
5588	};
5589	return net_run_function(argc, argv, func, net_rpc_usage);
5590}
5591