r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation
[samba.git] / source / utils / net_rpc.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
6    Copyright (C) 2004 Guenther Deschner (gd@samba.org)
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
21  
22 #include "includes.h"
23 #include "utils/net.h"
24
25 /**
26  * @file net_rpc.c
27  *
28  * @brief RPC based subcommands for the 'net' utility.
29  *
30  * This file should contain much of the functionality that used to
31  * be found in rpcclient, execpt that the commands should change 
32  * less often, and the fucntionality should be sane (the user is not 
33  * expected to know a rid/sid before they conduct an operation etc.)
34  *
35  * @todo Perhaps eventually these should be split out into a number
36  * of files, as this could get quite big.
37  **/
38
39
40 /* 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 = TALLOC_ARRAY(mem_ctx, 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 = SMB_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 = SMB_MALLOC_ARRAY(struct full_alias, 100);
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 = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
3057
3058                                 for (j = 0; j < alias.num_members; j++)
3059                                         sid_copy(&alias.members[j],
3060                                                  &members[j]);
3061                         }
3062
3063                         sid_copy(&alias.sid, domain_sid);
3064                         sid_append_rid(&alias.sid, groups[i].rid);
3065
3066                         push_alias(mem_ctx, &alias);
3067                 }
3068         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3069
3070         result = NT_STATUS_OK;
3071
3072  done:
3073         cli_samr_close(cli, mem_ctx, &domain_pol);
3074
3075         return result;
3076 }
3077
3078 /*
3079  * Dump server_aliases as names for debugging purposes.
3080  */
3081 static NTSTATUS
3082 rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name,
3083                    struct cli_state *cli, TALLOC_CTX *mem_ctx, 
3084                    int argc, const char **argv)
3085 {
3086         int i;
3087         NTSTATUS result;
3088         POLICY_HND lsa_pol;
3089
3090         result = cli_lsa_open_policy(cli, mem_ctx, True, 
3091                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
3092                                      &lsa_pol);
3093         if (!NT_STATUS_IS_OK(result))
3094                 return result;
3095
3096         for (i=0; i<num_server_aliases; i++) {
3097                 char **names;
3098                 char **domains;
3099                 uint32 *types;
3100                 int j;
3101
3102                 struct full_alias *alias = &server_aliases[i];
3103
3104                 result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol, 1,
3105                                              &alias->sid,
3106                                              &domains, &names, &types);
3107                 if (!NT_STATUS_IS_OK(result))
3108                         continue;
3109
3110                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
3111
3112                 if (alias->num_members == 0) {
3113                         DEBUG(1, ("\n"));
3114                         continue;
3115                 }
3116
3117                 result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol,
3118                                              alias->num_members,
3119                                              alias->members,
3120                                              &domains, &names, &types);
3121
3122                 if (!NT_STATUS_IS_OK(result) &&
3123                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
3124                         continue;
3125
3126                 for (j=0; j<alias->num_members; j++)
3127                         DEBUG(1, ("%s\\%s (%d); ",
3128                                   domains[j] ? domains[j] : "*unknown*", 
3129                                   names[j] ? names[j] : "*unknown*",types[j]));
3130                 DEBUG(1, ("\n"));
3131         }
3132
3133         cli_lsa_close(cli, mem_ctx, &lsa_pol);
3134
3135         return NT_STATUS_OK;
3136 }
3137
3138 /*
3139  * Fetch a list of all server aliases and their members into
3140  * server_aliases.
3141  */
3142 static NTSTATUS
3143 rpc_aliaslist_internals(const DOM_SID *domain_sid, const char *domain_name,
3144                         struct cli_state *cli, TALLOC_CTX *mem_ctx, 
3145                         int argc, const char **argv)
3146 {
3147         NTSTATUS result;
3148         POLICY_HND connect_pol;
3149         DOM_SID global_sid_Builtin;
3150
3151         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
3152                                   &connect_pol);
3153
3154         if (!NT_STATUS_IS_OK(result))
3155                 goto done;
3156         
3157         string_to_sid(&global_sid_Builtin, "S-1-5-32");
3158
3159         result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol,
3160                                           &global_sid_Builtin);
3161
3162         if (!NT_STATUS_IS_OK(result))
3163                 goto done;
3164         
3165         result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol,
3166                                           domain_sid);
3167
3168         cli_samr_close(cli, mem_ctx, &connect_pol);
3169  done:
3170         return result;
3171 }
3172
3173 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
3174 {
3175         DOM_SID global_sid_World;
3176         DOM_SID global_sid_Network;
3177         DOM_SID global_sid_Authenticated_Users;
3178
3179         string_to_sid(&global_sid_World, "S-1-1-0");
3180         string_to_sid(&global_sid_Network, "S-1-5-2");
3181         string_to_sid(&global_sid_Authenticated_Users, "S-1-5-11");
3182
3183         token->num_sids = 4;
3184
3185         token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4);
3186
3187         token->user_sids[0] = *user_sid;
3188         sid_copy(&token->user_sids[1], &global_sid_World);
3189         sid_copy(&token->user_sids[2], &global_sid_Network);
3190         sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
3191 }
3192
3193 static void free_user_token(NT_USER_TOKEN *token)
3194 {
3195         SAFE_FREE(token->user_sids);
3196 }
3197
3198 static BOOL is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
3199 {
3200         int i;
3201
3202         for (i=0; i<token->num_sids; i++) {
3203                 if (sid_compare(sid, &token->user_sids[i]) == 0)
3204                         return True;
3205         }
3206         return False;
3207 }
3208
3209 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
3210 {
3211         if (is_sid_in_token(token, sid))
3212                 return;
3213
3214         token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
3215
3216         sid_copy(&token->user_sids[token->num_sids], sid);
3217
3218         token->num_sids += 1;
3219 }
3220
3221 struct user_token {
3222         fstring name;
3223         NT_USER_TOKEN token;
3224 };
3225
3226 static void dump_user_token(struct user_token *token)
3227 {
3228         int i;
3229
3230         d_printf("%s\n", token->name);
3231
3232         for (i=0; i<token->token.num_sids; i++) {
3233                 d_printf(" %s\n", sid_string_static(&token->token.user_sids[i]));
3234         }
3235 }
3236
3237 static BOOL is_alias_member(DOM_SID *sid, struct full_alias *alias)
3238 {
3239         int i;
3240
3241         for (i=0; i<alias->num_members; i++) {
3242                 if (sid_compare(sid, &alias->members[i]) == 0)
3243                         return True;
3244         }
3245
3246         return False;
3247 }
3248
3249 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
3250 {
3251         int i;
3252
3253         for (i=0; i<num_server_aliases; i++) {
3254                 if (is_alias_member(&sid, &server_aliases[i]))
3255                         add_sid_to_token(token, &server_aliases[i].sid);
3256         }
3257 }
3258
3259 /*
3260  * We got a user token with all the SIDs we can know about without asking the
3261  * server directly. These are the user and domain group sids. All of these can
3262  * be members of aliases. So scan the list of aliases for each of the SIDs and
3263  * add them to the token.
3264  */
3265
3266 static void collect_alias_memberships(NT_USER_TOKEN *token)
3267 {
3268         int num_global_sids = token->num_sids;
3269         int i;
3270
3271         for (i=0; i<num_global_sids; i++) {
3272                 collect_sid_memberships(token, token->user_sids[i]);
3273         }
3274 }
3275
3276 static BOOL get_user_sids(const char *domain, const char *user,
3277                           NT_USER_TOKEN *token)
3278 {
3279         struct winbindd_request request;
3280         struct winbindd_response response;
3281         fstring full_name;
3282         NSS_STATUS result;
3283
3284         DOM_SID user_sid;
3285
3286         int i;
3287
3288         fstr_sprintf(full_name, "%s%c%s",
3289                      domain, *lp_winbind_separator(), user);
3290
3291         /* First let's find out the user sid */
3292
3293         ZERO_STRUCT(request);
3294         ZERO_STRUCT(response);
3295
3296         fstrcpy(request.data.name.dom_name, domain);
3297         fstrcpy(request.data.name.name, user);
3298
3299         result = winbindd_request(WINBINDD_LOOKUPNAME, &request, &response);
3300
3301         if (result != NSS_STATUS_SUCCESS) {
3302                 DEBUG(1, ("winbind could not find %s\n", full_name));
3303                 return False;
3304         }
3305
3306         if (response.data.sid.type != SID_NAME_USER) {
3307                 DEBUG(1, ("%s is not a user\n", full_name));
3308                 return False;
3309         }
3310
3311         string_to_sid(&user_sid, response.data.sid.sid);
3312
3313         init_user_token(token, &user_sid);
3314
3315         /* And now the groups winbind knows about */
3316
3317         ZERO_STRUCT(response);
3318
3319         fstrcpy(request.data.username, full_name);
3320
3321         result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
3322
3323         if (result != NSS_STATUS_SUCCESS) {
3324                 DEBUG(1, ("winbind could not get groups of %s\n", full_name));
3325                 return False;
3326         }
3327
3328         for (i = 0; i < response.data.num_entries; i++) {
3329                 gid_t gid = ((gid_t *)response.extra_data)[i];
3330                 DOM_SID sid;
3331
3332                 struct winbindd_request sidrequest;
3333                 struct winbindd_response sidresponse;
3334
3335                 ZERO_STRUCT(sidrequest);
3336                 ZERO_STRUCT(sidresponse);
3337
3338                 sidrequest.data.gid = gid;
3339
3340                 result = winbindd_request(WINBINDD_GID_TO_SID,
3341                                           &sidrequest, &sidresponse);
3342
3343                 if (result != NSS_STATUS_SUCCESS) {
3344                         DEBUG(1, ("winbind could not find SID of gid %d\n",
3345                                   gid));
3346                         return False;
3347                 }
3348
3349                 DEBUG(3, (" %s\n", sidresponse.data.sid.sid));
3350
3351                 string_to_sid(&sid, sidresponse.data.sid.sid);
3352                 add_sid_to_token(token, &sid);
3353         }
3354
3355         SAFE_FREE(response.extra_data);
3356
3357         return True;
3358 }
3359         
3360 /**
3361  * Get a list of all user tokens we want to look at
3362  **/
3363 static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens)
3364 {
3365         struct winbindd_request request;
3366         struct winbindd_response response;
3367         const char *extra_data;
3368         fstring name;
3369         int i;
3370         struct user_token *result;
3371
3372         /* Send request to winbind daemon */
3373
3374         ZERO_STRUCT(request);
3375         ZERO_STRUCT(response);
3376         
3377         if (winbindd_request(WINBINDD_LIST_USERS, &request, &response) !=
3378             NSS_STATUS_SUCCESS)
3379                 return False;
3380
3381         /* Look through extra data */
3382
3383         if (!response.extra_data)
3384                 return False;
3385
3386         extra_data = (const char *)response.extra_data;
3387         *num_tokens = 0;
3388
3389         while(next_token(&extra_data, name, ",", sizeof(fstring))) {
3390                 *num_tokens += 1;
3391         }
3392
3393         result = SMB_MALLOC_ARRAY(struct user_token, *num_tokens);
3394
3395         if (result == NULL) {
3396                 DEBUG(1, ("Could not malloc sid array\n"));
3397                 return False;
3398         }
3399
3400         extra_data = (const char *)response.extra_data;
3401         i=0;
3402
3403         while(next_token(&extra_data, name, ",", sizeof(fstring))) {
3404
3405                 fstring domain, user;
3406                 char *p;
3407
3408                 fstrcpy(result[i].name, name);
3409
3410                 p = strchr(name, *lp_winbind_separator());
3411
3412                 DEBUG(3, ("%s\n", name));
3413
3414                 if (p == NULL)
3415                         continue;
3416
3417                 *p++ = '\0';
3418
3419                 fstrcpy(domain, name);
3420                 strupper_m(domain);
3421                 fstrcpy(user, p);
3422
3423                 get_user_sids(domain, user, &(result[i].token));
3424                 i+=1;
3425         }
3426         
3427         SAFE_FREE(response.extra_data);
3428
3429         *user_tokens = result;
3430
3431         return True;
3432 }
3433
3434 static BOOL get_user_tokens_from_file(FILE *f,
3435                                       int *num_tokens,
3436                                       struct user_token **tokens)
3437 {
3438         struct user_token *token = NULL;
3439
3440         while (!feof(f)) {
3441                 fstring line;
3442
3443                 if (fgets(line, sizeof(line)-1, f) == NULL) {
3444                         return True;
3445                 }
3446
3447                 if (line[strlen(line)-1] == '\n')
3448                         line[strlen(line)-1] = '\0';
3449
3450                 if (line[0] == ' ') {
3451                         /* We have a SID */
3452
3453                         DOM_SID sid;
3454                         string_to_sid(&sid, &line[1]);
3455
3456                         if (token == NULL) {
3457                                 DEBUG(0, ("File does not begin with username"));
3458                                 return False;
3459                         }
3460
3461                         add_sid_to_token(&token->token, &sid);
3462                         continue;
3463                 }
3464
3465                 /* And a new user... */
3466
3467                 *num_tokens += 1;
3468                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
3469                 if (*tokens == NULL) {
3470                         DEBUG(0, ("Could not realloc tokens\n"));
3471                         return False;
3472                 }
3473
3474                 token = &((*tokens)[*num_tokens-1]);
3475
3476                 fstrcpy(token->name, line);
3477                 token->token.num_sids = 0;
3478                 token->token.user_sids = NULL;
3479                 continue;
3480         }
3481         
3482         return False;
3483 }
3484
3485
3486 /*
3487  * Show the list of all users that have access to a share
3488  */
3489
3490 static void show_userlist(struct cli_state *cli,
3491                           TALLOC_CTX *mem_ctx, const char *netname,
3492                           int num_tokens, struct user_token *tokens)
3493 {
3494         int fnum;
3495         SEC_DESC *share_sd = NULL;
3496         SEC_DESC *root_sd = NULL;
3497         int i;
3498         SRV_SHARE_INFO info;
3499         WERROR result;
3500         uint16 cnum;
3501
3502         result = cli_srvsvc_net_share_get_info(cli, mem_ctx, netname,
3503                                                502, &info);
3504
3505         if (!W_ERROR_IS_OK(result)) {
3506                 DEBUG(1, ("Coult not query secdesc for share %s\n",
3507                           netname));
3508                 return;
3509         }
3510
3511         share_sd = info.share.info502.info_502_str.sd;
3512         if (share_sd == NULL) {
3513                 DEBUG(1, ("Got no secdesc for share %s\n",
3514                           netname));
3515         }
3516
3517         cnum = cli->cnum;
3518
3519         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
3520                 return;
3521         }
3522
3523         fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
3524
3525         if (fnum != -1) {
3526                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
3527         }
3528
3529         for (i=0; i<num_tokens; i++) {
3530                 uint32 acc_granted;
3531                 NTSTATUS status;
3532
3533                 if (share_sd != NULL) {
3534                         if (!se_access_check(share_sd, &tokens[i].token,
3535                                              1, &acc_granted, &status)) {
3536                                 DEBUG(1, ("Could not check share_sd for "
3537                                           "user %s\n",
3538                                           tokens[i].name));
3539                                 continue;
3540                         }
3541
3542                         if (!NT_STATUS_IS_OK(status))
3543                                 continue;
3544                 }
3545
3546                 if (root_sd == NULL) {
3547                         d_printf(" %s\n", tokens[i].name);
3548                         continue;
3549                 }
3550
3551                 if (!se_access_check(root_sd, &tokens[i].token,
3552                                      1, &acc_granted, &status)) {
3553                         DEBUG(1, ("Could not check root_sd for user %s\n",
3554                                   tokens[i].name));
3555                         continue;
3556                 }
3557
3558                 if (!NT_STATUS_IS_OK(status))
3559                         continue;
3560
3561                 d_printf(" %s\n", tokens[i].name);
3562         }
3563
3564         if (fnum != -1)
3565                 cli_close(cli, fnum);
3566         cli_tdis(cli);
3567         cli->cnum = cnum;
3568         
3569         return;
3570 }
3571
3572 struct share_list {
3573         int num_shares;
3574         char **shares;
3575 };
3576
3577 static void collect_share(const char *name, uint32 m,
3578                           const char *comment, void *state)
3579 {
3580         struct share_list *share_list = (struct share_list *)state;
3581
3582         if (m != STYPE_DISKTREE)
3583                 return;
3584
3585         share_list->num_shares += 1;
3586         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
3587         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
3588 }
3589
3590 static void rpc_share_userlist_usage(void)
3591 {
3592         return;
3593 }
3594         
3595 /** 
3596  * List shares on a remote RPC server, including the security descriptors
3597  *
3598  * All parameters are provided by the run_rpc_command function, except for
3599  * argc, argv which are passes through. 
3600  *
3601  * @param domain_sid The domain sid acquired from the remote server
3602  * @param cli A cli_state connected to the server.
3603  * @param mem_ctx Talloc context, destoyed on completion of the function.
3604  * @param argc  Standard main() style argc
3605  * @param argv  Standard main() style argv.  Initial components are already
3606  *              stripped
3607  *
3608  * @return Normal NTSTATUS return.
3609  **/
3610
3611 static NTSTATUS 
3612 rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
3613                                  const char *domain_name,
3614                                  struct cli_state *cli,
3615                                  TALLOC_CTX *mem_ctx,
3616                                  int argc, const char **argv)
3617 {
3618         int ret;
3619         BOOL r;
3620         ENUM_HND hnd;
3621         uint32 i;
3622         FILE *f;
3623
3624         struct user_token *tokens = NULL;
3625         int num_tokens = 0;
3626
3627         struct share_list share_list;
3628
3629         if (argc > 1) {
3630                 rpc_share_userlist_usage();
3631                 return NT_STATUS_UNSUCCESSFUL;
3632         }
3633
3634         if (argc == 0) {
3635                 f = stdin;
3636         } else {
3637                 f = fopen(argv[0], "r");
3638         }
3639
3640         if (f == NULL) {
3641                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
3642                 return NT_STATUS_UNSUCCESSFUL;
3643         }
3644
3645         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
3646
3647         if (f != stdin)
3648                 fclose(f);
3649
3650         if (!r) {
3651                 DEBUG(0, ("Could not read users from file\n"));
3652                 return NT_STATUS_UNSUCCESSFUL;
3653         }
3654
3655         for (i=0; i<num_tokens; i++)
3656                 collect_alias_memberships(&tokens[i].token);
3657
3658         init_enum_hnd(&hnd, 0);
3659
3660         share_list.num_shares = 0;
3661         share_list.shares = NULL;
3662
3663         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
3664
3665         if (ret == -1) {
3666                 DEBUG(0, ("Error returning browse list: %s\n",
3667                           cli_errstr(cli)));
3668                 goto done;
3669         }
3670
3671         for (i = 0; i < share_list.num_shares; i++) {
3672                 char *netname = share_list.shares[i];
3673
3674                 if (netname[strlen(netname)-1] == '$')
3675                         continue;
3676
3677                 d_printf("%s\n", netname);
3678
3679                 show_userlist(cli, mem_ctx, netname,
3680                               num_tokens, tokens);
3681         }
3682  done:
3683         for (i=0; i<num_tokens; i++) {
3684                 free_user_token(&tokens[i].token);
3685         }
3686         SAFE_FREE(tokens);
3687         SAFE_FREE(share_list.shares);
3688
3689         return NT_STATUS_OK;
3690 }
3691
3692 static int
3693 rpc_share_allowedusers(int argc, const char **argv)
3694 {
3695         int result;
3696
3697         result = run_rpc_command(NULL, PI_SAMR, 0,
3698                                  rpc_aliaslist_internals,
3699                                  argc, argv);
3700         if (result != 0)
3701                 return result;
3702
3703         result = run_rpc_command(NULL, PI_LSARPC, 0,
3704                                  rpc_aliaslist_dump,
3705                                  argc, argv);
3706         if (result != 0)
3707                 return result;
3708
3709         return run_rpc_command(NULL, PI_SRVSVC, 0,
3710                                rpc_share_allowedusers_internals,
3711                                argc, argv);
3712 }
3713
3714 int net_usersidlist(int argc, const char **argv)
3715 {
3716         int num_tokens = 0;
3717         struct user_token *tokens = NULL;
3718         int i;
3719
3720         if (argc != 0) {
3721                 net_usersidlist_usage(argc, argv);
3722                 return 0;
3723         }
3724
3725         if (!get_user_tokens(&num_tokens, &tokens)) {
3726                 DEBUG(0, ("Could not get the user/sid list\n"));
3727                 return 0;
3728         }
3729
3730         for (i=0; i<num_tokens; i++) {
3731                 dump_user_token(&tokens[i]);
3732                 free_user_token(&tokens[i].token);
3733         }
3734
3735         SAFE_FREE(tokens);
3736         return 1;
3737 }
3738
3739 int net_usersidlist_usage(int argc, const char **argv)
3740 {
3741         d_printf("net usersidlist\n"
3742                  "\tprints out a list of all users the running winbind knows\n"
3743                  "\tabout, together with all their SIDs. This is used as\n"
3744                  "\tinput to the 'net rpc share allowedusers' command.\n\n");
3745
3746         net_common_flags_usage(argc, argv);
3747         return -1;
3748 }
3749
3750 /** 
3751  * 'net rpc share' entrypoint.
3752  * @param argc  Standard main() style argc
3753  * @param argv  Standard main() style argv.  Initial components are already
3754  *              stripped
3755  **/
3756
3757 int net_rpc_share(int argc, const char **argv) 
3758 {
3759         struct functable func[] = {
3760                 {"add", rpc_share_add},
3761                 {"delete", rpc_share_delete},
3762                 {"allowedusers", rpc_share_allowedusers},
3763                 {"migrate", rpc_share_migrate},
3764                 {NULL, NULL}
3765         };
3766
3767         if (argc == 0)
3768                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
3769                                        rpc_share_list_internals,
3770                                        argc, argv);
3771
3772         return net_run_function(argc, argv, func, rpc_share_usage);
3773 }
3774
3775 /****************************************************************************/
3776
3777 static int rpc_file_usage(int argc, const char **argv)
3778 {
3779         return net_help_file(argc, argv);
3780 }
3781
3782 /** 
3783  * Close a file on a remote RPC server
3784  *
3785  * All parameters are provided by the run_rpc_command function, except for
3786  * argc, argv which are passes through. 
3787  *
3788  * @param domain_sid The domain sid acquired from the remote server
3789  * @param cli A cli_state connected to the server.
3790  * @param mem_ctx Talloc context, destoyed on completion of the function.
3791  * @param argc  Standard main() style argc
3792  * @param argv  Standard main() style argv.  Initial components are already
3793  *              stripped
3794  *
3795  * @return Normal NTSTATUS return.
3796  **/
3797 static NTSTATUS 
3798 rpc_file_close_internals(const DOM_SID *domain_sid, const char *domain_name, 
3799                          struct cli_state *cli,
3800                          TALLOC_CTX *mem_ctx, int argc, const char **argv)
3801 {
3802         WERROR result;
3803         result = cli_srvsvc_net_file_close(cli, mem_ctx, atoi(argv[0]));
3804         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3805 }
3806
3807 /** 
3808  * Close a file on a remote RPC server
3809  *
3810  * @param argc  Standard main() style argc
3811  * @param argv  Standard main() style argv.  Initial components are already
3812  *              stripped
3813  *
3814  * @return A shell status integer (0 for success)
3815  **/
3816 static int rpc_file_close(int argc, const char **argv)
3817 {
3818         if (argc < 1) {
3819                 DEBUG(1, ("No fileid given on close\n"));
3820                 return(rpc_file_usage(argc, argv));
3821         }
3822
3823         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3824                                rpc_file_close_internals,
3825                                argc, argv);
3826 }
3827
3828 /** 
3829  * Formatted print of open file info 
3830  *
3831  * @param info3  FILE_INFO_3 contents
3832  * @param str3   strings for FILE_INFO_3
3833  **/
3834
3835 static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
3836 {
3837         fstring user = "", path = "";
3838
3839         rpcstr_pull_unistr2_fstring(user, &str3->uni_user_name);
3840         rpcstr_pull_unistr2_fstring(path, &str3->uni_path_name);
3841
3842         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
3843                  info3->id, user, info3->perms, info3->num_locks, path);
3844 }
3845
3846 /** 
3847  * List open files on a remote RPC server
3848  *
3849  * All parameters are provided by the run_rpc_command function, except for
3850  * argc, argv which are passes through. 
3851  *
3852  * @param domain_sid The domain sid acquired from the remote server
3853  * @param cli A cli_state connected to the server.
3854  * @param mem_ctx Talloc context, destoyed on completion of the function.
3855  * @param argc  Standard main() style argc
3856  * @param argv  Standard main() style argv.  Initial components are already
3857  *              stripped
3858  *
3859  * @return Normal NTSTATUS return.
3860  **/
3861
3862 static NTSTATUS 
3863 rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
3864                         struct cli_state *cli,
3865                         TALLOC_CTX *mem_ctx, int argc, const char **argv)
3866 {
3867         SRV_FILE_INFO_CTR ctr;
3868         WERROR result;
3869         ENUM_HND hnd;
3870         uint32 preferred_len = 0xffffffff, i;
3871         const char *username=NULL;
3872
3873         init_enum_hnd(&hnd, 0);
3874
3875         /* if argc > 0, must be user command */
3876         if (argc > 0)
3877                 username = smb_xstrdup(argv[0]);
3878                 
3879         result = cli_srvsvc_net_file_enum(
3880                 cli, mem_ctx, 3, username, &ctr, preferred_len, &hnd);
3881
3882         if (!W_ERROR_IS_OK(result))
3883                 goto done;
3884
3885         /* Display results */
3886
3887         d_printf(
3888                  "\nEnumerating open files on remote server:\n\n"\
3889                  "\nFileId  Opened by            Perms  Locks  Path"\
3890                  "\n------  ---------            -----  -----  ---- \n");
3891         for (i = 0; i < ctr.num_entries; i++)
3892                 display_file_info_3(&ctr.file.info3[i].info_3, 
3893                                     &ctr.file.info3[i].info_3_str);
3894  done:
3895         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3896 }
3897
3898
3899 /** 
3900  * List files for a user on a remote RPC server
3901  *
3902  * @param argc  Standard main() style argc
3903  * @param argv  Standard main() style argv.  Initial components are already
3904  *              stripped
3905  *
3906  * @return A shell status integer (0 for success)
3907  **/
3908 static int rpc_file_user(int argc, const char **argv)
3909 {
3910         if (argc < 1) {
3911                 DEBUG(1, ("No username given\n"));
3912                 return(rpc_file_usage(argc, argv));
3913         }
3914
3915         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3916                                rpc_file_list_internals,
3917                                argc, argv);
3918 }
3919
3920
3921 /** 
3922  * 'net rpc file' entrypoint.
3923  * @param argc  Standard main() style argc
3924  * @param argv  Standard main() style argv.  Initial components are already
3925  *              stripped
3926  **/
3927
3928 int net_rpc_file(int argc, const char **argv) 
3929 {
3930         struct functable func[] = {
3931                 {"close", rpc_file_close},
3932                 {"user", rpc_file_user},
3933 #if 0
3934                 {"info", rpc_file_info},
3935 #endif
3936                 {NULL, NULL}
3937         };
3938
3939         if (argc == 0)
3940                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
3941                                        rpc_file_list_internals,
3942                                        argc, argv);
3943
3944         return net_run_function(argc, argv, func, rpc_file_usage);
3945 }
3946
3947 /****************************************************************************/
3948
3949
3950
3951 /** 
3952  * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
3953  *
3954  * All parameters are provided by the run_rpc_command function, except for
3955  * argc, argv which are passed through. 
3956  *
3957  * @param domain_sid The domain sid aquired from the remote server
3958  * @param cli A cli_state connected to the server.
3959  * @param mem_ctx Talloc context, destoyed on compleation of the function.
3960  * @param argc  Standard main() style argc
3961  * @param argv  Standard main() style argv.  Initial components are already
3962  *              stripped
3963  *
3964  * @return Normal NTSTATUS return.
3965  **/
3966
3967 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, 
3968                                              const char *domain_name, 
3969                                              struct cli_state *cli, 
3970                                              TALLOC_CTX *mem_ctx, 
3971                                              int argc, const char **argv) 
3972 {
3973         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
3974         
3975         result = cli_shutdown_abort(cli, mem_ctx);
3976         
3977         if (NT_STATUS_IS_OK(result)) {
3978                 d_printf("\nShutdown successfully aborted\n");
3979                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
3980         } else
3981                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
3982         
3983         return result;
3984 }
3985
3986
3987 /** 
3988  * ABORT the shutdown of a remote RPC Server,  over winreg pipe
3989  *
3990  * All parameters are provided by the run_rpc_command function, except for
3991  * argc, argv which are passed through. 
3992  *
3993  * @param domain_sid The domain sid aquired from the remote server
3994  * @param cli A cli_state connected to the server.
3995  * @param mem_ctx Talloc context, destoyed on compleation of the function.
3996  * @param argc  Standard main() style argc
3997  * @param argv  Standard main() style argv.  Initial components are already
3998  *              stripped
3999  *
4000  * @return Normal NTSTATUS return.
4001  **/
4002
4003 static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid, 
4004                                                  const char *domain_name, 
4005                                                  struct cli_state *cli, 
4006                                                  TALLOC_CTX *mem_ctx, 
4007                                                  int argc, const char **argv) 
4008 {
4009         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4010         
4011         result = cli_reg_abort_shutdown(cli, mem_ctx);
4012         
4013         if (NT_STATUS_IS_OK(result)) {
4014                 d_printf("\nShutdown successfully aborted\n");
4015                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
4016         } else
4017                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
4018         
4019         return result;
4020 }
4021
4022 /** 
4023  * ABORT the Shut down of a remote RPC server
4024  *
4025  * @param argc  Standard main() style argc
4026  * @param argv  Standard main() style argv.  Initial components are already
4027  *              stripped
4028  *
4029  * @return A shell status integer (0 for success)
4030  **/
4031
4032 static int rpc_shutdown_abort(int argc, const char **argv) 
4033 {
4034         int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0, 
4035                                  rpc_shutdown_abort_internals,
4036                                  argc, argv);
4037
4038         if (rc == 0)
4039                 return rc;
4040
4041         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
4042
4043         return run_rpc_command(NULL, PI_WINREG, 0, 
4044                                rpc_reg_shutdown_abort_internals,
4045                                argc, argv);
4046 }
4047
4048 /** 
4049  * Shut down a remote RPC Server via initshutdown pipe
4050  *
4051  * All parameters are provided by the run_rpc_command function, except for
4052  * argc, argv which are passes through. 
4053  *
4054  * @param domain_sid The domain sid aquired from the remote server
4055  * @param cli A cli_state connected to the server.
4056  * @param mem_ctx Talloc context, destoyed on compleation of the function.
4057  * @param argc  Standard main() style argc
4058  * @param argc  Standard main() style argv.  Initial components are already
4059  *              stripped
4060  *
4061  * @return Normal NTSTATUS return.
4062  **/
4063
4064 static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid, 
4065                                             const char *domain_name, 
4066                                             struct cli_state *cli, 
4067                                             TALLOC_CTX *mem_ctx, 
4068                                             int argc, const char **argv) 
4069 {
4070         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4071         const char *msg = "This machine will be shutdown shortly";
4072         uint32 timeout = 20;
4073
4074         if (opt_comment) {
4075                 msg = opt_comment;
4076         }
4077         if (opt_timeout) {
4078                 timeout = opt_timeout;
4079         }
4080
4081         /* create an entry */
4082         result = cli_shutdown_init(cli, mem_ctx, msg, timeout, opt_reboot, 
4083                                    opt_force);
4084
4085         if (NT_STATUS_IS_OK(result)) {
4086                 d_printf("\nShutdown of remote machine succeeded\n");
4087                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
4088         } else
4089                 DEBUG(0,("Shutdown of remote machine failed!\n"));
4090
4091         return result;
4092 }
4093
4094 /** 
4095  * Shut down a remote RPC Server via winreg pipe
4096  *
4097  * All parameters are provided by the run_rpc_command function, except for
4098  * argc, argv which are passes through. 
4099  *
4100  * @param domain_sid The domain sid aquired from the remote server
4101  * @param cli A cli_state connected to the server.
4102  * @param mem_ctx Talloc context, destoyed on compleation of the function.
4103  * @param argc  Standard main() style argc
4104  * @param argc  Standard main() style argv.  Initial components are already
4105  *              stripped
4106  *
4107  * @return Normal NTSTATUS return.
4108  **/
4109
4110 static NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid, 
4111                                            const char *domain_name, 
4112                                            struct cli_state *cli, 
4113                                            TALLOC_CTX *mem_ctx, 
4114                                            int argc, const char **argv) 
4115 {
4116         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4117         const char *msg = "This machine will be shutdown shortly";
4118         uint32 timeout = 20;
4119 #if 0
4120         poptContext pc;
4121         int rc;
4122
4123         struct poptOption long_options[] = {
4124                 {"message",    'm', POPT_ARG_STRING, &msg},
4125                 {"timeout",    't', POPT_ARG_INT,    &timeout},
4126                 {"reboot",     'r', POPT_ARG_NONE,   &reboot},
4127                 {"force",      'f', POPT_ARG_NONE,   &force},
4128                 { 0, 0, 0, 0}
4129         };
4130
4131         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
4132                             POPT_CONTEXT_KEEP_FIRST);
4133
4134         rc = poptGetNextOpt(pc);
4135         
4136         if (rc < -1) {
4137                 /* an error occurred during option processing */
4138                 DEBUG(0, ("%s: %s\n",
4139                           poptBadOption(pc, POPT_BADOPTION_NOALIAS),
4140                           poptStrerror(rc)));
4141                 return NT_STATUS_INVALID_PARAMETER;
4142         }
4143 #endif
4144         if (opt_comment) {
4145                 msg = opt_comment;
4146         }
4147         if (opt_timeout) {
4148                 timeout = opt_timeout;
4149         }
4150
4151         /* create an entry */
4152         result = cli_reg_shutdown(cli, mem_ctx, msg, timeout, opt_reboot, opt_force);
4153
4154         if (NT_STATUS_IS_OK(result)) {
4155                 d_printf("\nShutdown of remote machine succeeded\n");
4156                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
4157         }
4158         else
4159                 DEBUG(0,("Shutdown of remote machine failed!\n"));
4160
4161         return result;
4162 }
4163
4164 /** 
4165  * Shut down a remote RPC server
4166  *
4167  * @param argc  Standard main() style argc
4168  * @param argc  Standard main() style argv.  Initial components are already
4169  *              stripped
4170  *
4171  * @return A shell status integer (0 for success)
4172  **/
4173
4174 static int rpc_shutdown(int argc, const char **argv) 
4175 {
4176         int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0, 
4177                                  rpc_init_shutdown_internals,
4178                                  argc, argv);
4179         if (rc == 0)
4180                 return rc;
4181
4182         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
4183
4184         return run_rpc_command(NULL, PI_WINREG, 0, rpc_reg_shutdown_internals,
4185                                        argc, argv);
4186 }
4187
4188 /***************************************************************************
4189   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
4190   
4191  ***************************************************************************/
4192
4193 /**
4194  * Add interdomain trust account to the RPC server.
4195  * All parameters (except for argc and argv) are passed by run_rpc_command
4196  * function.
4197  *
4198  * @param domain_sid The domain sid acquired from the server
4199  * @param cli A cli_state connected to the server.
4200  * @param mem_ctx Talloc context, destoyed on completion of the function.
4201  * @param argc  Standard main() style argc
4202  * @param argc  Standard main() style argv.  Initial components are already
4203  *              stripped
4204  *
4205  * @return normal NTSTATUS return code
4206  */
4207
4208 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, 
4209                                            const char *domain_name, 
4210                                            struct cli_state *cli, TALLOC_CTX *mem_ctx, 
4211                                            int argc, const char **argv) {
4212
4213         POLICY_HND connect_pol, domain_pol, user_pol;
4214         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4215         char *acct_name;
4216         uint16 acb_info;
4217         uint32 unknown, user_rid;
4218
4219         if (argc != 2) {
4220                 d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
4221                 return NT_STATUS_INVALID_PARAMETER;
4222         }
4223
4224         /* 
4225          * Make valid trusting domain account (ie. uppercased and with '$' appended)
4226          */
4227          
4228         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
4229                 return NT_STATUS_NO_MEMORY;
4230         }
4231
4232         strupper_m(acct_name);
4233
4234         /* Get samr policy handle */
4235         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
4236                                   &connect_pol);
4237         if (!NT_STATUS_IS_OK(result)) {
4238                 goto done;
4239         }
4240         
4241         /* Get domain policy handle */
4242         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
4243                                       MAXIMUM_ALLOWED_ACCESS,
4244                                       domain_sid, &domain_pol);
4245         if (!NT_STATUS_IS_OK(result)) {
4246                 goto done;
4247         }
4248
4249         /* Create trusting domain's account */
4250         acb_info = ACB_DOMTRUST;
4251         unknown = 0xe00500b0; /* No idea what this is - a permission mask?
4252                                  mimir: yes, most probably it is */
4253
4254         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
4255                                           acct_name, acb_info, unknown,
4256                                           &user_pol, &user_rid);
4257         if (!NT_STATUS_IS_OK(result)) {
4258                 goto done;
4259         }
4260
4261         {
4262                 SAM_USERINFO_CTR ctr;
4263                 SAM_USER_INFO_24 p24;
4264                 uchar pwbuf[516];
4265
4266                 encode_pw_buffer((char *)pwbuf, argv[1], STR_UNICODE);
4267
4268                 ZERO_STRUCT(ctr);
4269                 ZERO_STRUCT(p24);
4270
4271                 init_sam_user_info24(&p24, (char *)pwbuf, 24);
4272
4273                 ctr.switch_value = 24;
4274                 ctr.info.id24 = &p24;
4275
4276                 result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24,
4277                                                &cli->user_session_key, &ctr);
4278
4279                 if (!NT_STATUS_IS_OK(result)) {
4280                         DEBUG(0,("Could not set trust account password: %s\n",
4281                                  nt_errstr(result)));
4282                         goto done;
4283                 }
4284         }
4285
4286  done:
4287         SAFE_FREE(acct_name);
4288         return result;
4289 }
4290
4291 /**
4292  * Create interdomain trust account for a remote domain.
4293  *
4294  * @param argc standard argc
4295  * @param argv standard argv without initial components
4296  *
4297  * @return Integer status (0 means success)
4298  **/
4299
4300 static int rpc_trustdom_add(int argc, const char **argv)
4301 {
4302         if (argc > 0) {
4303                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
4304                                        argc, argv);
4305         } else {
4306                 d_printf("Usage: net rpc trustdom add <domain>\n");
4307                 return -1;
4308         }
4309 }
4310
4311
4312 /**
4313  * Delete interdomain trust account for a remote domain.
4314  *
4315  * @param argc standard argc
4316  * @param argv standard argv without initial components
4317  *
4318  * @return Integer status (0 means success)
4319  **/
4320  
4321 static int rpc_trustdom_del(int argc, const char **argv)
4322 {
4323         d_printf("Sorry, not yet implemented.\n");
4324         d_printf("Use 'smbpasswd -x -i' instead.\n");
4325         return -1;
4326 }
4327
4328  
4329 /**
4330  * Establish trust relationship to a trusting domain.
4331  * Interdomain account must already be created on remote PDC.
4332  *
4333  * @param argc standard argc
4334  * @param argv standard argv without initial components
4335  *
4336  * @return Integer status (0 means success)
4337  **/
4338
4339 static int rpc_trustdom_establish(int argc, const char **argv)
4340 {
4341         struct cli_state *cli;
4342         struct in_addr server_ip;
4343         POLICY_HND connect_hnd;
4344         TALLOC_CTX *mem_ctx;
4345         NTSTATUS nt_status;
4346         DOM_SID *domain_sid;
4347         WKS_INFO_100 wks_info;
4348         
4349         char* domain_name;
4350         char* domain_name_pol;
4351         char* acct_name;
4352         fstring pdc_name;
4353
4354         /*
4355          * Connect to \\server\ipc$ as 'our domain' account with password
4356          */
4357
4358         if (argc != 1) {
4359                 d_printf("Usage: net rpc trustdom establish <domain_name>\n");
4360                 return -1;
4361         }
4362
4363         domain_name = smb_xstrdup(argv[0]);
4364         strupper_m(domain_name);
4365
4366         /* account name used at first is our domain's name with '$' */
4367         asprintf(&acct_name, "%s$", lp_workgroup());
4368         strupper_m(acct_name);
4369         
4370         /*
4371          * opt_workgroup will be used by connection functions further,
4372          * hence it should be set to remote domain name instead of ours
4373          */
4374         if (opt_workgroup) {
4375                 opt_workgroup = smb_xstrdup(domain_name);
4376         };
4377         
4378         opt_user_name = acct_name;
4379
4380         /* find the domain controller */
4381         if (!net_find_pdc(&server_ip, pdc_name, domain_name)) {
4382                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
4383                 return -1;
4384         }
4385
4386         /* connect to ipc$ as username/password */
4387         nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
4388         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
4389
4390                 /* Is it trusting domain account for sure ? */
4391                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
4392                         nt_errstr(nt_status)));
4393                 return -1;
4394         }
4395         
4396         /*
4397          * Connect to \\server\ipc$ again (this time anonymously)
4398          */
4399         
4400         nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
4401         
4402         if (NT_STATUS_IS_ERR(nt_status)) {
4403                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
4404                         domain_name, nt_errstr(nt_status)));
4405         }
4406
4407         /*
4408          * Use NetServerEnum2 to make sure we're talking to a proper server
4409          */
4410          
4411         if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
4412                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
4413                          for domain %s\n", domain_name));
4414         }
4415          
4416         /*
4417          * Call WksQueryInfo to check remote server's capabilities
4418          * note: It is now used only to get unicode domain name
4419          */
4420         
4421         if (!cli_nt_session_open(cli, PI_WKSSVC)) {
4422                 DEBUG(0, ("Couldn't not initialise wkssvc pipe\n"));
4423                 return -1;
4424         }
4425
4426         if (!(mem_ctx = talloc_init("establishing trust relationship to domain %s",
4427                         domain_name))) {
4428                 DEBUG(0, ("talloc_init() failed\n"));
4429                 cli_shutdown(cli);
4430                 return -1;
4431         }
4432         
4433         nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info);
4434         
4435         if (NT_STATUS_IS_ERR(nt_status)) {
4436                 DEBUG(0, ("WksQueryInfo call failed.\n"));
4437                 return -1;
4438         }
4439
4440         if (cli->nt_pipe_fnum)
4441                 cli_nt_session_close(cli);
4442
4443
4444         /*
4445          * Call LsaOpenPolicy and LsaQueryInfo
4446          */
4447          
4448         if (!(mem_ctx = talloc_init("rpc_trustdom_establish"))) {
4449                 DEBUG(0, ("talloc_init() failed\n"));
4450                 cli_shutdown(cli);
4451                 return -1;
4452         }
4453
4454         if (!cli_nt_session_open(cli, PI_LSARPC)) {
4455                 DEBUG(0, ("Could not initialise lsa pipe\n"));
4456                 cli_shutdown(cli);
4457                 return -1;
4458         }
4459
4460         nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
4461                                          &connect_hnd);
4462         if (NT_STATUS_IS_ERR(nt_status)) {
4463                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
4464                         nt_errstr(nt_status)));
4465                 return -1;
4466         }
4467
4468         /* Querying info level 5 */
4469         
4470         nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
4471                                               5 /* info level */, &domain_name_pol,
4472                                               &domain_sid);
4473         if (NT_STATUS_IS_ERR(nt_status)) {
4474                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
4475                         nt_errstr(nt_status)));
4476                 return -1;
4477         }
4478
4479
4480
4481
4482         /* There should be actually query info level 3 (following nt serv behaviour),
4483            but I still don't know if it's _really_ necessary */
4484                         
4485         /*
4486          * Store the password in secrets db
4487          */
4488
4489         if (!secrets_store_trusted_domain_password(domain_name, wks_info.uni_lan_grp.buffer,
4490                                                    wks_info.uni_lan_grp.uni_str_len, opt_password,
4491                                                    *domain_sid)) {
4492                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
4493                 return -1;
4494         }
4495         
4496         /*
4497          * Close the pipes and clean up
4498          */
4499          
4500         nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
4501         if (NT_STATUS_IS_ERR(nt_status)) {
4502                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
4503                         nt_errstr(nt_status)));
4504                 return -1;
4505         }
4506
4507         if (cli->nt_pipe_fnum)
4508                 cli_nt_session_close(cli);
4509          
4510         talloc_destroy(mem_ctx);
4511          
4512         d_printf("Trust to domain %s established\n", domain_name);
4513         return 0;
4514 }
4515
4516 /**
4517  * Revoke trust relationship to the remote domain
4518  *
4519  * @param argc standard argc
4520  * @param argv standard argv without initial components
4521  *
4522  * @return Integer status (0 means success)
4523  **/
4524
4525 static int rpc_trustdom_revoke(int argc, const char **argv)
4526 {
4527         char* domain_name;
4528
4529         if (argc < 1) return -1;
4530         
4531         /* generate upper cased domain name */
4532         domain_name = smb_xstrdup(argv[0]);
4533         strupper_m(domain_name);
4534
4535         /* delete password of the trust */
4536         if (!trusted_domain_password_delete(domain_name)) {
4537                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
4538                           domain_name));
4539                 return -1;
4540         };
4541         
4542         return 0;
4543 }
4544
4545 /**
4546  * Usage for 'net rpc trustdom' command
4547  *
4548  * @param argc standard argc
4549  * @param argv standard argv without inital components
4550  *
4551  * @return Integer status returned to shell
4552  **/
4553  
4554 static int rpc_trustdom_usage(int argc, const char **argv)
4555 {
4556         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
4557         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
4558         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
4559         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
4560         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
4561         return -1;
4562 }
4563
4564
4565 static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, 
4566                                      const char *domain_name, 
4567                                      struct cli_state *cli, TALLOC_CTX *mem_ctx,
4568                                      int argc, const char **argv)
4569 {
4570         fstring str_sid;
4571         sid_to_string(str_sid, domain_sid);
4572         d_printf("%s\n", str_sid);
4573         return NT_STATUS_OK;
4574 }
4575
4576
4577 static int rpc_trustdom_list(int argc, const char **argv)
4578 {
4579         /* common variables */
4580         TALLOC_CTX* mem_ctx;
4581         struct cli_state *cli, *remote_cli;
4582         NTSTATUS nt_status;
4583         const char *domain_name = NULL;
4584         DOM_SID *queried_dom_sid;
4585         fstring ascii_sid, padding;
4586         int ascii_dom_name_len;
4587         POLICY_HND connect_hnd;
4588         
4589         /* trusted domains listing variables */
4590         unsigned int num_domains, enum_ctx = 0;
4591         int i, pad_len, col_len = 20;
4592         DOM_SID *domain_sids;
4593         char **trusted_dom_names;
4594         fstring pdc_name;
4595         char *dummy;
4596         
4597         /* trusting domains listing variables */
4598         POLICY_HND domain_hnd;
4599         char **trusting_dom_names;
4600         uint32 *trusting_dom_rids;
4601         
4602         /*
4603          * Listing trusted domains (stored in secrets.tdb, if local)
4604          */
4605
4606         mem_ctx = talloc_init("trust relationships listing");
4607
4608         /*
4609          * set domain and pdc name to local samba server (default)
4610          * or to remote one given in command line
4611          */
4612         
4613         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
4614                 domain_name = opt_workgroup;
4615                 opt_target_workgroup = opt_workgroup;
4616         } else {
4617                 fstrcpy(pdc_name, global_myname());
4618                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
4619                 opt_target_workgroup = domain_name;
4620         };
4621
4622         /* open \PIPE\lsarpc and open policy handle */
4623         if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
4624                 DEBUG(0, ("Couldn't connect to domain controller\n"));
4625                 return -1;
4626         };
4627
4628         if (!cli_nt_session_open(cli, PI_LSARPC)) {
4629                 DEBUG(0, ("Could not initialise lsa pipe\n"));
4630                 return -1;
4631         };
4632
4633         nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
4634                                         &connect_hnd);
4635         if (NT_STATUS_IS_ERR(nt_status)) {
4636                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
4637                         nt_errstr(nt_status)));
4638                 return -1;
4639         };
4640         
4641         /* query info level 5 to obtain sid of a domain being queried */
4642         nt_status = cli_lsa_query_info_policy(
4643                 cli, mem_ctx, &connect_hnd, 5 /* info level */, 
4644                 &dummy, &queried_dom_sid);
4645
4646         if (NT_STATUS_IS_ERR(nt_status)) {
4647                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
4648                         nt_errstr(nt_status)));
4649                 return -1;
4650         }
4651                 
4652         /*
4653          * Keep calling LsaEnumTrustdom over opened pipe until
4654          * the end of enumeration is reached
4655          */
4656          
4657         d_printf("Trusted domains list:\n\n");
4658
4659         do {
4660                 nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx,
4661                                                    &num_domains,
4662                                                    &trusted_dom_names, &domain_sids);
4663                 
4664                 if (NT_STATUS_IS_ERR(nt_status)) {
4665                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
4666                                 nt_errstr(nt_status)));
4667                         return -1;
4668                 };
4669                 
4670                 for (i = 0; i < num_domains; i++) {
4671                         /* convert sid into ascii string */
4672                         sid_to_string(ascii_sid, &(domain_sids[i]));
4673                 
4674                         /* calculate padding space for d_printf to look nicer */
4675                         pad_len = col_len - strlen(trusted_dom_names[i]);
4676                         padding[pad_len] = 0;
4677                         do padding[--pad_len] = ' '; while (pad_len);
4678                         
4679                         d_printf("%s%s%s\n", trusted_dom_names[i], padding, ascii_sid);
4680                 };
4681                 
4682                 /*
4683                  * in case of no trusted domains say something rather
4684                  * than just display blank line
4685                  */
4686                 if (!num_domains) d_printf("none\n");
4687
4688         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
4689
4690         /* close this connection before doing next one */
4691         nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
4692         if (NT_STATUS_IS_ERR(nt_status)) {
4693                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
4694                         nt_errstr(nt_status)));
4695                 return -1;
4696         };
4697         
4698         cli_nt_session_close(cli);
4699
4700         /*
4701          * Listing trusting domains (stored in passdb backend, if local)
4702          */
4703         
4704         d_printf("\nTrusting domains list:\n\n");
4705
4706         /*
4707          * Open \PIPE\samr and get needed policy handles
4708          */
4709         if (!cli_nt_session_open(cli, PI_SAMR)) {
4710                 DEBUG(0, ("Could not initialise samr pipe\n"));
4711                 return -1;
4712         };
4713         
4714         /* SamrConnect */
4715         nt_status = cli_samr_connect(cli, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN,
4716                                                                  &connect_hnd);
4717         if (!NT_STATUS_IS_OK(nt_status)) {
4718                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
4719                         nt_errstr(nt_status)));
4720                 return -1;
4721         };
4722         
4723         /* SamrOpenDomain - we have to open domain policy handle in order to be
4724            able to enumerate accounts*/
4725         nt_status = cli_samr_open_domain(cli, mem_ctx, &connect_hnd,
4726                                          SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
4727                                          queried_dom_sid, &domain_hnd);                                                                  
4728         if (!NT_STATUS_IS_OK(nt_status)) {
4729                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
4730                         nt_errstr(nt_status)));
4731                 return -1;
4732         };
4733         
4734         /*
4735          * perform actual enumeration
4736          */
4737          
4738         enum_ctx = 0;   /* reset enumeration context from last enumeration */
4739         do {
4740                         
4741                 nt_status = cli_samr_enum_dom_users(cli, mem_ctx, &domain_hnd,
4742                                                     &enum_ctx, ACB_DOMTRUST, 0xffff,
4743                                                     &trusting_dom_names, &trusting_dom_rids,
4744                                                     &num_domains);
4745                 if (NT_STATUS_IS_ERR(nt_status)) {
4746                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
4747                                 nt_errstr(nt_status)));
4748                         return -1;
4749                 };
4750                 
4751                 for (i = 0; i < num_domains; i++) {
4752
4753                         /*
4754                          * get each single domain's sid (do we _really_ need this ?):
4755                          *  1) connect to domain's pdc
4756                          *  2) query the pdc for domain's sid
4757                          */
4758
4759                         /* get rid of '$' tail */
4760                         ascii_dom_name_len = strlen(trusting_dom_names[i]);
4761                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
4762                                 trusting_dom_names[i][ascii_dom_name_len - 1] = '\0';
4763                         
4764                         /* calculate padding space for d_printf to look nicer */
4765                         pad_len = col_len - strlen(trusting_dom_names[i]);
4766                         padding[pad_len] = 0;
4767                         do padding[--pad_len] = ' '; while (pad_len);
4768
4769                         /* set opt_* variables to remote domain */
4770                         strupper_m(trusting_dom_names[i]);
4771                         opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]);
4772                         opt_target_workgroup = opt_workgroup;
4773                         
4774                         d_printf("%s%s", trusting_dom_names[i], padding);
4775                         
4776                         /* connect to remote domain controller */
4777                         remote_cli = net_make_ipc_connection(NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS);
4778                         if (remote_cli) {                       
4779                                 /* query for domain's sid */
4780                                 if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
4781                                         d_printf("couldn't get domain's sid\n");
4782
4783                                 cli_shutdown(remote_cli);
4784                         
4785                         } else {
4786                                 d_printf("domain controller is not responding\n");
4787                         };
4788                 };
4789                 
4790                 if (!num_domains) d_printf("none\n");
4791                 
4792         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
4793
4794         /* close opened samr and domain policy handles */
4795         nt_status = cli_samr_close(cli, mem_ctx, &domain_hnd);
4796         if (!NT_STATUS_IS_OK(nt_status)) {
4797                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
4798         };
4799         
4800         nt_status = cli_samr_close(cli, mem_ctx, &connect_hnd);
4801         if (!NT_STATUS_IS_OK(nt_status)) {
4802                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
4803         };
4804         
4805         /* close samr pipe and connection to IPC$ */
4806         cli_nt_session_close(cli);
4807         cli_shutdown(cli);
4808
4809         talloc_destroy(mem_ctx);         
4810         return 0;
4811 }
4812
4813 /**
4814  * Entrypoint for 'net rpc trustdom' code
4815  *
4816  * @param argc standard argc
4817  * @param argv standard argv without initial components
4818  *
4819  * @return Integer status (0 means success)
4820  */
4821
4822 static int rpc_trustdom(int argc, const char **argv)
4823 {
4824         struct functable func[] = {
4825                 {"add", rpc_trustdom_add},
4826                 {"del", rpc_trustdom_del},
4827                 {"establish", rpc_trustdom_establish},
4828                 {"revoke", rpc_trustdom_revoke},
4829                 {"help", rpc_trustdom_usage},
4830                 {"list", rpc_trustdom_list},
4831                 {NULL, NULL}
4832         };
4833
4834         if (argc == 0) {
4835                 rpc_trustdom_usage(argc, argv);
4836                 return -1;
4837         }
4838
4839         return (net_run_function(argc, argv, func, rpc_user_usage));
4840 }
4841
4842 /**
4843  * Check if a server will take rpc commands
4844  * @param flags Type of server to connect to (PDC, DMB, localhost)
4845  *              if the host is not explicitly specified
4846  * @return  BOOL (true means rpc supported)
4847  */
4848 BOOL net_rpc_check(unsigned flags)
4849 {
4850         struct cli_state cli;
4851         BOOL ret = False;
4852         struct in_addr server_ip;
4853         char *server_name = NULL;
4854
4855         /* flags (i.e. server type) may depend on command */
4856         if (!net_find_server(flags, &server_ip, &server_name))
4857                 return False;
4858
4859         ZERO_STRUCT(cli);
4860         if (cli_initialise(&cli) == False)
4861                 return False;
4862
4863         if (!cli_connect(&cli, server_name, &server_ip))
4864                 goto done;
4865         if (!attempt_netbios_session_request(&cli, global_myname(), 
4866                                              server_name, &server_ip))
4867                 goto done;
4868         if (!cli_negprot(&cli))
4869                 goto done;
4870         if (cli.protocol < PROTOCOL_NT1)
4871                 goto done;
4872
4873         ret = True;
4874  done:
4875         cli_shutdown(&cli);
4876         return ret;
4877 }
4878
4879 /* dump sam database via samsync rpc calls */
4880 static int rpc_samdump(int argc, const char **argv) {
4881         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
4882                                argc, argv);
4883 }
4884
4885 /* syncronise sam database via samsync rpc calls */
4886 static int rpc_vampire(int argc, const char **argv) {
4887         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
4888                                argc, argv);
4889 }
4890
4891 /** 
4892  * Migrate everything from a print-server
4893  *
4894  * @param argc  Standard main() style argc
4895  * @param argv  Standard main() style argv.  Initial components are already
4896  *              stripped
4897  *
4898  * @return A shell status integer (0 for success)
4899  *
4900  * The order is important !
4901  * To successfully add drivers the print-queues have to exist !
4902  * Applying ACLs should be the last step, because you're easily locked out
4903  *
4904  **/
4905 static int rpc_printer_migrate_all(int argc, const char **argv)
4906 {
4907         int ret;
4908
4909         if (!opt_host) {
4910                 printf("no server to migrate\n");
4911                 return -1;
4912         }
4913
4914         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
4915         if (ret)
4916                 return ret;
4917
4918         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
4919         if (ret)
4920                 return ret;
4921
4922         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
4923         if (ret)
4924                 return ret;
4925
4926         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
4927         if (ret)
4928                 return ret;
4929
4930         return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
4931
4932 }
4933
4934 /** 
4935  * Migrate print-drivers from a print-server
4936  *
4937  * @param argc  Standard main() style argc
4938  * @param argv  Standard main() style argv.  Initial components are already
4939  *              stripped
4940  *
4941  * @return A shell status integer (0 for success)
4942  **/
4943 static int rpc_printer_migrate_drivers(int argc, const char **argv)
4944 {
4945         if (!opt_host) {
4946                 printf("no server to migrate\n");
4947                 return -1;
4948         }
4949
4950         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
4951                                rpc_printer_migrate_drivers_internals,
4952                                argc, argv);
4953 }
4954
4955 /** 
4956  * Migrate print-forms from a print-server
4957  *
4958  * @param argc  Standard main() style argc
4959  * @param argv  Standard main() style argv.  Initial components are already
4960  *              stripped
4961  *
4962  * @return A shell status integer (0 for success)
4963  **/
4964 static int rpc_printer_migrate_forms(int argc, const char **argv)
4965 {
4966         if (!opt_host) {
4967                 printf("no server to migrate\n");
4968                 return -1;
4969         }
4970
4971         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
4972                                rpc_printer_migrate_forms_internals,
4973                                argc, argv);
4974 }
4975
4976 /** 
4977  * Migrate printers from a print-server
4978  *
4979  * @param argc  Standard main() style argc
4980  * @param argv  Standard main() style argv.  Initial components are already
4981  *              stripped
4982  *
4983  * @return A shell status integer (0 for success)
4984  **/
4985 static int rpc_printer_migrate_printers(int argc, const char **argv)
4986 {
4987         if (!opt_host) {
4988                 printf("no server to migrate\n");
4989                 return -1;
4990         }
4991
4992         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
4993                                rpc_printer_migrate_printers_internals,
4994                                argc, argv);
4995 }
4996
4997 /** 
4998  * Migrate printer-ACLs from a print-server
4999  *
5000  * @param argc  Standard main() style argc
5001  * @param argv  Standard main() style argv.  Initial components are already
5002  *              stripped
5003  *
5004  * @return A shell status integer (0 for success)
5005  **/
5006 static int rpc_printer_migrate_security(int argc, const char **argv)
5007 {
5008         if (!opt_host) {
5009                 printf("no server to migrate\n");
5010                 return -1;
5011         }
5012
5013         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5014                                rpc_printer_migrate_security_internals,
5015                                argc, argv);
5016 }
5017
5018 /** 
5019  * Migrate printer-settings from a print-server
5020  *
5021  * @param argc  Standard main() style argc
5022  * @param argv  Standard main() style argv.  Initial components are already
5023  *              stripped
5024  *
5025  * @return A shell status integer (0 for success)
5026  **/
5027 static int rpc_printer_migrate_settings(int argc, const char **argv)
5028 {
5029         if (!opt_host) {
5030                 printf("no server to migrate\n");
5031                 return -1;
5032         }
5033
5034         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5035                                rpc_printer_migrate_settings_internals,
5036                                argc, argv);
5037 }
5038
5039 /** 
5040  * 'net rpc printer' entrypoint.
5041  * @param argc  Standard main() style argc
5042  * @param argv  Standard main() style argv.  Initial components are already
5043  *              stripped
5044  **/
5045
5046 int rpc_printer_migrate(int argc, const char **argv) 
5047 {
5048
5049         /* ouch: when addriver and setdriver are called from within
5050            rpc_printer_migrate_drivers_internals, the printer-queue already
5051            *has* to exist */
5052
5053         struct functable func[] = {
5054                 {"all",         rpc_printer_migrate_all},
5055                 {"drivers",     rpc_printer_migrate_drivers},
5056                 {"forms",       rpc_printer_migrate_forms},
5057                 {"help",        rpc_printer_usage},
5058                 {"printers",    rpc_printer_migrate_printers},
5059                 {"security",    rpc_printer_migrate_security},
5060                 {"settings",    rpc_printer_migrate_settings},
5061                 {NULL, NULL}
5062         };
5063
5064         return net_run_function(argc, argv, func, rpc_printer_usage);
5065 }
5066
5067
5068 /** 
5069  * List printers on a remote RPC server
5070  *
5071  * @param argc  Standard main() style argc
5072  * @param argv  Standard main() style argv.  Initial components are already
5073  *              stripped
5074  *
5075  * @return A shell status integer (0 for success)
5076  **/
5077 static int rpc_printer_list(int argc, const char **argv)
5078 {
5079
5080         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5081                                rpc_printer_list_internals,
5082                                argc, argv);
5083 }
5084
5085 /** 
5086  * List printer-drivers on a remote RPC server
5087  *
5088  * @param argc  Standard main() style argc
5089  * @param argv  Standard main() style argv.  Initial components are already
5090  *              stripped
5091  *
5092  * @return A shell status integer (0 for success)
5093  **/
5094 static int rpc_printer_driver_list(int argc, const char **argv)
5095 {
5096
5097         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5098                                rpc_printer_driver_list_internals,
5099                                argc, argv);
5100 }
5101
5102 /** 
5103  * Publish printer in ADS via MSRPC
5104  *
5105  * @param argc  Standard main() style argc
5106  * @param argv  Standard main() style argv.  Initial components are already
5107  *              stripped
5108  *
5109  * @return A shell status integer (0 for success)
5110  **/
5111 static int rpc_printer_publish_publish(int argc, const char **argv)
5112 {
5113
5114         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5115                                rpc_printer_publish_publish_internals,
5116                                argc, argv);
5117 }
5118
5119 /** 
5120  * Update printer in ADS via MSRPC
5121  *
5122  * @param argc  Standard main() style argc
5123  * @param argv  Standard main() style argv.  Initial components are already
5124  *              stripped
5125  *
5126  * @return A shell status integer (0 for success)
5127  **/
5128 static int rpc_printer_publish_update(int argc, const char **argv)
5129 {
5130
5131         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5132                                rpc_printer_publish_update_internals,
5133                                argc, argv);
5134 }
5135
5136 /** 
5137  * UnPublish printer in ADS via MSRPC
5138  *
5139  * @param argc  Standard main() style argc
5140  * @param argv  Standard main() style argv.  Initial components are already
5141  *              stripped
5142  *
5143  * @return A shell status integer (0 for success)
5144  **/
5145 static int rpc_printer_publish_unpublish(int argc, const char **argv)
5146 {
5147
5148         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5149                                rpc_printer_publish_unpublish_internals,
5150                                argc, argv);
5151 }
5152
5153 /** 
5154  * List published printers via MSRPC
5155  *
5156  * @param argc  Standard main() style argc
5157  * @param argv  Standard main() style argv.  Initial components are already
5158  *              stripped
5159  *
5160  * @return A shell status integer (0 for success)
5161  **/
5162 static int rpc_printer_publish_list(int argc, const char **argv)
5163 {
5164
5165         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5166                                rpc_printer_publish_list_internals,
5167                                argc, argv);
5168 }
5169
5170
5171 /** 
5172  * Publish printer in ADS
5173  *
5174  * @param argc  Standard main() style argc
5175  * @param argv  Standard main() style argv.  Initial components are already
5176  *              stripped
5177  *
5178  * @return A shell status integer (0 for success)
5179  **/
5180 static int rpc_printer_publish(int argc, const char **argv)
5181 {
5182
5183         struct functable func[] = {
5184                 {"publish",     rpc_printer_publish_publish},
5185                 {"update",      rpc_printer_publish_update},
5186                 {"unpublish",   rpc_printer_publish_unpublish},
5187                 {"list",        rpc_printer_publish_list},
5188                 {"help",        rpc_printer_usage},
5189                 {NULL, NULL}
5190         };
5191
5192         if (argc == 0)
5193                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5194                                rpc_printer_publish_list_internals,
5195                                argc, argv);
5196
5197         return net_run_function(argc, argv, func, rpc_printer_usage);
5198
5199 }
5200
5201
5202 /** 
5203  * Display rpc printer help page.
5204  * @param argc  Standard main() style argc
5205  * @param argv  Standard main() style argv.  Initial components are already
5206  *              stripped
5207  **/
5208 int rpc_printer_usage(int argc, const char **argv)
5209 {
5210         return net_help_printer(argc, argv);
5211 }
5212
5213 /** 
5214  * 'net rpc printer' entrypoint.
5215  * @param argc  Standard main() style argc
5216  * @param argv  Standard main() style argv.  Initial components are already
5217  *              stripped
5218  **/
5219 int net_rpc_printer(int argc, const char **argv) 
5220 {
5221         struct functable func[] = {
5222                 {"list", rpc_printer_list},
5223                 {"migrate", rpc_printer_migrate},
5224                 {"driver", rpc_printer_driver_list},
5225                 {"publish", rpc_printer_publish},
5226                 {NULL, NULL}
5227         };
5228
5229         if (argc == 0)
5230                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5231                                rpc_printer_list_internals,
5232                                argc, argv);
5233
5234         return net_run_function(argc, argv, func, rpc_printer_usage);
5235 }
5236
5237 /****************************************************************************/
5238
5239
5240 /** 
5241  * Basic usage function for 'net rpc'
5242  * @param argc  Standard main() style argc
5243  * @param argv  Standard main() style argv.  Initial components are already
5244  *              stripped
5245  **/
5246
5247 int net_rpc_usage(int argc, const char **argv) 
5248 {
5249         d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
5250         d_printf("  net rpc join \t\t\tto join a domain \n");
5251         d_printf("  net rpc oldjoin \t\t\tto join a domain created in server manager\n\n\n");
5252         d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
5253         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
5254         d_printf("  net rpc password <username> [<password>] -Uadmin_username%%admin_pass\n");
5255         d_printf("  net rpc group \t\tto list groups\n");
5256         d_printf("  net rpc share \t\tto add, delete, list and migrate shares\n");
5257         d_printf("  net rpc printer \t\tto list and migrate printers\n");
5258         d_printf("  net rpc file \t\t\tto list open files\n");
5259         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
5260         d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
5261         d_printf("  net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
5262         d_printf("  net rpc samdump \t\tdiplay an NT PDC's users, groups and other data\n");
5263         d_printf("  net rpc trustdom \t\tto create trusting domain's account\n"
5264                  "\t\t\t\t\tor establish trust\n");
5265         d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
5266         d_printf("  net rpc shutdown \t\tto shutdown a remote server\n");
5267         d_printf("\n");
5268         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
5269         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
5270         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
5271         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
5272         d_printf("\t-c or --comment=<message>\ttext message to display on impending shutdown\n");
5273         return -1;
5274 }
5275
5276
5277 /**
5278  * Help function for 'net rpc'.  Calls command specific help if requested
5279  * or displays usage of net rpc
5280  * @param argc  Standard main() style argc
5281  * @param argv  Standard main() style argv.  Initial components are already
5282  *              stripped
5283  **/
5284
5285 int net_rpc_help(int argc, const char **argv)
5286 {
5287         struct functable func[] = {
5288                 {"join", rpc_join_usage},
5289                 {"user", rpc_user_usage},
5290                 {"group", rpc_group_usage},
5291                 {"share", rpc_share_usage},
5292                 /*{"changetrustpw", rpc_changetrustpw_usage}, */
5293                 {"trustdom", rpc_trustdom_usage},
5294                 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
5295                 /*{"shutdown", rpc_shutdown_usage}, */
5296                 {NULL, NULL}
5297         };
5298
5299         if (argc == 0) {
5300                 net_rpc_usage(argc, argv);
5301                 return -1;
5302         }
5303
5304         return (net_run_function(argc, argv, func, rpc_user_usage));
5305 }
5306
5307
5308 /** 
5309  * 'net rpc' entrypoint.
5310  * @param argc  Standard main() style argc
5311  * @param argv  Standard main() style argv.  Initial components are already
5312  *              stripped
5313  **/
5314
5315 int net_rpc(int argc, const char **argv)
5316 {
5317         struct functable func[] = {
5318                 {"info", net_rpc_info},
5319                 {"join", net_rpc_join},
5320                 {"oldjoin", net_rpc_oldjoin},
5321                 {"testjoin", net_rpc_testjoin},
5322                 {"user", net_rpc_user},
5323                 {"password", rpc_user_password},
5324                 {"group", net_rpc_group},
5325                 {"share", net_rpc_share},
5326                 {"file", net_rpc_file},
5327                 {"printer", net_rpc_printer},
5328                 {"changetrustpw", net_rpc_changetrustpw},
5329                 {"trustdom", rpc_trustdom},
5330                 {"abortshutdown", rpc_shutdown_abort},
5331                 {"shutdown", rpc_shutdown},
5332                 {"samdump", rpc_samdump},
5333                 {"vampire", rpc_vampire},
5334                 {"getsid", net_rpc_getsid},
5335                 {"help", net_rpc_help},
5336                 {NULL, NULL}
5337         };
5338         return net_run_function(argc, argv, func, net_rpc_usage);
5339 }