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