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