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