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