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