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