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