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