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