r10247: Fix help text for net rpc shutdown.
[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                 return cli_srvsvc_net_share_enum(cli, mem_ctx, level, ctr, 
2590                                                  preferred_len, &hnd);
2591         }
2592
2593         /* request just one share */
2594         result = cli_srvsvc_net_share_get_info(cli, mem_ctx, argv[0], level, &info);
2595
2596         if (!W_ERROR_IS_OK(result))
2597                 goto done;
2598
2599         /* construct ctr */
2600         ZERO_STRUCTP(ctr);
2601
2602         ctr->info_level = ctr->switch_value = level;
2603         ctr->ptr_share_info = ctr->ptr_entries = 1;
2604         ctr->num_entries = ctr->num_entries2 = 1;
2605
2606         switch (level) {
2607         case 1:
2608         {
2609                 char *s;
2610                 SRV_SHARE_INFO_1 *info1;
2611                 
2612                 ctr->share.info1 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_1, 1);
2613                 info1 = ctr->share.info1;
2614                                 
2615                 memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
2616
2617                 /* Copy pointer crap */
2618
2619                 memcpy(&info1->info_1, &info.share.info1.info_1, sizeof(SH_INFO_1));
2620
2621                 /* Duplicate strings */
2622
2623                 s = unistr2_tdup(mem_ctx, &info.share.info1.info_1_str.uni_netname);
2624                 if (s)
2625                         init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
2626
2627                 s = unistr2_tdup(mem_ctx, &info.share.info1.info_1_str.uni_remark);
2628                 if (s)
2629                         init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);
2630         }
2631         case 2:
2632         {
2633                 char *s;
2634                 SRV_SHARE_INFO_2 *info2;
2635                 
2636                 ctr->share.info2 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_2, 1);
2637                 info2 = ctr->share.info2;
2638                                 
2639                 memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
2640
2641                 /* Copy pointer crap */
2642
2643                 memcpy(&info2->info_2, &info.share.info2.info_2, sizeof(SH_INFO_2));
2644
2645                 /* Duplicate strings */
2646
2647                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_netname);
2648                 if (s)
2649                         init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);
2650
2651                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_remark);
2652                 if (s)
2653                         init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);
2654
2655                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_path);
2656                 if (s)
2657                         init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);
2658
2659                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_passwd);
2660                 if (s)
2661                         init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
2662         }
2663         case 502:
2664         {
2665                 char *s;
2666                 SRV_SHARE_INFO_502 *info502;
2667
2668                 ctr->share.info502 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_502, 1);
2669                 info502 = ctr->share.info502;
2670
2671                 memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502));
2672
2673                 /* Copy pointer crap */
2674
2675                 memcpy(&info502->info_502, &info.share.info502.info_502, sizeof(SH_INFO_502));
2676
2677                 /* Duplicate strings */
2678
2679                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_netname);
2680                 if (s)
2681                         init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE);
2682
2683                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_remark);
2684                 if (s)
2685                         init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE);
2686
2687                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_path);
2688                 if (s)
2689                         init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE);
2690
2691                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_passwd);
2692                 if (s)
2693                         init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE);
2694
2695                 info502->info_502_str.sd = dup_sec_desc(mem_ctx, info.share.info502.info_502_str.sd);
2696                                 
2697         }
2698
2699         } /* switch */
2700
2701 done:
2702         return result;
2703 }
2704
2705 /** 
2706  * List shares on a remote RPC server
2707  *
2708  * All parameters are provided by the run_rpc_command function, except for
2709  * argc, argv which are passes through. 
2710  *
2711  * @param domain_sid The domain sid acquired from the remote server
2712  * @param cli A cli_state connected to the server.
2713  * @param mem_ctx Talloc context, destoyed on completion of the function.
2714  * @param argc  Standard main() style argc
2715  * @param argv  Standard main() style argv.  Initial components are already
2716  *              stripped
2717  *
2718  * @return Normal NTSTATUS return.
2719  **/
2720
2721 static NTSTATUS 
2722 rpc_share_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
2723                          struct cli_state *cli,
2724                          TALLOC_CTX *mem_ctx, int argc, const char **argv)
2725 {
2726         SRV_SHARE_INFO_CTR ctr;
2727         WERROR result;
2728         uint32 i, level = 1;
2729
2730         result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr);
2731         if (!W_ERROR_IS_OK(result))
2732                 goto done;
2733
2734         /* Display results */
2735
2736         if (opt_long_list_entries) {
2737                 d_printf(
2738         "\nEnumerating shared resources (exports) on remote server:\n\n"\
2739         "\nShare name   Type     Description\n"\
2740         "----------   ----     -----------\n");
2741         }
2742         for (i = 0; i < ctr.num_entries; i++)
2743                 display_share_info_1(&ctr.share.info1[i]);
2744  done:
2745         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
2746 }
2747
2748 /*** 
2749  * 'net rpc share list' entrypoint.
2750  * @param argc  Standard main() style argc
2751  * @param argv  Standard main() style argv.  Initial components are already
2752  *              stripped
2753  **/
2754 static int rpc_share_list(int argc, const char **argv)
2755 {
2756         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_list_internals, argc, argv);
2757 }
2758
2759 static BOOL check_share_availability(struct cli_state *cli, const char *netname)
2760 {
2761         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
2762                 d_printf("skipping   [%s]: not a file share.\n", netname);
2763                 return False;
2764         }
2765
2766         if (!cli_tdis(cli)) 
2767                 return False;
2768
2769         return True;
2770 }
2771
2772 static BOOL check_share_sanity(struct cli_state *cli, fstring netname, uint32 type)
2773 {
2774         /* only support disk shares */
2775         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
2776                 printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
2777                 return False;
2778         }
2779
2780         /* skip builtin shares */
2781         /* FIXME: should print$ be added too ? */
2782         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") || 
2783             strequal(netname,"global")) 
2784                 return False;
2785
2786         if (opt_exclude && in_list(netname, opt_exclude, False)) {
2787                 printf("excluding  [%s]\n", netname);
2788                 return False;
2789         }
2790
2791         return check_share_availability(cli, netname);
2792 }
2793
2794 /** 
2795  * Migrate shares from a remote RPC server to the local RPC srever
2796  *
2797  * All parameters are provided by the run_rpc_command function, except for
2798  * argc, argv which are passes through. 
2799  *
2800  * @param domain_sid The domain sid acquired from the remote server
2801  * @param cli A cli_state connected to the server.
2802  * @param mem_ctx Talloc context, destoyed on completion of the function.
2803  * @param argc  Standard main() style argc
2804  * @param argv  Standard main() style argv.  Initial components are already
2805  *              stripped
2806  *
2807  * @return Normal NTSTATUS return.
2808  **/
2809 static NTSTATUS 
2810 rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain_name, 
2811                                    struct cli_state *cli, TALLOC_CTX *mem_ctx, 
2812                                    int argc, const char **argv)
2813 {
2814         WERROR result;
2815         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
2816         SRV_SHARE_INFO_CTR ctr_src;
2817         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
2818         char *password = NULL; /* don't allow a share password */
2819         uint32 i;
2820         BOOL got_dst_srvsvc_pipe = False;
2821         struct cli_state *cli_dst = NULL;
2822         uint32 level = 502; /* includes secdesc */
2823
2824         result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src);
2825         if (!W_ERROR_IS_OK(result))
2826                 goto done;
2827
2828         /* connect destination PI_SRVSVC */
2829         nt_status = connect_dst_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe);
2830         if (!NT_STATUS_IS_OK(nt_status))
2831                 return nt_status;
2832
2833
2834         for (i = 0; i < ctr_src.num_entries; i++) {
2835
2836                 fstring netname = "", remark = "", path = "";
2837                 /* reset error-code */
2838                 nt_status = NT_STATUS_UNSUCCESSFUL;
2839
2840                 rpcstr_pull_unistr2_fstring(
2841                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
2842                 rpcstr_pull_unistr2_fstring(
2843                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
2844                 rpcstr_pull_unistr2_fstring(
2845                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
2846
2847                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
2848                         continue;
2849
2850                 /* finally add the share on the dst server */ 
2851
2852                 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n", 
2853                         netname, path, remark);
2854
2855                 result = cli_srvsvc_net_share_add(cli_dst, mem_ctx, netname, type, remark,
2856                                                   ctr_src.share.info502[i].info_502.perms,
2857                                                   ctr_src.share.info502[i].info_502.max_uses,
2858                                                   ctr_src.share.info502[i].info_502.num_uses,
2859                                                   path, password, level, 
2860                                                   NULL);
2861         
2862                 if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
2863                         printf("           [%s] does already exist\n", netname);
2864                         continue;
2865                 }
2866
2867                 if (!W_ERROR_IS_OK(result)) {
2868                         printf("cannot add share: %s\n", dos_errstr(result));
2869                         goto done;
2870                 }
2871
2872         }
2873
2874         nt_status = NT_STATUS_OK;
2875
2876 done:
2877         if (got_dst_srvsvc_pipe) {
2878                 cli_nt_session_close(cli_dst);
2879                 cli_shutdown(cli_dst);
2880         }
2881
2882         return nt_status;
2883
2884 }
2885
2886 /** 
2887  * Migrate shares from a rpc-server to another
2888  *
2889  * @param argc  Standard main() style argc
2890  * @param argv  Standard main() style argv.  Initial components are already
2891  *              stripped
2892  *
2893  * @return A shell status integer (0 for success)
2894  **/
2895 static int rpc_share_migrate_shares(int argc, const char **argv)
2896 {
2897
2898         if (!opt_host) {
2899                 printf("no server to migrate\n");
2900                 return -1;
2901         }
2902
2903         return run_rpc_command(NULL, PI_SRVSVC, 0, 
2904                                rpc_share_migrate_shares_internals,
2905                                argc, argv);
2906 }
2907
2908 /**
2909  * Copy a file/dir 
2910  *
2911  * @param f     file_info
2912  * @param mask  current search mask
2913  * @param state arg-pointer
2914  *
2915  **/
2916 static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state)
2917 {
2918         static NTSTATUS nt_status;
2919         static struct copy_clistate *local_state;
2920         static fstring filename, new_mask;
2921         fstring dir;
2922         char *old_dir;
2923
2924         local_state = (struct copy_clistate *)state;
2925         nt_status = NT_STATUS_UNSUCCESSFUL;
2926
2927         if (strequal(f->name, ".") || strequal(f->name, ".."))
2928                 return;
2929
2930         DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
2931
2932         /* DIRECTORY */
2933         if (f->mode & aDIR) {
2934
2935                 DEBUG(3,("got dir: %s\n", f->name));
2936
2937                 fstrcpy(dir, local_state->cwd);
2938                 fstrcat(dir, "\\");
2939                 fstrcat(dir, f->name);
2940
2941                 switch (net_mode_share)
2942                 {
2943                 case NET_MODE_SHARE_MIGRATE:
2944                         /* create that directory */
2945                         nt_status = net_copy_file(local_state->mem_ctx,
2946                                                   local_state->cli_share_src,
2947                                                   local_state->cli_share_dst,
2948                                                   dir, dir,
2949                                                   opt_acls? True : False,
2950                                                   opt_attrs? True : False,
2951                                                   opt_timestamps? True : False,
2952                                                   False);
2953                         break;
2954                 default:
2955                         d_printf("Unsupported mode %d\n", net_mode_share);
2956                         return;
2957                 }
2958
2959                 if (!NT_STATUS_IS_OK(nt_status)) 
2960                         printf("could not handle dir %s: %s\n", 
2961                                 dir, nt_errstr(nt_status));
2962
2963                 /* search below that directory */
2964                 fstrcpy(new_mask, dir);
2965                 fstrcat(new_mask, "\\*");
2966
2967                 old_dir = local_state->cwd;
2968                 local_state->cwd = dir;
2969                 if (!sync_files(local_state, new_mask))
2970                         printf("could not handle files\n");
2971                 local_state->cwd = old_dir;
2972
2973                 return;
2974         }
2975
2976
2977         /* FILE */
2978         fstrcpy(filename, local_state->cwd);
2979         fstrcat(filename, "\\");
2980         fstrcat(filename, f->name);
2981
2982         DEBUG(3,("got file: %s\n", filename));
2983
2984         switch (net_mode_share)
2985         {
2986         case NET_MODE_SHARE_MIGRATE:
2987                 nt_status = net_copy_file(local_state->mem_ctx, 
2988                                           local_state->cli_share_src, 
2989                                           local_state->cli_share_dst, 
2990                                           filename, filename, 
2991                                           opt_acls? True : False, 
2992                                           opt_attrs? True : False,
2993                                           opt_timestamps? True: False,
2994                                           True);
2995                 break;
2996         default:
2997                 d_printf("Unsupported file mode %d\n", net_mode_share);
2998                 return;
2999         }
3000
3001         if (!NT_STATUS_IS_OK(nt_status)) 
3002                 printf("could not handle file %s: %s\n", 
3003                         filename, nt_errstr(nt_status));
3004
3005 }
3006
3007 /**
3008  * sync files, can be called recursivly to list files 
3009  * and then call copy_fn for each file 
3010  *
3011  * @param cp_clistate   pointer to the copy_clistate we work with
3012  * @param mask          the current search mask
3013  *
3014  * @return              Boolean result
3015  **/
3016 BOOL sync_files(struct copy_clistate *cp_clistate, pstring mask)
3017 {
3018
3019         DEBUG(3,("calling cli_list with mask: %s\n", mask));
3020
3021         if (cli_list(cp_clistate->cli_share_src, mask, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3022                 d_printf("listing %s failed with error: %s\n", 
3023                         mask, cli_errstr(cp_clistate->cli_share_src));
3024                 return False;
3025         }
3026
3027         return True;
3028 }
3029
3030
3031 /**
3032  * Set the top level directory permissions before we do any further copies.
3033  * Should set up ACL inheritance.
3034  **/
3035
3036 BOOL copy_top_level_perms(struct copy_clistate *cp_clistate, 
3037                                 const char *sharename)
3038 {
3039         NTSTATUS nt_status;
3040
3041         switch (net_mode_share) {
3042         case NET_MODE_SHARE_MIGRATE:
3043                 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3044                 nt_status = net_copy_fileattr(cp_clistate->mem_ctx,
3045                                                 cp_clistate->cli_share_src, 
3046                                                 cp_clistate->cli_share_dst,
3047                                                 "\\", "\\",
3048                                                 opt_acls? True : False, 
3049                                                 opt_attrs? True : False,
3050                                                 opt_timestamps? True: False,
3051                                                 False);
3052                 break;
3053         default:
3054                 d_printf("Unsupported mode %d\n", net_mode_share);
3055                 break;
3056         }
3057
3058         if (!NT_STATUS_IS_OK(nt_status))  {
3059                 printf("Could handle directory attributes for top level directory of share %s. Error %s\n", 
3060                         sharename, nt_errstr(nt_status));
3061                 return False;
3062         }
3063
3064         return True;
3065 }
3066
3067
3068 /** 
3069  * Sync all files inside a remote share to another share (over smb)
3070  *
3071  * All parameters are provided by the run_rpc_command function, except for
3072  * argc, argv which are passes through. 
3073  *
3074  * @param domain_sid The domain sid acquired from the remote server
3075  * @param cli A cli_state connected to the server.
3076  * @param mem_ctx Talloc context, destoyed on completion of the function.
3077  * @param argc  Standard main() style argc
3078  * @param argv  Standard main() style argv.  Initial components are already
3079  *              stripped
3080  *
3081  * @return Normal NTSTATUS return.
3082  **/
3083 static NTSTATUS 
3084 rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_name, 
3085                                   struct cli_state *cli, TALLOC_CTX *mem_ctx,
3086                                   int argc, const char **argv)
3087 {
3088         WERROR result;
3089         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3090         SRV_SHARE_INFO_CTR ctr_src;
3091         uint32 i;
3092         uint32 level = 502;
3093         struct copy_clistate cp_clistate;
3094         BOOL got_src_share = False;
3095         BOOL got_dst_share = False;
3096         pstring mask = "\\*";
3097         char *dst = NULL;
3098
3099         dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1");
3100
3101         result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src);
3102
3103         if (!W_ERROR_IS_OK(result))
3104                 goto done;
3105
3106         for (i = 0; i < ctr_src.num_entries; i++) {
3107
3108                 fstring netname = "";
3109
3110                 rpcstr_pull_unistr2_fstring(
3111                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3112
3113                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3114                         continue;
3115
3116                 /* one might not want to mirror whole discs :) */
3117                 if (strequal(netname, "print$") || netname[1] == '$') {
3118                         d_printf("skipping   [%s]: builtin/hidden share\n", netname);
3119                         continue;
3120                 }
3121
3122                 switch (net_mode_share)
3123                 {
3124                 case NET_MODE_SHARE_MIGRATE:
3125                         printf("syncing");
3126                         break;
3127                 default:
3128                         d_printf("Unsupported mode %d\n", net_mode_share);
3129                         break;
3130                 }
3131                 printf("    [%s] files and directories %s ACLs, %s DOS Attributes %s\n", 
3132                         netname, 
3133                         opt_acls ? "including" : "without", 
3134                         opt_attrs ? "including" : "without",
3135                         opt_timestamps ? "(preserving timestamps)" : "");
3136
3137                 cp_clistate.mem_ctx = mem_ctx;
3138                 cp_clistate.cli_share_src = NULL;
3139                 cp_clistate.cli_share_dst = NULL;
3140                 cp_clistate.cwd = NULL;
3141                 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3142
3143                 /* open share source */
3144                 nt_status = connect_to_service(&cp_clistate.cli_share_src,
3145                                                &cli->dest_ip, cli->desthost,
3146                                                netname, "A:");
3147                 if (!NT_STATUS_IS_OK(nt_status))
3148                         goto done;
3149
3150                 got_src_share = True;
3151
3152                 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3153                         /* open share destination */
3154                         nt_status = connect_to_service(&cp_clistate.cli_share_dst,
3155                                                        NULL, dst, netname, "A:");
3156                         if (!NT_STATUS_IS_OK(nt_status))
3157                                 goto done;
3158
3159                         got_dst_share = True;
3160                 }
3161
3162                 if (!copy_top_level_perms(&cp_clistate, netname)) {
3163                         d_printf("Could not handle the top level directory permissions for the share: %s\n", netname);
3164                         nt_status = NT_STATUS_UNSUCCESSFUL;
3165                         goto done;
3166                 }
3167
3168                 if (!sync_files(&cp_clistate, mask)) {
3169                         d_printf("could not handle files for share: %s\n", netname);
3170                         nt_status = NT_STATUS_UNSUCCESSFUL;
3171                         goto done;
3172                 }
3173         }
3174
3175         nt_status = NT_STATUS_OK;
3176
3177 done:
3178
3179         if (got_src_share)
3180                 cli_shutdown(cp_clistate.cli_share_src);
3181
3182         if (got_dst_share)
3183                 cli_shutdown(cp_clistate.cli_share_dst);
3184
3185         return nt_status;
3186
3187 }
3188
3189 static int rpc_share_migrate_files(int argc, const char **argv)
3190 {
3191
3192         if (!opt_host) {
3193                 printf("no server to migrate\n");
3194                 return -1;
3195         }
3196
3197         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3198                                rpc_share_migrate_files_internals,
3199                                argc, argv);
3200 }
3201
3202 /** 
3203  * Migrate share-ACLs from a remote RPC server to the local RPC srever
3204  *
3205  * All parameters are provided by the run_rpc_command function, except for
3206  * argc, argv which are passes through. 
3207  *
3208  * @param domain_sid The domain sid acquired from the remote server
3209  * @param cli A cli_state connected to the server.
3210  * @param mem_ctx Talloc context, destoyed on completion of the function.
3211  * @param argc  Standard main() style argc
3212  * @param argv  Standard main() style argv.  Initial components are already
3213  *              stripped
3214  *
3215  * @return Normal NTSTATUS return.
3216  **/
3217 static NTSTATUS 
3218 rpc_share_migrate_security_internals(const DOM_SID *domain_sid, const char *domain_name, 
3219                                      struct cli_state *cli, TALLOC_CTX *mem_ctx, 
3220                                      int argc, const char **argv)
3221 {
3222         WERROR result;
3223         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3224         SRV_SHARE_INFO_CTR ctr_src;
3225         SRV_SHARE_INFO info;
3226         uint32 i;
3227         BOOL got_dst_srvsvc_pipe = False;
3228         struct cli_state *cli_dst = NULL;
3229         uint32 level = 502; /* includes secdesc */
3230
3231         result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src);
3232
3233         if (!W_ERROR_IS_OK(result))
3234                 goto done;
3235
3236         /* connect destination PI_SRVSVC */
3237         nt_status = connect_dst_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe);
3238         if (!NT_STATUS_IS_OK(nt_status))
3239                 return nt_status;
3240
3241
3242         for (i = 0; i < ctr_src.num_entries; i++) {
3243
3244                 fstring netname = "", remark = "", path = "";
3245                 /* reset error-code */
3246                 nt_status = NT_STATUS_UNSUCCESSFUL;
3247
3248                 rpcstr_pull_unistr2_fstring(
3249                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3250                 rpcstr_pull_unistr2_fstring(
3251                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
3252                 rpcstr_pull_unistr2_fstring(
3253                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
3254
3255                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3256                         continue;
3257
3258                 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n", 
3259                         netname, path, remark);
3260
3261                 if (opt_verbose)
3262                         display_sec_desc(ctr_src.share.info502[i].info_502_str.sd);
3263
3264                 /* init info */
3265                 ZERO_STRUCT(info);
3266
3267                 info.switch_value = level;
3268                 info.ptr_share_ctr = 1;
3269
3270                 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3271                 info.share.info502 = ctr_src.share.info502[i];
3272
3273                 /* finally modify the share on the dst server */
3274                 result = cli_srvsvc_net_share_set_info(cli_dst, mem_ctx, netname, level, &info);
3275         
3276                 if (!W_ERROR_IS_OK(result)) {
3277                         printf("cannot set share-acl: %s\n", dos_errstr(result));
3278                         goto done;
3279                 }
3280
3281         }
3282
3283         nt_status = NT_STATUS_OK;
3284
3285 done:
3286         if (got_dst_srvsvc_pipe) {
3287                 cli_nt_session_close(cli_dst);
3288                 cli_shutdown(cli_dst);
3289         }
3290
3291         return nt_status;
3292
3293 }
3294
3295 /** 
3296  * Migrate share-acls from a rpc-server to another
3297  *
3298  * @param argc  Standard main() style argc
3299  * @param argv  Standard main() style argv.  Initial components are already
3300  *              stripped
3301  *
3302  * @return A shell status integer (0 for success)
3303  **/
3304 static int rpc_share_migrate_security(int argc, const char **argv)
3305 {
3306
3307         if (!opt_host) {
3308                 printf("no server to migrate\n");
3309                 return -1;
3310         }
3311
3312         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3313                                rpc_share_migrate_security_internals,
3314                                argc, argv);
3315 }
3316
3317 /** 
3318  * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3319  * from one server to another
3320  *
3321  * @param argc  Standard main() style argc
3322  * @param argv  Standard main() style argv.  Initial components are already
3323  *              stripped
3324  *
3325  * @return A shell status integer (0 for success)
3326  *
3327  **/
3328 static int rpc_share_migrate_all(int argc, const char **argv)
3329 {
3330         int ret;
3331
3332         if (!opt_host) {
3333                 printf("no server to migrate\n");
3334                 return -1;
3335         }
3336
3337         /* order is important. we don't want to be locked out by the share-acl
3338          * before copying files - gd */
3339         
3340         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
3341         if (ret)
3342                 return ret;
3343
3344         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
3345         if (ret)
3346                 return ret;
3347         
3348         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_security_internals, argc, argv);
3349 }
3350
3351
3352 /** 
3353  * 'net rpc share migrate' entrypoint.
3354  * @param argc  Standard main() style argc
3355  * @param argv  Standard main() style argv.  Initial components are already
3356  *              stripped
3357  **/
3358 static int rpc_share_migrate(int argc, const char **argv)
3359 {
3360
3361         struct functable func[] = {
3362                 {"all",         rpc_share_migrate_all},
3363                 {"files",       rpc_share_migrate_files},
3364                 {"help",        rpc_share_usage},
3365                 {"security",    rpc_share_migrate_security},
3366                 {"shares",      rpc_share_migrate_shares},
3367                 {NULL, NULL}
3368         };
3369
3370         net_mode_share = NET_MODE_SHARE_MIGRATE;
3371
3372         return net_run_function(argc, argv, func, rpc_share_usage);
3373 }
3374
3375 struct full_alias {
3376         DOM_SID sid;
3377         uint32 num_members;
3378         DOM_SID *members;
3379 };
3380
3381 static int num_server_aliases;
3382 static struct full_alias *server_aliases;
3383
3384 /*
3385  * Add an alias to the static list.
3386  */
3387 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
3388 {
3389         if (server_aliases == NULL)
3390                 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
3391
3392         server_aliases[num_server_aliases] = *alias;
3393         num_server_aliases += 1;
3394 }
3395
3396 /*
3397  * For a specific domain on the server, fetch all the aliases
3398  * and their members. Add all of them to the server_aliases.
3399  */
3400 static NTSTATUS
3401 rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx,
3402                          POLICY_HND *connect_pol,
3403                          const DOM_SID *domain_sid)
3404 {
3405         uint32 start_idx, max_entries, num_entries, i;
3406         struct acct_info *groups;
3407         NTSTATUS result;
3408         POLICY_HND domain_pol;
3409
3410         /* Get domain policy handle */
3411         
3412         result = cli_samr_open_domain(cli, mem_ctx, connect_pol,
3413                                       MAXIMUM_ALLOWED_ACCESS,
3414                                       domain_sid, &domain_pol);
3415         if (!NT_STATUS_IS_OK(result))
3416                 return result;
3417
3418         start_idx = 0;
3419         max_entries = 250;
3420
3421         do {
3422                 result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
3423                                                   &start_idx, max_entries,
3424                                                   &groups, &num_entries);
3425
3426                 for (i = 0; i < num_entries; i++) {
3427
3428                         POLICY_HND alias_pol;
3429                         struct full_alias alias;
3430                         DOM_SID *members;
3431                         int j;
3432
3433                         result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
3434                                                      MAXIMUM_ALLOWED_ACCESS,
3435                                                      groups[i].rid,
3436                                                      &alias_pol);
3437                         if (!NT_STATUS_IS_OK(result))
3438                                 goto done;
3439
3440                         result = cli_samr_query_aliasmem(cli, mem_ctx,
3441                                                          &alias_pol,
3442                                                          &alias.num_members,
3443                                                          &members);
3444                         if (!NT_STATUS_IS_OK(result))
3445                                 goto done;
3446
3447                         result = cli_samr_close(cli, mem_ctx, &alias_pol);
3448                         if (!NT_STATUS_IS_OK(result))
3449                                 goto done;
3450
3451                         alias.members = NULL;
3452
3453                         if (alias.num_members > 0) {
3454                                 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
3455
3456                                 for (j = 0; j < alias.num_members; j++)
3457                                         sid_copy(&alias.members[j],
3458                                                  &members[j]);
3459                         }
3460
3461                         sid_copy(&alias.sid, domain_sid);
3462                         sid_append_rid(&alias.sid, groups[i].rid);
3463
3464                         push_alias(mem_ctx, &alias);
3465                 }
3466         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3467
3468         result = NT_STATUS_OK;
3469
3470  done:
3471         cli_samr_close(cli, mem_ctx, &domain_pol);
3472
3473         return result;
3474 }
3475
3476 /*
3477  * Dump server_aliases as names for debugging purposes.
3478  */
3479 static NTSTATUS
3480 rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name,
3481                    struct cli_state *cli, TALLOC_CTX *mem_ctx, 
3482                    int argc, const char **argv)
3483 {
3484         int i;
3485         NTSTATUS result;
3486         POLICY_HND lsa_pol;
3487
3488         result = cli_lsa_open_policy(cli, mem_ctx, True, 
3489                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
3490                                      &lsa_pol);
3491         if (!NT_STATUS_IS_OK(result))
3492                 return result;
3493
3494         for (i=0; i<num_server_aliases; i++) {
3495                 char **names;
3496                 char **domains;
3497                 uint32 *types;
3498                 int j;
3499
3500                 struct full_alias *alias = &server_aliases[i];
3501
3502                 result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol, 1,
3503                                              &alias->sid,
3504                                              &domains, &names, &types);
3505                 if (!NT_STATUS_IS_OK(result))
3506                         continue;
3507
3508                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
3509
3510                 if (alias->num_members == 0) {
3511                         DEBUG(1, ("\n"));
3512                         continue;
3513                 }
3514
3515                 result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol,
3516                                              alias->num_members,
3517                                              alias->members,
3518                                              &domains, &names, &types);
3519
3520                 if (!NT_STATUS_IS_OK(result) &&
3521                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
3522                         continue;
3523
3524                 for (j=0; j<alias->num_members; j++)
3525                         DEBUG(1, ("%s\\%s (%d); ",
3526                                   domains[j] ? domains[j] : "*unknown*", 
3527                                   names[j] ? names[j] : "*unknown*",types[j]));
3528                 DEBUG(1, ("\n"));
3529         }
3530
3531         cli_lsa_close(cli, mem_ctx, &lsa_pol);
3532
3533         return NT_STATUS_OK;
3534 }
3535
3536 /*
3537  * Fetch a list of all server aliases and their members into
3538  * server_aliases.
3539  */
3540 static NTSTATUS
3541 rpc_aliaslist_internals(const DOM_SID *domain_sid, const char *domain_name,
3542                         struct cli_state *cli, TALLOC_CTX *mem_ctx, 
3543                         int argc, const char **argv)
3544 {
3545         NTSTATUS result;
3546         POLICY_HND connect_pol;
3547
3548         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
3549                                   &connect_pol);
3550
3551         if (!NT_STATUS_IS_OK(result))
3552                 goto done;
3553         
3554         result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol,
3555                                           &global_sid_Builtin);
3556
3557         if (!NT_STATUS_IS_OK(result))
3558                 goto done;
3559         
3560         result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol,
3561                                           domain_sid);
3562
3563         cli_samr_close(cli, mem_ctx, &connect_pol);
3564  done:
3565         return result;
3566 }
3567
3568 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
3569 {
3570         token->num_sids = 4;
3571
3572         token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4);
3573
3574         token->user_sids[0] = *user_sid;
3575         sid_copy(&token->user_sids[1], &global_sid_World);
3576         sid_copy(&token->user_sids[2], &global_sid_Network);
3577         sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
3578 }
3579
3580 static void free_user_token(NT_USER_TOKEN *token)
3581 {
3582         SAFE_FREE(token->user_sids);
3583 }
3584
3585 static BOOL is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
3586 {
3587         int i;
3588
3589         for (i=0; i<token->num_sids; i++) {
3590                 if (sid_compare(sid, &token->user_sids[i]) == 0)
3591                         return True;
3592         }
3593         return False;
3594 }
3595
3596 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
3597 {
3598         if (is_sid_in_token(token, sid))
3599                 return;
3600
3601         token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
3602
3603         sid_copy(&token->user_sids[token->num_sids], sid);
3604
3605         token->num_sids += 1;
3606 }
3607
3608 struct user_token {
3609         fstring name;
3610         NT_USER_TOKEN token;
3611 };
3612
3613 static void dump_user_token(struct user_token *token)
3614 {
3615         int i;
3616
3617         d_printf("%s\n", token->name);
3618
3619         for (i=0; i<token->token.num_sids; i++) {
3620                 d_printf(" %s\n", sid_string_static(&token->token.user_sids[i]));
3621         }
3622 }
3623
3624 static BOOL is_alias_member(DOM_SID *sid, struct full_alias *alias)
3625 {
3626         int i;
3627
3628         for (i=0; i<alias->num_members; i++) {
3629                 if (sid_compare(sid, &alias->members[i]) == 0)
3630                         return True;
3631         }
3632
3633         return False;
3634 }
3635
3636 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
3637 {
3638         int i;
3639
3640         for (i=0; i<num_server_aliases; i++) {
3641                 if (is_alias_member(&sid, &server_aliases[i]))
3642                         add_sid_to_token(token, &server_aliases[i].sid);
3643         }
3644 }
3645
3646 /*
3647  * We got a user token with all the SIDs we can know about without asking the
3648  * server directly. These are the user and domain group sids. All of these can
3649  * be members of aliases. So scan the list of aliases for each of the SIDs and
3650  * add them to the token.
3651  */
3652
3653 static void collect_alias_memberships(NT_USER_TOKEN *token)
3654 {
3655         int num_global_sids = token->num_sids;
3656         int i;
3657
3658         for (i=0; i<num_global_sids; i++) {
3659                 collect_sid_memberships(token, token->user_sids[i]);
3660         }
3661 }
3662
3663 static BOOL get_user_sids(const char *domain, const char *user,
3664                           NT_USER_TOKEN *token)
3665 {
3666         struct winbindd_request request;
3667         struct winbindd_response response;
3668         fstring full_name;
3669         NSS_STATUS result;
3670
3671         DOM_SID user_sid;
3672
3673         int i;
3674
3675         fstr_sprintf(full_name, "%s%c%s",
3676                      domain, *lp_winbind_separator(), user);
3677
3678         /* First let's find out the user sid */
3679
3680         ZERO_STRUCT(request);
3681         ZERO_STRUCT(response);
3682
3683         fstrcpy(request.data.name.dom_name, domain);
3684         fstrcpy(request.data.name.name, user);
3685
3686         result = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response);
3687
3688         if (result != NSS_STATUS_SUCCESS) {
3689                 DEBUG(1, ("winbind could not find %s\n", full_name));
3690                 return False;
3691         }
3692
3693         if (response.data.sid.type != SID_NAME_USER) {
3694                 DEBUG(1, ("%s is not a user\n", full_name));
3695                 return False;
3696         }
3697
3698         string_to_sid(&user_sid, response.data.sid.sid);
3699
3700         init_user_token(token, &user_sid);
3701
3702         /* And now the groups winbind knows about */
3703
3704         ZERO_STRUCT(response);
3705
3706         fstrcpy(request.data.username, full_name);
3707
3708         result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
3709
3710         if (result != NSS_STATUS_SUCCESS) {
3711                 DEBUG(1, ("winbind could not get groups of %s\n", full_name));
3712                 return False;
3713         }
3714
3715         for (i = 0; i < response.data.num_entries; i++) {
3716                 gid_t gid = ((gid_t *)response.extra_data)[i];
3717                 DOM_SID sid;
3718
3719                 struct winbindd_request sidrequest;
3720                 struct winbindd_response sidresponse;
3721
3722                 ZERO_STRUCT(sidrequest);
3723                 ZERO_STRUCT(sidresponse);
3724
3725                 sidrequest.data.gid = gid;
3726
3727                 result = winbindd_request_response(WINBINDD_GID_TO_SID,
3728                                           &sidrequest, &sidresponse);
3729
3730                 if (result != NSS_STATUS_SUCCESS) {
3731                         DEBUG(1, ("winbind could not find SID of gid %d\n",
3732                                   gid));
3733                         return False;
3734                 }
3735
3736                 DEBUG(3, (" %s\n", sidresponse.data.sid.sid));
3737
3738                 string_to_sid(&sid, sidresponse.data.sid.sid);
3739                 add_sid_to_token(token, &sid);
3740         }
3741
3742         SAFE_FREE(response.extra_data);
3743
3744         return True;
3745 }
3746         
3747 /**
3748  * Get a list of all user tokens we want to look at
3749  **/
3750 static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens)
3751 {
3752         struct winbindd_request request;
3753         struct winbindd_response response;
3754         const char *extra_data;
3755         fstring name;
3756         int i;
3757         struct user_token *result;
3758
3759         if (lp_winbind_use_default_domain() &&
3760             (opt_target_workgroup == NULL)) {
3761                 d_printf("winbind use default domain = yes set, please "
3762                          "specify a workgroup\n");
3763                 return False;
3764         }
3765
3766         /* Send request to winbind daemon */
3767
3768         ZERO_STRUCT(request);
3769         ZERO_STRUCT(response);
3770         
3771         if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
3772             NSS_STATUS_SUCCESS)
3773                 return False;
3774
3775         /* Look through extra data */
3776
3777         if (!response.extra_data)
3778                 return False;
3779
3780         extra_data = (const char *)response.extra_data;
3781         *num_tokens = 0;
3782
3783         while(next_token(&extra_data, name, ",", sizeof(fstring))) {
3784                 *num_tokens += 1;
3785         }
3786
3787         result = SMB_MALLOC_ARRAY(struct user_token, *num_tokens);
3788
3789         if (result == NULL) {
3790                 DEBUG(1, ("Could not malloc sid array\n"));
3791                 return False;
3792         }
3793
3794         extra_data = (const char *)response.extra_data;
3795         i=0;
3796
3797         while(next_token(&extra_data, name, ",", sizeof(fstring))) {
3798
3799                 fstring domain, user;
3800                 char *p;
3801
3802                 fstrcpy(result[i].name, name);
3803
3804                 p = strchr(name, *lp_winbind_separator());
3805
3806                 DEBUG(3, ("%s\n", name));
3807
3808                 if (p == NULL) {
3809                         fstrcpy(domain, opt_target_workgroup);
3810                         fstrcpy(user, name);
3811                 } else {
3812                         *p++ = '\0';
3813                         fstrcpy(domain, name);
3814                         strupper_m(domain);
3815                         fstrcpy(user, p);
3816                 }
3817
3818                 get_user_sids(domain, user, &(result[i].token));
3819                 i+=1;
3820         }
3821         
3822         SAFE_FREE(response.extra_data);
3823
3824         *user_tokens = result;
3825
3826         return True;
3827 }
3828
3829 static BOOL get_user_tokens_from_file(FILE *f,
3830                                       int *num_tokens,
3831                                       struct user_token **tokens)
3832 {
3833         struct user_token *token = NULL;
3834
3835         while (!feof(f)) {
3836                 fstring line;
3837
3838                 if (fgets(line, sizeof(line)-1, f) == NULL) {
3839                         return True;
3840                 }
3841
3842                 if (line[strlen(line)-1] == '\n')
3843                         line[strlen(line)-1] = '\0';
3844
3845                 if (line[0] == ' ') {
3846                         /* We have a SID */
3847
3848                         DOM_SID sid;
3849                         string_to_sid(&sid, &line[1]);
3850
3851                         if (token == NULL) {
3852                                 DEBUG(0, ("File does not begin with username"));
3853                                 return False;
3854                         }
3855
3856                         add_sid_to_token(&token->token, &sid);
3857                         continue;
3858                 }
3859
3860                 /* And a new user... */
3861
3862                 *num_tokens += 1;
3863                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
3864                 if (*tokens == NULL) {
3865                         DEBUG(0, ("Could not realloc tokens\n"));
3866                         return False;
3867                 }
3868
3869                 token = &((*tokens)[*num_tokens-1]);
3870
3871                 fstrcpy(token->name, line);
3872                 token->token.num_sids = 0;
3873                 token->token.user_sids = NULL;
3874                 continue;
3875         }
3876         
3877         return False;
3878 }
3879
3880
3881 /*
3882  * Show the list of all users that have access to a share
3883  */
3884
3885 static void show_userlist(struct cli_state *cli,
3886                           TALLOC_CTX *mem_ctx, const char *netname,
3887                           int num_tokens, struct user_token *tokens)
3888 {
3889         int fnum;
3890         SEC_DESC *share_sd = NULL;
3891         SEC_DESC *root_sd = NULL;
3892         int i;
3893         SRV_SHARE_INFO info;
3894         WERROR result;
3895         uint16 cnum;
3896
3897         result = cli_srvsvc_net_share_get_info(cli, mem_ctx, netname,
3898                                                502, &info);
3899
3900         if (!W_ERROR_IS_OK(result)) {
3901                 DEBUG(1, ("Coult not query secdesc for share %s\n",
3902                           netname));
3903                 return;
3904         }
3905
3906         share_sd = info.share.info502.info_502_str.sd;
3907         if (share_sd == NULL) {
3908                 DEBUG(1, ("Got no secdesc for share %s\n",
3909                           netname));
3910         }
3911
3912         cnum = cli->cnum;
3913
3914         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
3915                 return;
3916         }
3917
3918         fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
3919
3920         if (fnum != -1) {
3921                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
3922         }
3923
3924         for (i=0; i<num_tokens; i++) {
3925                 uint32 acc_granted;
3926                 NTSTATUS status;
3927
3928                 if (share_sd != NULL) {
3929                         if (!se_access_check(share_sd, &tokens[i].token,
3930                                              1, &acc_granted, &status)) {
3931                                 DEBUG(1, ("Could not check share_sd for "
3932                                           "user %s\n",
3933                                           tokens[i].name));
3934                                 continue;
3935                         }
3936
3937                         if (!NT_STATUS_IS_OK(status))
3938                                 continue;
3939                 }
3940
3941                 if (root_sd == NULL) {
3942                         d_printf(" %s\n", tokens[i].name);
3943                         continue;
3944                 }
3945
3946                 if (!se_access_check(root_sd, &tokens[i].token,
3947                                      1, &acc_granted, &status)) {
3948                         DEBUG(1, ("Could not check root_sd for user %s\n",
3949                                   tokens[i].name));
3950                         continue;
3951                 }
3952
3953                 if (!NT_STATUS_IS_OK(status))
3954                         continue;
3955
3956                 d_printf(" %s\n", tokens[i].name);
3957         }
3958
3959         if (fnum != -1)
3960                 cli_close(cli, fnum);
3961         cli_tdis(cli);
3962         cli->cnum = cnum;
3963         
3964         return;
3965 }
3966
3967 struct share_list {
3968         int num_shares;
3969         char **shares;
3970 };
3971
3972 static void collect_share(const char *name, uint32 m,
3973                           const char *comment, void *state)
3974 {
3975         struct share_list *share_list = (struct share_list *)state;
3976
3977         if (m != STYPE_DISKTREE)
3978                 return;
3979
3980         share_list->num_shares += 1;
3981         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
3982         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
3983 }
3984
3985 static void rpc_share_userlist_usage(void)
3986 {
3987         return;
3988 }
3989         
3990 /** 
3991  * List shares on a remote RPC server, including the security descriptors
3992  *
3993  * All parameters are provided by the run_rpc_command function, except for
3994  * argc, argv which are passes through. 
3995  *
3996  * @param domain_sid The domain sid acquired from the remote server
3997  * @param cli A cli_state connected to the server.
3998  * @param mem_ctx Talloc context, destoyed on completion of the function.
3999  * @param argc  Standard main() style argc
4000  * @param argv  Standard main() style argv.  Initial components are already
4001  *              stripped
4002  *
4003  * @return Normal NTSTATUS return.
4004  **/
4005
4006 static NTSTATUS 
4007 rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
4008                                  const char *domain_name,
4009                                  struct cli_state *cli,
4010                                  TALLOC_CTX *mem_ctx,
4011                                  int argc, const char **argv)
4012 {
4013         int ret;
4014         BOOL r;
4015         ENUM_HND hnd;
4016         uint32 i;
4017         FILE *f;
4018
4019         struct user_token *tokens = NULL;
4020         int num_tokens = 0;
4021
4022         struct share_list share_list;
4023
4024         if (argc > 1) {
4025                 rpc_share_userlist_usage();
4026                 return NT_STATUS_UNSUCCESSFUL;
4027         }
4028
4029         if (argc == 0) {
4030                 f = stdin;
4031         } else {
4032                 f = fopen(argv[0], "r");
4033         }
4034
4035         if (f == NULL) {
4036                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4037                 return NT_STATUS_UNSUCCESSFUL;
4038         }
4039
4040         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4041
4042         if (f != stdin)
4043                 fclose(f);
4044
4045         if (!r) {
4046                 DEBUG(0, ("Could not read users from file\n"));
4047                 return NT_STATUS_UNSUCCESSFUL;
4048         }
4049
4050         for (i=0; i<num_tokens; i++)
4051                 collect_alias_memberships(&tokens[i].token);
4052
4053         init_enum_hnd(&hnd, 0);
4054
4055         share_list.num_shares = 0;
4056         share_list.shares = NULL;
4057
4058         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4059
4060         if (ret == -1) {
4061                 DEBUG(0, ("Error returning browse list: %s\n",
4062                           cli_errstr(cli)));
4063                 goto done;
4064         }
4065
4066         for (i = 0; i < share_list.num_shares; i++) {
4067                 char *netname = share_list.shares[i];
4068
4069                 if (netname[strlen(netname)-1] == '$')
4070                         continue;
4071
4072                 d_printf("%s\n", netname);
4073
4074                 show_userlist(cli, mem_ctx, netname,
4075                               num_tokens, tokens);
4076         }
4077  done:
4078         for (i=0; i<num_tokens; i++) {
4079                 free_user_token(&tokens[i].token);
4080         }
4081         SAFE_FREE(tokens);
4082         SAFE_FREE(share_list.shares);
4083
4084         return NT_STATUS_OK;
4085 }
4086
4087 static int
4088 rpc_share_allowedusers(int argc, const char **argv)
4089 {
4090         int result;
4091
4092         result = run_rpc_command(NULL, PI_SAMR, 0,
4093                                  rpc_aliaslist_internals,
4094                                  argc, argv);
4095         if (result != 0)
4096                 return result;
4097
4098         result = run_rpc_command(NULL, PI_LSARPC, 0,
4099                                  rpc_aliaslist_dump,
4100                                  argc, argv);
4101         if (result != 0)
4102                 return result;
4103
4104         return run_rpc_command(NULL, PI_SRVSVC, 0,
4105                                rpc_share_allowedusers_internals,
4106                                argc, argv);
4107 }
4108
4109 int net_usersidlist(int argc, const char **argv)
4110 {
4111         int num_tokens = 0;
4112         struct user_token *tokens = NULL;
4113         int i;
4114
4115         if (argc != 0) {
4116                 net_usersidlist_usage(argc, argv);
4117                 return 0;
4118         }
4119
4120         if (!get_user_tokens(&num_tokens, &tokens)) {
4121                 DEBUG(0, ("Could not get the user/sid list\n"));
4122                 return 0;
4123         }
4124
4125         for (i=0; i<num_tokens; i++) {
4126                 dump_user_token(&tokens[i]);
4127                 free_user_token(&tokens[i].token);
4128         }
4129
4130         SAFE_FREE(tokens);
4131         return 1;
4132 }
4133
4134 int net_usersidlist_usage(int argc, const char **argv)
4135 {
4136         d_printf("net usersidlist\n"
4137                  "\tprints out a list of all users the running winbind knows\n"
4138                  "\tabout, together with all their SIDs. This is used as\n"
4139                  "\tinput to the 'net rpc share allowedusers' command.\n\n");
4140
4141         net_common_flags_usage(argc, argv);
4142         return -1;
4143 }
4144
4145 /** 
4146  * 'net rpc share' entrypoint.
4147  * @param argc  Standard main() style argc
4148  * @param argv  Standard main() style argv.  Initial components are already
4149  *              stripped
4150  **/
4151
4152 int net_rpc_share(int argc, const char **argv) 
4153 {
4154         struct functable func[] = {
4155                 {"add", rpc_share_add},
4156                 {"delete", rpc_share_delete},
4157                 {"allowedusers", rpc_share_allowedusers},
4158                 {"migrate", rpc_share_migrate},
4159                 {"list", rpc_share_list},
4160                 {NULL, NULL}
4161         };
4162
4163         if (argc == 0)
4164                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
4165                                        rpc_share_list_internals,
4166                                        argc, argv);
4167
4168         return net_run_function(argc, argv, func, rpc_share_usage);
4169 }
4170
4171 /****************************************************************************/
4172
4173 static int rpc_file_usage(int argc, const char **argv)
4174 {
4175         return net_help_file(argc, argv);
4176 }
4177
4178 /** 
4179  * Close a file on a remote RPC server
4180  *
4181  * All parameters are provided by the run_rpc_command function, except for
4182  * argc, argv which are passes through. 
4183  *
4184  * @param domain_sid The domain sid acquired from the remote server
4185  * @param cli A cli_state connected to the server.
4186  * @param mem_ctx Talloc context, destoyed on completion of the function.
4187  * @param argc  Standard main() style argc
4188  * @param argv  Standard main() style argv.  Initial components are already
4189  *              stripped
4190  *
4191  * @return Normal NTSTATUS return.
4192  **/
4193 static NTSTATUS 
4194 rpc_file_close_internals(const DOM_SID *domain_sid, const char *domain_name, 
4195                          struct cli_state *cli,
4196                          TALLOC_CTX *mem_ctx, int argc, const char **argv)
4197 {
4198         WERROR result;
4199         result = cli_srvsvc_net_file_close(cli, mem_ctx, atoi(argv[0]));
4200         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
4201 }
4202
4203 /** 
4204  * Close a file on a remote RPC server
4205  *
4206  * @param argc  Standard main() style argc
4207  * @param argv  Standard main() style argv.  Initial components are already
4208  *              stripped
4209  *
4210  * @return A shell status integer (0 for success)
4211  **/
4212 static int rpc_file_close(int argc, const char **argv)
4213 {
4214         if (argc < 1) {
4215                 DEBUG(1, ("No fileid given on close\n"));
4216                 return(rpc_file_usage(argc, argv));
4217         }
4218
4219         return run_rpc_command(NULL, PI_SRVSVC, 0, 
4220                                rpc_file_close_internals,
4221                                argc, argv);
4222 }
4223
4224 /** 
4225  * Formatted print of open file info 
4226  *
4227  * @param info3  FILE_INFO_3 contents
4228  * @param str3   strings for FILE_INFO_3
4229  **/
4230
4231 static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
4232 {
4233         fstring user = "", path = "";
4234
4235         rpcstr_pull_unistr2_fstring(user, &str3->uni_user_name);
4236         rpcstr_pull_unistr2_fstring(path, &str3->uni_path_name);
4237
4238         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
4239                  info3->id, user, info3->perms, info3->num_locks, path);
4240 }
4241
4242 /** 
4243  * List open files on a remote RPC server
4244  *
4245  * All parameters are provided by the run_rpc_command function, except for
4246  * argc, argv which are passes through. 
4247  *
4248  * @param domain_sid The domain sid acquired from the remote server
4249  * @param cli A cli_state connected to the server.
4250  * @param mem_ctx Talloc context, destoyed on completion of the function.
4251  * @param argc  Standard main() style argc
4252  * @param argv  Standard main() style argv.  Initial components are already
4253  *              stripped
4254  *
4255  * @return Normal NTSTATUS return.
4256  **/
4257
4258 static NTSTATUS 
4259 rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
4260                         struct cli_state *cli,
4261                         TALLOC_CTX *mem_ctx, int argc, const char **argv)
4262 {
4263         SRV_FILE_INFO_CTR ctr;
4264         WERROR result;
4265         ENUM_HND hnd;
4266         uint32 preferred_len = 0xffffffff, i;
4267         const char *username=NULL;
4268
4269         init_enum_hnd(&hnd, 0);
4270
4271         /* if argc > 0, must be user command */
4272         if (argc > 0)
4273                 username = smb_xstrdup(argv[0]);
4274                 
4275         result = cli_srvsvc_net_file_enum(
4276                 cli, mem_ctx, 3, username, &ctr, preferred_len, &hnd);
4277
4278         if (!W_ERROR_IS_OK(result))
4279                 goto done;
4280
4281         /* Display results */
4282
4283         d_printf(
4284                  "\nEnumerating open files on remote server:\n\n"\
4285                  "\nFileId  Opened by            Perms  Locks  Path"\
4286                  "\n------  ---------            -----  -----  ---- \n");
4287         for (i = 0; i < ctr.num_entries; i++)
4288                 display_file_info_3(&ctr.file.info3[i].info_3, 
4289                                     &ctr.file.info3[i].info_3_str);
4290  done:
4291         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
4292 }
4293
4294
4295 /** 
4296  * List files for a user on a remote RPC server
4297  *
4298  * @param argc  Standard main() style argc
4299  * @param argv  Standard main() style argv.  Initial components are already
4300  *              stripped
4301  *
4302  * @return A shell status integer (0 for success)
4303  **/
4304 static int rpc_file_user(int argc, const char **argv)
4305 {
4306         if (argc < 1) {
4307                 DEBUG(1, ("No username given\n"));
4308                 return(rpc_file_usage(argc, argv));
4309         }
4310
4311         return run_rpc_command(NULL, PI_SRVSVC, 0, 
4312                                rpc_file_list_internals,
4313                                argc, argv);
4314 }
4315
4316
4317 /** 
4318  * 'net rpc file' entrypoint.
4319  * @param argc  Standard main() style argc
4320  * @param argv  Standard main() style argv.  Initial components are already
4321  *              stripped
4322  **/
4323
4324 int net_rpc_file(int argc, const char **argv) 
4325 {
4326         struct functable func[] = {
4327                 {"close", rpc_file_close},
4328                 {"user", rpc_file_user},
4329 #if 0
4330                 {"info", rpc_file_info},
4331 #endif
4332                 {NULL, NULL}
4333         };
4334
4335         if (argc == 0)
4336                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
4337                                        rpc_file_list_internals,
4338                                        argc, argv);
4339
4340         return net_run_function(argc, argv, func, rpc_file_usage);
4341 }
4342
4343 /****************************************************************************/
4344
4345
4346
4347 /** 
4348  * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
4349  *
4350  * All parameters are provided by the run_rpc_command function, except for
4351  * argc, argv which are passed through. 
4352  *
4353  * @param domain_sid The domain sid aquired from the remote server
4354  * @param cli A cli_state connected to the server.
4355  * @param mem_ctx Talloc context, destoyed on compleation of the function.
4356  * @param argc  Standard main() style argc
4357  * @param argv  Standard main() style argv.  Initial components are already
4358  *              stripped
4359  *
4360  * @return Normal NTSTATUS return.
4361  **/
4362
4363 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, 
4364                                              const char *domain_name, 
4365                                              struct cli_state *cli, 
4366                                              TALLOC_CTX *mem_ctx, 
4367                                              int argc, const char **argv) 
4368 {
4369         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4370         
4371         result = cli_shutdown_abort(cli, mem_ctx);
4372         
4373         if (NT_STATUS_IS_OK(result)) {
4374                 d_printf("\nShutdown successfully aborted\n");
4375                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
4376         } else
4377                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
4378         
4379         return result;
4380 }
4381
4382
4383 /** 
4384  * ABORT the shutdown of a remote RPC Server,  over winreg pipe
4385  *
4386  * All parameters are provided by the run_rpc_command function, except for
4387  * argc, argv which are passed through. 
4388  *
4389  * @param domain_sid The domain sid aquired from the remote server
4390  * @param cli A cli_state connected to the server.
4391  * @param mem_ctx Talloc context, destoyed on compleation of the function.
4392  * @param argc  Standard main() style argc
4393  * @param argv  Standard main() style argv.  Initial components are already
4394  *              stripped
4395  *
4396  * @return Normal NTSTATUS return.
4397  **/
4398
4399 static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid, 
4400                                                  const char *domain_name, 
4401                                                  struct cli_state *cli, 
4402                                                  TALLOC_CTX *mem_ctx, 
4403                                                  int argc, const char **argv) 
4404 {
4405         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4406         
4407         result = werror_to_ntstatus(cli_reg_abort_shutdown(cli, mem_ctx));
4408         
4409         if (NT_STATUS_IS_OK(result)) {
4410                 d_printf("\nShutdown successfully aborted\n");
4411                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
4412         } else
4413                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
4414         
4415         return result;
4416 }
4417
4418 /** 
4419  * ABORT the Shut down of a remote RPC server
4420  *
4421  * @param argc  Standard main() style argc
4422  * @param argv  Standard main() style argv.  Initial components are already
4423  *              stripped
4424  *
4425  * @return A shell status integer (0 for success)
4426  **/
4427
4428 static int rpc_shutdown_abort(int argc, const char **argv) 
4429 {
4430         int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0, 
4431                                  rpc_shutdown_abort_internals,
4432                                  argc, argv);
4433
4434         if (rc == 0)
4435                 return rc;
4436
4437         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
4438
4439         return run_rpc_command(NULL, PI_WINREG, 0, 
4440                                rpc_reg_shutdown_abort_internals,
4441                                argc, argv);
4442 }
4443
4444 /** 
4445  * Shut down a remote RPC Server via initshutdown pipe
4446  *
4447  * All parameters are provided by the run_rpc_command function, except for
4448  * argc, argv which are passes through. 
4449  *
4450  * @param domain_sid The domain sid aquired from the remote server
4451  * @param cli A cli_state connected to the server.
4452  * @param mem_ctx Talloc context, destoyed on compleation of the function.
4453  * @param argc  Standard main() style argc
4454  * @param argc  Standard main() style argv.  Initial components are already
4455  *              stripped
4456  *
4457  * @return Normal NTSTATUS return.
4458  **/
4459
4460 static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid, 
4461                                             const char *domain_name, 
4462                                             struct cli_state *cli, 
4463                                             TALLOC_CTX *mem_ctx, 
4464                                             int argc, const char **argv) 
4465 {
4466         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4467         const char *msg = "This machine will be shutdown shortly";
4468         uint32 timeout = 20;
4469
4470         if (opt_comment) {
4471                 msg = opt_comment;
4472         } else {
4473                 msg = "";
4474         }
4475
4476         if (opt_timeout) {
4477                 timeout = opt_timeout;
4478         }
4479
4480         /* create an entry */
4481         result = cli_shutdown_init(cli, mem_ctx, msg, timeout, opt_reboot, 
4482                                    opt_force);
4483
4484         if (NT_STATUS_IS_OK(result)) {
4485                 d_printf("\nShutdown of remote machine succeeded\n");
4486                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
4487         } else
4488                 DEBUG(0,("Shutdown of remote machine failed!\n"));
4489
4490         return result;
4491 }
4492
4493 /** 
4494  * Shut down a remote RPC Server via winreg pipe
4495  *
4496  * All parameters are provided by the run_rpc_command function, except for
4497  * argc, argv which are passes through. 
4498  *
4499  * @param domain_sid The domain sid aquired from the remote server
4500  * @param cli A cli_state connected to the server.
4501  * @param mem_ctx Talloc context, destoyed on compleation of the function.
4502  * @param argc  Standard main() style argc
4503  * @param argc  Standard main() style argv.  Initial components are already
4504  *              stripped
4505  *
4506  * @return Normal NTSTATUS return.
4507  **/
4508
4509 static NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid, 
4510                                            const char *domain_name, 
4511                                            struct cli_state *cli, 
4512                                            TALLOC_CTX *mem_ctx, 
4513                                            int argc, const char **argv) 
4514 {
4515         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4516         const char *msg = "This machine will be shutdown shortly";
4517         uint32 timeout = 20;
4518 #if 0
4519         poptContext pc;
4520         int rc;
4521
4522         struct poptOption long_options[] = {
4523                 {"message",    'm', POPT_ARG_STRING, &msg},
4524                 {"timeout",    't', POPT_ARG_INT,    &timeout},
4525                 {"reboot",     'r', POPT_ARG_NONE,   &reboot},
4526                 {"force",      'f', POPT_ARG_NONE,   &force},
4527                 { 0, 0, 0, 0}
4528         };
4529
4530         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
4531                             POPT_CONTEXT_KEEP_FIRST);
4532
4533         rc = poptGetNextOpt(pc);
4534         
4535         if (rc < -1) {
4536                 /* an error occurred during option processing */
4537                 DEBUG(0, ("%s: %s\n",
4538                           poptBadOption(pc, POPT_BADOPTION_NOALIAS),
4539                           poptStrerror(rc)));
4540                 return NT_STATUS_INVALID_PARAMETER;
4541         }
4542 #endif
4543         if (opt_comment) {
4544                 msg = opt_comment;
4545         }
4546         if (opt_timeout) {
4547                 timeout = opt_timeout;
4548         }
4549
4550         /* create an entry */
4551         result = werror_to_ntstatus(cli_reg_shutdown(cli, mem_ctx, msg, timeout, opt_reboot, opt_force));
4552
4553         if (NT_STATUS_IS_OK(result)) {
4554                 d_printf("\nShutdown of remote machine succeeded\n");
4555                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
4556         }
4557         else
4558                 DEBUG(0,("Shutdown of remote machine failed!\n"));
4559
4560         return result;
4561 }
4562
4563 /** 
4564  * Shut down a remote RPC server
4565  *
4566  * @param argc  Standard main() style argc
4567  * @param argc  Standard main() style argv.  Initial components are already
4568  *              stripped
4569  *
4570  * @return A shell status integer (0 for success)
4571  **/
4572
4573 static int rpc_shutdown(int argc, const char **argv) 
4574 {
4575         int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0, 
4576                                  rpc_init_shutdown_internals,
4577                                  argc, argv);
4578         if (rc == 0)
4579                 return rc;
4580
4581         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
4582
4583         return run_rpc_command(NULL, PI_WINREG, 0, rpc_reg_shutdown_internals,
4584                                        argc, argv);
4585 }
4586
4587 /***************************************************************************
4588   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
4589   
4590  ***************************************************************************/
4591
4592 /**
4593  * Add interdomain trust account to the RPC server.
4594  * All parameters (except for argc and argv) are passed by run_rpc_command
4595  * function.
4596  *
4597  * @param domain_sid The domain sid acquired from the server
4598  * @param cli A cli_state connected to the server.
4599  * @param mem_ctx Talloc context, destoyed on completion of the function.
4600  * @param argc  Standard main() style argc
4601  * @param argc  Standard main() style argv.  Initial components are already
4602  *              stripped
4603  *
4604  * @return normal NTSTATUS return code
4605  */
4606
4607 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, 
4608                                            const char *domain_name, 
4609                                            struct cli_state *cli, TALLOC_CTX *mem_ctx, 
4610                                            int argc, const char **argv) {
4611
4612         POLICY_HND connect_pol, domain_pol, user_pol;
4613         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4614         char *acct_name;
4615         uint16 acb_info;
4616         uint32 unknown, user_rid;
4617
4618         if (argc != 2) {
4619                 d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
4620                 return NT_STATUS_INVALID_PARAMETER;
4621         }
4622
4623         /* 
4624          * Make valid trusting domain account (ie. uppercased and with '$' appended)
4625          */
4626          
4627         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
4628                 return NT_STATUS_NO_MEMORY;
4629         }
4630
4631         strupper_m(acct_name);
4632
4633         /* Get samr policy handle */
4634         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
4635                                   &connect_pol);
4636         if (!NT_STATUS_IS_OK(result)) {
4637                 goto done;
4638         }
4639         
4640         /* Get domain policy handle */
4641         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
4642                                       MAXIMUM_ALLOWED_ACCESS,
4643                                       domain_sid, &domain_pol);
4644         if (!NT_STATUS_IS_OK(result)) {
4645                 goto done;
4646         }
4647
4648         /* Create trusting domain's account */
4649         acb_info = ACB_NORMAL; 
4650         unknown = 0xe00500b0; /* No idea what this is - a permission mask?
4651                                  mimir: yes, most probably it is */
4652
4653         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
4654                                           acct_name, acb_info, unknown,
4655                                           &user_pol, &user_rid);
4656         if (!NT_STATUS_IS_OK(result)) {
4657                 goto done;
4658         }
4659
4660         {
4661                 SAM_USERINFO_CTR ctr;
4662                 SAM_USER_INFO_23 p23;
4663                 NTTIME notime;
4664                 char nostr[] = "";
4665                 LOGON_HRS hrs;
4666                 uchar pwbuf[516];
4667
4668                 encode_pw_buffer((char *)pwbuf, argv[1], STR_UNICODE);
4669
4670                 ZERO_STRUCT(ctr);
4671                 ZERO_STRUCT(p23);
4672                 ZERO_STRUCT(notime);
4673                 hrs.max_len = 1260;
4674                 hrs.offset = 0;
4675                 hrs.len = 21;
4676                 memset(hrs.hours, 0xFF, sizeof(hrs.hours));
4677                 acb_info = ACB_DOMTRUST;
4678
4679                 init_sam_user_info23A(&p23, &notime, &notime, &notime,
4680                                       &notime, &notime, &notime,
4681                                       nostr, nostr, nostr, nostr, nostr,
4682                                       nostr, nostr, nostr, nostr, nostr,
4683                                       0, 0, acb_info, ACCT_FLAGS, 168, &hrs, 
4684                                       0, 0, (char *)pwbuf);
4685                 ctr.switch_value = 23;
4686                 ctr.info.id23 = &p23;
4687                 p23.passmustchange = 0;
4688
4689                 result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 23,
4690                                                &cli->user_session_key, &ctr);
4691
4692                 if (!NT_STATUS_IS_OK(result)) {
4693                         DEBUG(0,("Could not set trust account password: %s\n",
4694                                  nt_errstr(result)));
4695                         goto done;
4696                 }
4697         }
4698
4699  done:
4700         SAFE_FREE(acct_name);
4701         return result;
4702 }
4703
4704 /**
4705  * Create interdomain trust account for a remote domain.
4706  *
4707  * @param argc standard argc
4708  * @param argv standard argv without initial components
4709  *
4710  * @return Integer status (0 means success)
4711  **/
4712
4713 static int rpc_trustdom_add(int argc, const char **argv)
4714 {
4715         if (argc > 0) {
4716                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
4717                                        argc, argv);
4718         } else {
4719                 d_printf("Usage: net rpc trustdom add <domain>\n");
4720                 return -1;
4721         }
4722 }
4723
4724
4725 /**
4726  * Remove interdomain trust account from the RPC server.
4727  * All parameters (except for argc and argv) are passed by run_rpc_command
4728  * function.
4729  *
4730  * @param domain_sid The domain sid acquired from the server
4731  * @param cli A cli_state connected to the server.
4732  * @param mem_ctx Talloc context, destoyed on completion of the function.
4733  * @param argc  Standard main() style argc
4734  * @param argc  Standard main() style argv.  Initial components are already
4735  *              stripped
4736  *
4737  * @return normal NTSTATUS return code
4738  */
4739
4740 static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, 
4741                                            const char *domain_name, 
4742                                            struct cli_state *cli, TALLOC_CTX *mem_ctx, 
4743                                            int argc, const char **argv) {
4744
4745         POLICY_HND connect_pol, domain_pol, user_pol;
4746         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4747         char *acct_name;
4748         const char **names;
4749         DOM_SID trust_acct_sid;
4750         uint32 *user_rids, num_rids, *name_types;
4751         uint32 flags = 0x000003e8; /* Unknown */
4752
4753         if (argc != 1) {
4754                 d_printf("Usage: net rpc trustdom del <domain_name>\n");
4755                 return NT_STATUS_INVALID_PARAMETER;
4756         }
4757
4758         /* 
4759          * Make valid trusting domain account (ie. uppercased and with '$' appended)
4760          */
4761         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
4762
4763         if (acct_name == NULL)
4764                 return NT_STATUS_NO_MEMORY;
4765
4766         strupper_m(acct_name);
4767
4768         names = TALLOC_ARRAY(mem_ctx, const char *, 1);
4769         names[0] = acct_name;
4770
4771
4772         /* Get samr policy handle */
4773         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
4774                                   &connect_pol);
4775         if (!NT_STATUS_IS_OK(result)) {
4776                 goto done;
4777         }
4778         
4779         /* Get domain policy handle */
4780         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
4781                                       MAXIMUM_ALLOWED_ACCESS,
4782                                       domain_sid, &domain_pol);
4783         if (!NT_STATUS_IS_OK(result)) {
4784                 goto done;
4785         }
4786
4787         result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, 1,
4788                                        names, &num_rids,
4789                                        &user_rids, &name_types);
4790         
4791         if (!NT_STATUS_IS_OK(result)) {
4792                 goto done;
4793         }
4794
4795         result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
4796                                     MAXIMUM_ALLOWED_ACCESS,
4797                                     user_rids[0], &user_pol);
4798
4799         if (!NT_STATUS_IS_OK(result)) {
4800                 goto done;
4801         }
4802
4803         /* append the rid to the domain sid */
4804         sid_copy(&trust_acct_sid, domain_sid);
4805         if (!sid_append_rid(&trust_acct_sid, user_rids[0])) {
4806                 goto done;
4807         }
4808
4809         /* remove the sid */
4810
4811         result = cli_samr_remove_sid_foreign_domain(cli, mem_ctx, &user_pol,
4812                                                     &trust_acct_sid);
4813
4814         if (!NT_STATUS_IS_OK(result)) {
4815                 goto done;
4816         }
4817
4818         /* Delete user */
4819
4820         result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
4821
4822         if (!NT_STATUS_IS_OK(result)) {
4823                 goto done;
4824         }
4825
4826         if (!NT_STATUS_IS_OK(result)) {
4827           DEBUG(0,("Could not set trust account password: %s\n",
4828                    nt_errstr(result)));
4829           goto done;
4830         }
4831
4832  done:
4833         return result;
4834 }
4835
4836 /**
4837  * Delete interdomain trust account for a remote domain.
4838  *
4839  * @param argc standard argc
4840  * @param argv standard argv without initial components
4841  *
4842  * @return Integer status (0 means success)
4843  **/
4844
4845 static int rpc_trustdom_del(int argc, const char **argv)
4846 {
4847         if (argc > 0) {
4848                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_del_internals,
4849                                        argc, argv);
4850         } else {
4851                 d_printf("Usage: net rpc trustdom del <domain>\n");
4852                 return -1;
4853         }
4854 }
4855  
4856
4857 /**
4858  * Establish trust relationship to a trusting domain.
4859  * Interdomain account must already be created on remote PDC.
4860  *
4861  * @param argc standard argc
4862  * @param argv standard argv without initial components
4863  *
4864  * @return Integer status (0 means success)
4865  **/
4866
4867 static int rpc_trustdom_establish(int argc, const char **argv)
4868 {
4869         struct cli_state *cli;
4870         struct in_addr server_ip;
4871         POLICY_HND connect_hnd;
4872         TALLOC_CTX *mem_ctx;
4873         NTSTATUS nt_status;
4874         DOM_SID *domain_sid;
4875         smb_ucs2_t *uni_domain_name;
4876         
4877         char* domain_name;
4878         char* domain_name_pol;
4879         char* acct_name;
4880         fstring pdc_name;
4881
4882         /*
4883          * Connect to \\server\ipc$ as 'our domain' account with password
4884          */
4885
4886         if (argc != 1) {
4887                 d_printf("Usage: net rpc trustdom establish <domain_name>\n");
4888                 return -1;
4889         }
4890
4891         domain_name = smb_xstrdup(argv[0]);
4892         strupper_m(domain_name);
4893
4894         /* account name used at first is our domain's name with '$' */
4895         asprintf(&acct_name, "%s$", lp_workgroup());
4896         strupper_m(acct_name);
4897         
4898         /*
4899          * opt_workgroup will be used by connection functions further,
4900          * hence it should be set to remote domain name instead of ours
4901          */
4902         if (opt_workgroup) {
4903                 opt_workgroup = smb_xstrdup(domain_name);
4904         };
4905         
4906         opt_user_name = acct_name;
4907
4908         /* find the domain controller */
4909         if (!net_find_pdc(&server_ip, pdc_name, domain_name)) {
4910                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
4911                 return -1;
4912         }
4913
4914         /* connect to ipc$ as username/password */
4915         nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
4916         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
4917
4918                 /* Is it trusting domain account for sure ? */
4919                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
4920                         nt_errstr(nt_status)));
4921                 return -1;
4922         }
4923         
4924         /*
4925          * Connect to \\server\ipc$ again (this time anonymously)
4926          */
4927         
4928         nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
4929         
4930         if (NT_STATUS_IS_ERR(nt_status)) {
4931                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
4932                         domain_name, nt_errstr(nt_status)));
4933         }
4934
4935         /*
4936          * Use NetServerEnum2 to make sure we're talking to a proper server
4937          */
4938          
4939         if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
4940                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
4941                          for domain %s\n", domain_name));
4942         }
4943          
4944         if (!(mem_ctx = talloc_init("establishing trust relationship to "
4945                                     "domain %s", domain_name))) {
4946                 DEBUG(0, ("talloc_init() failed\n"));
4947                 cli_shutdown(cli);
4948                 return -1;
4949         }
4950
4951         /*
4952          * Call LsaOpenPolicy and LsaQueryInfo
4953          */
4954          
4955         if (!cli_nt_session_open(cli, PI_LSARPC)) {
4956                 DEBUG(0, ("Could not initialise lsa pipe\n"));
4957                 cli_shutdown(cli);
4958                 return -1;
4959         }
4960
4961         nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
4962                                          &connect_hnd);
4963         if (NT_STATUS_IS_ERR(nt_status)) {
4964                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
4965                         nt_errstr(nt_status)));
4966                 return -1;
4967         }
4968
4969         /* Querying info level 5 */
4970         
4971         nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
4972                                               5 /* info level */,
4973                                               &domain_name_pol, &domain_sid);
4974         if (NT_STATUS_IS_ERR(nt_status)) {
4975                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
4976                         nt_errstr(nt_status)));
4977                 return -1;
4978         }
4979
4980         if (push_ucs2_talloc(mem_ctx, &uni_domain_name, domain_name_pol) == (size_t)-1) {
4981                 DEBUG(0, ("Could not convert domain name %s to unicode\n",
4982                           domain_name_pol));
4983                 return -1;
4984         }
4985
4986         /* There should be actually query info level 3 (following nt serv behaviour),
4987            but I still don't know if it's _really_ necessary */
4988                         
4989         /*
4990          * Store the password in secrets db
4991          */
4992
4993         if (!secrets_store_trusted_domain_password(domain_name,
4994                                                    uni_domain_name,
4995                                                    strlen_w(uni_domain_name)+1,
4996                                                    opt_password,
4997                                                    *domain_sid)) {
4998                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
4999                 return -1;
5000         }
5001         
5002         /*
5003          * Close the pipes and clean up
5004          */
5005          
5006         nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
5007         if (NT_STATUS_IS_ERR(nt_status)) {
5008                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5009                         nt_errstr(nt_status)));
5010                 return -1;
5011         }
5012
5013         if (cli->pipes[cli->pipe_idx].fnum)
5014                 cli_nt_session_close(cli);
5015
5016         cli_shutdown(cli);
5017          
5018         talloc_destroy(mem_ctx);
5019          
5020         d_printf("Trust to domain %s established\n", domain_name);
5021         return 0;
5022 }
5023
5024 /**
5025  * Revoke trust relationship to the remote domain
5026  *
5027  * @param argc standard argc
5028  * @param argv standard argv without initial components
5029  *
5030  * @return Integer status (0 means success)
5031  **/
5032
5033 static int rpc_trustdom_revoke(int argc, const char **argv)
5034 {
5035         char* domain_name;
5036
5037         if (argc < 1) return -1;
5038         
5039         /* generate upper cased domain name */
5040         domain_name = smb_xstrdup(argv[0]);
5041         strupper_m(domain_name);
5042
5043         /* delete password of the trust */
5044         if (!trusted_domain_password_delete(domain_name)) {
5045                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
5046                           domain_name));
5047                 return -1;
5048         };
5049         
5050         return 0;
5051 }
5052
5053 /**
5054  * Usage for 'net rpc trustdom' command
5055  *
5056  * @param argc standard argc
5057  * @param argv standard argv without inital components
5058  *
5059  * @return Integer status returned to shell
5060  **/
5061  
5062 static int rpc_trustdom_usage(int argc, const char **argv)
5063 {
5064         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
5065         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
5066         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
5067         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
5068         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
5069         d_printf("  net rpc trustdom vampire \t vampire interdomain trust relationships from remote server\n");
5070         return -1;
5071 }
5072
5073
5074 static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, 
5075                                      const char *domain_name, 
5076                                      struct cli_state *cli, TALLOC_CTX *mem_ctx,
5077                                      int argc, const char **argv)
5078 {
5079         fstring str_sid;
5080         sid_to_string(str_sid, domain_sid);
5081         d_printf("%s\n", str_sid);
5082         return NT_STATUS_OK;
5083 }
5084
5085 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
5086 {
5087         fstring ascii_sid, padding;
5088         int pad_len, col_len = 20;
5089
5090         /* convert sid into ascii string */
5091         sid_to_string(ascii_sid, dom_sid);
5092
5093         /* calculate padding space for d_printf to look nicer */
5094         pad_len = col_len - strlen(trusted_dom_name);
5095         padding[pad_len] = 0;
5096         do padding[--pad_len] = ' '; while (pad_len);
5097                         
5098         d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
5099 }
5100
5101 static NTSTATUS vampire_trusted_domain(struct cli_state *cli, 
5102                                       TALLOC_CTX *mem_ctx, 
5103                                       POLICY_HND *pol, 
5104                                       DOM_SID dom_sid, 
5105                                       const char *trusted_dom_name)
5106 {
5107         NTSTATUS nt_status;
5108         LSA_TRUSTED_DOMAIN_INFO *info;
5109         char *cleartextpwd = NULL;
5110         DATA_BLOB data;
5111         smb_ucs2_t *uni_dom_name;
5112
5113         nt_status = cli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, pol, 4, &dom_sid, &info);
5114         
5115         if (NT_STATUS_IS_ERR(nt_status)) {
5116                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5117                 nt_errstr(nt_status)));
5118                 goto done;
5119         }
5120
5121         data = data_blob(NULL, info->password.password.length);
5122
5123         memcpy(data.data, info->password.password.data, info->password.password.length);
5124         data.length     = info->password.password.length;
5125                                 
5126         cleartextpwd = decrypt_trustdom_secret(cli->pwd.password, &data);
5127
5128         if (cleartextpwd == NULL) {
5129                 DEBUG(0,("retrieved NULL password\n"));
5130                 nt_status = NT_STATUS_UNSUCCESSFUL;
5131                 goto done;
5132         }
5133         
5134         if (push_ucs2_talloc(mem_ctx, &uni_dom_name, trusted_dom_name) == (size_t)-1) {
5135                 DEBUG(0, ("Could not convert domain name %s to unicode\n",
5136                           trusted_dom_name));
5137                 nt_status = NT_STATUS_UNSUCCESSFUL;
5138                 goto done;
5139         }
5140
5141         if (!secrets_store_trusted_domain_password(trusted_dom_name,
5142                                                    uni_dom_name,
5143                                                    strlen_w(uni_dom_name)+1,
5144                                                    cleartextpwd,
5145                                                    dom_sid)) {
5146                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5147                 nt_status = NT_STATUS_UNSUCCESSFUL;
5148                 goto done;
5149         }
5150
5151         DEBUG(100,("sucessfully vampired trusted domain [%s], sid: [%s], password: [%s]\n",  
5152                 trusted_dom_name, sid_string_static(&dom_sid), cleartextpwd));
5153
5154 done:
5155         SAFE_FREE(cleartextpwd);
5156         data_blob_free(&data);
5157
5158         return nt_status;
5159 }
5160
5161 static int rpc_trustdom_vampire(int argc, const char **argv)
5162 {
5163         /* common variables */
5164         TALLOC_CTX* mem_ctx;
5165         struct cli_state *cli;
5166         NTSTATUS nt_status;
5167         const char *domain_name = NULL;
5168         DOM_SID *queried_dom_sid;
5169         POLICY_HND connect_hnd;
5170
5171         /* trusted domains listing variables */
5172         unsigned int num_domains, enum_ctx = 0;
5173         int i;
5174         DOM_SID *domain_sids;
5175         char **trusted_dom_names;
5176         fstring pdc_name;
5177         char *dummy;
5178
5179         /*
5180          * Listing trusted domains (stored in secrets.tdb, if local)
5181          */
5182
5183         mem_ctx = talloc_init("trust relationships vampire");
5184
5185         /*
5186          * set domain and pdc name to local samba server (default)
5187          * or to remote one given in command line
5188          */
5189
5190         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
5191                 domain_name = opt_workgroup;
5192                 opt_target_workgroup = opt_workgroup;
5193         } else {
5194                 fstrcpy(pdc_name, global_myname());
5195                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5196                 opt_target_workgroup = domain_name;
5197         };
5198
5199         /* open \PIPE\lsarpc and open policy handle */
5200         if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
5201                 DEBUG(0, ("Couldn't connect to domain controller\n"));
5202                 return -1;
5203         };
5204
5205         if (!cli_nt_session_open(cli, PI_LSARPC)) {
5206                 DEBUG(0, ("Could not initialise lsa pipe\n"));
5207                 return -1;
5208         };
5209
5210         nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
5211                                         &connect_hnd);
5212         if (NT_STATUS_IS_ERR(nt_status)) {
5213                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5214                         nt_errstr(nt_status)));
5215                 return -1;
5216         };
5217
5218         /* query info level 5 to obtain sid of a domain being queried */
5219         nt_status = cli_lsa_query_info_policy(
5220                 cli, mem_ctx, &connect_hnd, 5 /* info level */, 
5221                 &dummy, &queried_dom_sid);
5222
5223         if (NT_STATUS_IS_ERR(nt_status)) {
5224                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5225                         nt_errstr(nt_status)));
5226                 return -1;
5227         }
5228
5229         /*
5230          * Keep calling LsaEnumTrustdom over opened pipe until
5231          * the end of enumeration is reached
5232          */
5233
5234         d_printf("Vampire trusted domains:\n\n");
5235
5236         do {
5237                 nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx,
5238                                                    &num_domains,
5239                                                    &trusted_dom_names, &domain_sids);
5240                 
5241                 if (NT_STATUS_IS_ERR(nt_status)) {
5242                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
5243                                 nt_errstr(nt_status)));
5244                         return -1;
5245                 };
5246                 
5247                 for (i = 0; i < num_domains; i++) {
5248
5249                         print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
5250
5251                         nt_status = vampire_trusted_domain(cli, mem_ctx, &connect_hnd, 
5252                                                            domain_sids[i], trusted_dom_names[i]);
5253                         if (!NT_STATUS_IS_OK(nt_status))
5254                                 return -1;
5255                 };
5256
5257                 /*
5258                  * in case of no trusted domains say something rather
5259                  * than just display blank line
5260                  */
5261                 if (!num_domains) d_printf("none\n");
5262
5263         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
5264
5265         /* close this connection before doing next one */
5266         nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
5267         if (NT_STATUS_IS_ERR(nt_status)) {
5268                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
5269                         nt_errstr(nt_status)));
5270                 return -1;
5271         };
5272
5273         /* close lsarpc pipe and connection to IPC$ */
5274         cli_nt_session_close(cli);
5275         cli_shutdown(cli);
5276
5277         talloc_destroy(mem_ctx);         
5278         return 0;
5279 }
5280
5281 static int rpc_trustdom_list(int argc, const char **argv)
5282 {
5283         /* common variables */
5284         TALLOC_CTX* mem_ctx;
5285         struct cli_state *cli, *remote_cli;
5286         NTSTATUS nt_status;
5287         const char *domain_name = NULL;
5288         DOM_SID *queried_dom_sid;
5289         fstring padding;
5290         int ascii_dom_name_len;
5291         POLICY_HND connect_hnd;
5292         
5293         /* trusted domains listing variables */
5294         unsigned int num_domains, enum_ctx = 0;
5295         int i, pad_len, col_len = 20;
5296         DOM_SID *domain_sids;
5297         char **trusted_dom_names;
5298         fstring pdc_name;
5299         char *dummy;
5300         
5301         /* trusting domains listing variables */
5302         POLICY_HND domain_hnd;
5303         char **trusting_dom_names;
5304         uint32 *trusting_dom_rids;
5305         
5306         /*
5307          * Listing trusted domains (stored in secrets.tdb, if local)
5308          */
5309
5310         mem_ctx = talloc_init("trust relationships listing");
5311
5312         /*
5313          * set domain and pdc name to local samba server (default)
5314          * or to remote one given in command line
5315          */
5316         
5317         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
5318                 domain_name = opt_workgroup;
5319                 opt_target_workgroup = opt_workgroup;
5320         } else {
5321                 fstrcpy(pdc_name, global_myname());
5322                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5323                 opt_target_workgroup = domain_name;
5324         };
5325
5326         /* open \PIPE\lsarpc and open policy handle */
5327         if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
5328                 DEBUG(0, ("Couldn't connect to domain controller\n"));
5329                 return -1;
5330         };
5331
5332         if (!cli_nt_session_open(cli, PI_LSARPC)) {
5333                 DEBUG(0, ("Could not initialise lsa pipe\n"));
5334                 return -1;
5335         };
5336
5337         nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
5338                                         &connect_hnd);
5339         if (NT_STATUS_IS_ERR(nt_status)) {
5340                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5341                         nt_errstr(nt_status)));
5342                 return -1;
5343         };
5344         
5345         /* query info level 5 to obtain sid of a domain being queried */
5346         nt_status = cli_lsa_query_info_policy(
5347                 cli, mem_ctx, &connect_hnd, 5 /* info level */, 
5348                 &dummy, &queried_dom_sid);
5349
5350         if (NT_STATUS_IS_ERR(nt_status)) {
5351                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5352                         nt_errstr(nt_status)));
5353                 return -1;
5354         }
5355                 
5356         /*
5357          * Keep calling LsaEnumTrustdom over opened pipe until
5358          * the end of enumeration is reached
5359          */
5360          
5361         d_printf("Trusted domains list:\n\n");
5362
5363         do {
5364                 nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx,
5365                                                    &num_domains,
5366                                                    &trusted_dom_names, &domain_sids);
5367                 
5368                 if (NT_STATUS_IS_ERR(nt_status)) {
5369                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
5370                                 nt_errstr(nt_status)));
5371                         return -1;
5372                 };
5373                 
5374                 for (i = 0; i < num_domains; i++) {
5375                         print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
5376                 };
5377                 
5378                 /*
5379                  * in case of no trusted domains say something rather
5380                  * than just display blank line
5381                  */
5382                 if (!num_domains) d_printf("none\n");
5383
5384         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
5385
5386         /* close this connection before doing next one */
5387         nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
5388         if (NT_STATUS_IS_ERR(nt_status)) {
5389                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
5390                         nt_errstr(nt_status)));
5391                 return -1;
5392         };
5393         
5394         cli_nt_session_close(cli);
5395
5396         /*
5397          * Listing trusting domains (stored in passdb backend, if local)
5398          */
5399         
5400         d_printf("\nTrusting domains list:\n\n");
5401
5402         /*
5403          * Open \PIPE\samr and get needed policy handles
5404          */
5405         if (!cli_nt_session_open(cli, PI_SAMR)) {
5406                 DEBUG(0, ("Could not initialise samr pipe\n"));
5407                 return -1;
5408         };
5409         
5410         /* SamrConnect */
5411         nt_status = cli_samr_connect(cli, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN,
5412                                                                  &connect_hnd);
5413         if (!NT_STATUS_IS_OK(nt_status)) {
5414                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
5415                         nt_errstr(nt_status)));
5416                 return -1;
5417         };
5418         
5419         /* SamrOpenDomain - we have to open domain policy handle in order to be
5420            able to enumerate accounts*/
5421         nt_status = cli_samr_open_domain(cli, mem_ctx, &connect_hnd,
5422                                          SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
5423                                          queried_dom_sid, &domain_hnd);                                                                  
5424         if (!NT_STATUS_IS_OK(nt_status)) {
5425                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
5426                         nt_errstr(nt_status)));
5427                 return -1;
5428         };
5429         
5430         /*
5431          * perform actual enumeration
5432          */
5433          
5434         enum_ctx = 0;   /* reset enumeration context from last enumeration */
5435         do {
5436                         
5437                 nt_status = cli_samr_enum_dom_users(cli, mem_ctx, &domain_hnd,
5438                                                     &enum_ctx, ACB_DOMTRUST, 0xffff,
5439                                                     &trusting_dom_names, &trusting_dom_rids,
5440                                                     &num_domains);
5441                 if (NT_STATUS_IS_ERR(nt_status)) {
5442                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
5443                                 nt_errstr(nt_status)));
5444                         return -1;
5445                 };
5446                 
5447                 for (i = 0; i < num_domains; i++) {
5448
5449                         /*
5450                          * get each single domain's sid (do we _really_ need this ?):
5451                          *  1) connect to domain's pdc
5452                          *  2) query the pdc for domain's sid
5453                          */
5454
5455                         /* get rid of '$' tail */
5456                         ascii_dom_name_len = strlen(trusting_dom_names[i]);
5457                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
5458                                 trusting_dom_names[i][ascii_dom_name_len - 1] = '\0';
5459                         
5460                         /* calculate padding space for d_printf to look nicer */
5461                         pad_len = col_len - strlen(trusting_dom_names[i]);
5462                         padding[pad_len] = 0;
5463                         do padding[--pad_len] = ' '; while (pad_len);
5464
5465                         /* set opt_* variables to remote domain */
5466                         strupper_m(trusting_dom_names[i]);
5467                         opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]);
5468                         opt_target_workgroup = opt_workgroup;
5469                         
5470                         d_printf("%s%s", trusting_dom_names[i], padding);
5471                         
5472                         /* connect to remote domain controller */
5473                         remote_cli = net_make_ipc_connection(NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS);
5474                         if (remote_cli) {                       
5475                                 /* query for domain's sid */
5476                                 if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
5477                                         d_printf("couldn't get domain's sid\n");
5478
5479                                 cli_shutdown(remote_cli);
5480                         
5481                         } else {
5482                                 d_printf("domain controller is not responding\n");
5483                         };
5484                 };
5485                 
5486                 if (!num_domains) d_printf("none\n");
5487                 
5488         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
5489
5490         /* close opened samr and domain policy handles */
5491         nt_status = cli_samr_close(cli, mem_ctx, &domain_hnd);
5492         if (!NT_STATUS_IS_OK(nt_status)) {
5493                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
5494         };
5495         
5496         nt_status = cli_samr_close(cli, mem_ctx, &connect_hnd);
5497         if (!NT_STATUS_IS_OK(nt_status)) {
5498                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
5499         };
5500         
5501         /* close samr pipe and connection to IPC$ */
5502         cli_nt_session_close(cli);
5503         cli_shutdown(cli);
5504
5505         talloc_destroy(mem_ctx);         
5506         return 0;
5507 }
5508
5509 /**
5510  * Entrypoint for 'net rpc trustdom' code
5511  *
5512  * @param argc standard argc
5513  * @param argv standard argv without initial components
5514  *
5515  * @return Integer status (0 means success)
5516  */
5517
5518 static int rpc_trustdom(int argc, const char **argv)
5519 {
5520         struct functable func[] = {
5521                 {"add", rpc_trustdom_add},
5522                 {"del", rpc_trustdom_del},
5523                 {"establish", rpc_trustdom_establish},
5524                 {"revoke", rpc_trustdom_revoke},
5525                 {"help", rpc_trustdom_usage},
5526                 {"list", rpc_trustdom_list},
5527                 {"vampire", rpc_trustdom_vampire},
5528                 {NULL, NULL}
5529         };
5530
5531         if (argc == 0) {
5532                 rpc_trustdom_usage(argc, argv);
5533                 return -1;
5534         }
5535
5536         return (net_run_function(argc, argv, func, rpc_user_usage));
5537 }
5538
5539 /**
5540  * Check if a server will take rpc commands
5541  * @param flags Type of server to connect to (PDC, DMB, localhost)
5542  *              if the host is not explicitly specified
5543  * @return  BOOL (true means rpc supported)
5544  */
5545 BOOL net_rpc_check(unsigned flags)
5546 {
5547         struct cli_state cli;
5548         BOOL ret = False;
5549         struct in_addr server_ip;
5550         char *server_name = NULL;
5551
5552         /* flags (i.e. server type) may depend on command */
5553         if (!net_find_server(flags, &server_ip, &server_name))
5554                 return False;
5555
5556         ZERO_STRUCT(cli);
5557         if (cli_initialise(&cli) == False)
5558                 return False;
5559
5560         if (!cli_connect(&cli, server_name, &server_ip))
5561                 goto done;
5562         if (!attempt_netbios_session_request(&cli, global_myname(), 
5563                                              server_name, &server_ip))
5564                 goto done;
5565         if (!cli_negprot(&cli))
5566                 goto done;
5567         if (cli.protocol < PROTOCOL_NT1)
5568                 goto done;
5569
5570         ret = True;
5571  done:
5572         cli_shutdown(&cli);
5573         return ret;
5574 }
5575
5576 /* dump sam database via samsync rpc calls */
5577 static int rpc_samdump(int argc, const char **argv) {
5578         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
5579                                argc, argv);
5580 }
5581
5582 /* syncronise sam database via samsync rpc calls */
5583 static int rpc_vampire(int argc, const char **argv) {
5584         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
5585                                argc, argv);
5586 }
5587
5588 /** 
5589  * Migrate everything from a print-server
5590  *
5591  * @param argc  Standard main() style argc
5592  * @param argv  Standard main() style argv.  Initial components are already
5593  *              stripped
5594  *
5595  * @return A shell status integer (0 for success)
5596  *
5597  * The order is important !
5598  * To successfully add drivers the print-queues have to exist !
5599  * Applying ACLs should be the last step, because you're easily locked out
5600  *
5601  **/
5602 static int rpc_printer_migrate_all(int argc, const char **argv)
5603 {
5604         int ret;
5605
5606         if (!opt_host) {
5607                 printf("no server to migrate\n");
5608                 return -1;
5609         }
5610
5611         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
5612         if (ret)
5613                 return ret;
5614
5615         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
5616         if (ret)
5617                 return ret;
5618
5619         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
5620         if (ret)
5621                 return ret;
5622
5623         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
5624         if (ret)
5625                 return ret;
5626
5627         return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
5628
5629 }
5630
5631 /** 
5632  * Migrate print-drivers from a print-server
5633  *
5634  * @param argc  Standard main() style argc
5635  * @param argv  Standard main() style argv.  Initial components are already
5636  *              stripped
5637  *
5638  * @return A shell status integer (0 for success)
5639  **/
5640 static int rpc_printer_migrate_drivers(int argc, const char **argv)
5641 {
5642         if (!opt_host) {
5643                 printf("no server to migrate\n");
5644                 return -1;
5645         }
5646
5647         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5648                                rpc_printer_migrate_drivers_internals,
5649                                argc, argv);
5650 }
5651
5652 /** 
5653  * Migrate print-forms from a print-server
5654  *
5655  * @param argc  Standard main() style argc
5656  * @param argv  Standard main() style argv.  Initial components are already
5657  *              stripped
5658  *
5659  * @return A shell status integer (0 for success)
5660  **/
5661 static int rpc_printer_migrate_forms(int argc, const char **argv)
5662 {
5663         if (!opt_host) {
5664                 printf("no server to migrate\n");
5665                 return -1;
5666         }
5667
5668         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5669                                rpc_printer_migrate_forms_internals,
5670                                argc, argv);
5671 }
5672
5673 /** 
5674  * Migrate printers from a print-server
5675  *
5676  * @param argc  Standard main() style argc
5677  * @param argv  Standard main() style argv.  Initial components are already
5678  *              stripped
5679  *
5680  * @return A shell status integer (0 for success)
5681  **/
5682 static int rpc_printer_migrate_printers(int argc, const char **argv)
5683 {
5684         if (!opt_host) {
5685                 printf("no server to migrate\n");
5686                 return -1;
5687         }
5688
5689         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5690                                rpc_printer_migrate_printers_internals,
5691                                argc, argv);
5692 }
5693
5694 /** 
5695  * Migrate printer-ACLs from a print-server
5696  *
5697  * @param argc  Standard main() style argc
5698  * @param argv  Standard main() style argv.  Initial components are already
5699  *              stripped
5700  *
5701  * @return A shell status integer (0 for success)
5702  **/
5703 static int rpc_printer_migrate_security(int argc, const char **argv)
5704 {
5705         if (!opt_host) {
5706                 printf("no server to migrate\n");
5707                 return -1;
5708         }
5709
5710         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5711                                rpc_printer_migrate_security_internals,
5712                                argc, argv);
5713 }
5714
5715 /** 
5716  * Migrate printer-settings from a print-server
5717  *
5718  * @param argc  Standard main() style argc
5719  * @param argv  Standard main() style argv.  Initial components are already
5720  *              stripped
5721  *
5722  * @return A shell status integer (0 for success)
5723  **/
5724 static int rpc_printer_migrate_settings(int argc, const char **argv)
5725 {
5726         if (!opt_host) {
5727                 printf("no server to migrate\n");
5728                 return -1;
5729         }
5730
5731         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5732                                rpc_printer_migrate_settings_internals,
5733                                argc, argv);
5734 }
5735
5736 /** 
5737  * 'net rpc printer' entrypoint.
5738  * @param argc  Standard main() style argc
5739  * @param argv  Standard main() style argv.  Initial components are already
5740  *              stripped
5741  **/
5742
5743 int rpc_printer_migrate(int argc, const char **argv) 
5744 {
5745
5746         /* ouch: when addriver and setdriver are called from within
5747            rpc_printer_migrate_drivers_internals, the printer-queue already
5748            *has* to exist */
5749
5750         struct functable func[] = {
5751                 {"all",         rpc_printer_migrate_all},
5752                 {"drivers",     rpc_printer_migrate_drivers},
5753                 {"forms",       rpc_printer_migrate_forms},
5754                 {"help",        rpc_printer_usage},
5755                 {"printers",    rpc_printer_migrate_printers},
5756                 {"security",    rpc_printer_migrate_security},
5757                 {"settings",    rpc_printer_migrate_settings},
5758                 {NULL, NULL}
5759         };
5760
5761         return net_run_function(argc, argv, func, rpc_printer_usage);
5762 }
5763
5764
5765 /** 
5766  * List printers on a remote RPC server
5767  *
5768  * @param argc  Standard main() style argc
5769  * @param argv  Standard main() style argv.  Initial components are already
5770  *              stripped
5771  *
5772  * @return A shell status integer (0 for success)
5773  **/
5774 static int rpc_printer_list(int argc, const char **argv)
5775 {
5776
5777         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5778                                rpc_printer_list_internals,
5779                                argc, argv);
5780 }
5781
5782 /** 
5783  * List printer-drivers on a remote RPC server
5784  *
5785  * @param argc  Standard main() style argc
5786  * @param argv  Standard main() style argv.  Initial components are already
5787  *              stripped
5788  *
5789  * @return A shell status integer (0 for success)
5790  **/
5791 static int rpc_printer_driver_list(int argc, const char **argv)
5792 {
5793
5794         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5795                                rpc_printer_driver_list_internals,
5796                                argc, argv);
5797 }
5798
5799 /** 
5800  * Publish printer in ADS via MSRPC
5801  *
5802  * @param argc  Standard main() style argc
5803  * @param argv  Standard main() style argv.  Initial components are already
5804  *              stripped
5805  *
5806  * @return A shell status integer (0 for success)
5807  **/
5808 static int rpc_printer_publish_publish(int argc, const char **argv)
5809 {
5810
5811         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5812                                rpc_printer_publish_publish_internals,
5813                                argc, argv);
5814 }
5815
5816 /** 
5817  * Update printer in ADS via MSRPC
5818  *
5819  * @param argc  Standard main() style argc
5820  * @param argv  Standard main() style argv.  Initial components are already
5821  *              stripped
5822  *
5823  * @return A shell status integer (0 for success)
5824  **/
5825 static int rpc_printer_publish_update(int argc, const char **argv)
5826 {
5827
5828         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5829                                rpc_printer_publish_update_internals,
5830                                argc, argv);
5831 }
5832
5833 /** 
5834  * UnPublish printer in ADS via MSRPC
5835  *
5836  * @param argc  Standard main() style argc
5837  * @param argv  Standard main() style argv.  Initial components are already
5838  *              stripped
5839  *
5840  * @return A shell status integer (0 for success)
5841  **/
5842 static int rpc_printer_publish_unpublish(int argc, const char **argv)
5843 {
5844
5845         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5846                                rpc_printer_publish_unpublish_internals,
5847                                argc, argv);
5848 }
5849
5850 /** 
5851  * List published printers via MSRPC
5852  *
5853  * @param argc  Standard main() style argc
5854  * @param argv  Standard main() style argv.  Initial components are already
5855  *              stripped
5856  *
5857  * @return A shell status integer (0 for success)
5858  **/
5859 static int rpc_printer_publish_list(int argc, const char **argv)
5860 {
5861
5862         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5863                                rpc_printer_publish_list_internals,
5864                                argc, argv);
5865 }
5866
5867
5868 /** 
5869  * Publish printer in ADS
5870  *
5871  * @param argc  Standard main() style argc
5872  * @param argv  Standard main() style argv.  Initial components are already
5873  *              stripped
5874  *
5875  * @return A shell status integer (0 for success)
5876  **/
5877 static int rpc_printer_publish(int argc, const char **argv)
5878 {
5879
5880         struct functable func[] = {
5881                 {"publish",     rpc_printer_publish_publish},
5882                 {"update",      rpc_printer_publish_update},
5883                 {"unpublish",   rpc_printer_publish_unpublish},
5884                 {"list",        rpc_printer_publish_list},
5885                 {"help",        rpc_printer_usage},
5886                 {NULL, NULL}
5887         };
5888
5889         if (argc == 0)
5890                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5891                                rpc_printer_publish_list_internals,
5892                                argc, argv);
5893
5894         return net_run_function(argc, argv, func, rpc_printer_usage);
5895
5896 }
5897
5898
5899 /** 
5900  * Display rpc printer help page.
5901  * @param argc  Standard main() style argc
5902  * @param argv  Standard main() style argv.  Initial components are already
5903  *              stripped
5904  **/
5905 int rpc_printer_usage(int argc, const char **argv)
5906 {
5907         return net_help_printer(argc, argv);
5908 }
5909
5910 /** 
5911  * 'net rpc printer' entrypoint.
5912  * @param argc  Standard main() style argc
5913  * @param argv  Standard main() style argv.  Initial components are already
5914  *              stripped
5915  **/
5916 int net_rpc_printer(int argc, const char **argv) 
5917 {
5918         struct functable func[] = {
5919                 {"list", rpc_printer_list},
5920                 {"migrate", rpc_printer_migrate},
5921                 {"driver", rpc_printer_driver_list},
5922                 {"publish", rpc_printer_publish},
5923                 {NULL, NULL}
5924         };
5925
5926         if (argc == 0)
5927                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
5928                                rpc_printer_list_internals,
5929                                argc, argv);
5930
5931         return net_run_function(argc, argv, func, rpc_printer_usage);
5932 }
5933
5934 /****************************************************************************/
5935
5936
5937 /** 
5938  * Basic usage function for 'net rpc'
5939  * @param argc  Standard main() style argc
5940  * @param argv  Standard main() style argv.  Initial components are already
5941  *              stripped
5942  **/
5943
5944 int net_rpc_usage(int argc, const char **argv) 
5945 {
5946         d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
5947         d_printf("  net rpc join \t\t\tto join a domain \n");
5948         d_printf("  net rpc oldjoin \t\t\tto join a domain created in server manager\n");
5949         d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
5950         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
5951         d_printf("  net rpc password <username> [<password>] -Uadmin_username%%admin_pass\n");
5952         d_printf("  net rpc group \t\tto list groups\n");
5953         d_printf("  net rpc share \t\tto add, delete, list and migrate shares\n");
5954         d_printf("  net rpc printer \t\tto list and migrate printers\n");
5955         d_printf("  net rpc file \t\t\tto list open files\n");
5956         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
5957         d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
5958         d_printf("  net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
5959         d_printf("  net rpc samdump \t\tdiplay an NT PDC's users, groups and other data\n");
5960         d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
5961         d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
5962         d_printf("  net rpc shutdown \t\tto shutdown a remote server\n");
5963         d_printf("  net rpc rights\t\tto manage privileges assigned to SIDs\n");
5964         d_printf("  net rpc registry\t\tto manage registry hives\n");
5965         d_printf("  net rpc service\t\tto start, stop and query services\n");
5966         d_printf("\n");
5967         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
5968         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
5969         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
5970         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
5971         d_printf("\t-C or --comment=<message>\ttext message to display on impending shutdown\n");
5972         return -1;
5973 }
5974
5975
5976 /**
5977  * Help function for 'net rpc'.  Calls command specific help if requested
5978  * or displays usage of net rpc
5979  * @param argc  Standard main() style argc
5980  * @param argv  Standard main() style argv.  Initial components are already
5981  *              stripped
5982  **/
5983
5984 int net_rpc_help(int argc, const char **argv)
5985 {
5986         struct functable func[] = {
5987                 {"join", rpc_join_usage},
5988                 {"user", rpc_user_usage},
5989                 {"group", rpc_group_usage},
5990                 {"share", rpc_share_usage},
5991                 /*{"changetrustpw", rpc_changetrustpw_usage}, */
5992                 {"trustdom", rpc_trustdom_usage},
5993                 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
5994                 /*{"shutdown", rpc_shutdown_usage}, */
5995                 {"vampire", rpc_vampire_usage},
5996                 {NULL, NULL}
5997         };
5998
5999         if (argc == 0) {
6000                 net_rpc_usage(argc, argv);
6001                 return -1;
6002         }
6003
6004         return (net_run_function(argc, argv, func, rpc_user_usage));
6005 }
6006
6007
6008 /** 
6009  * 'net rpc' entrypoint.
6010  * @param argc  Standard main() style argc
6011  * @param argv  Standard main() style argv.  Initial components are already
6012  *              stripped
6013  **/
6014
6015 int net_rpc(int argc, const char **argv)
6016 {
6017         struct functable func[] = {
6018                 {"info", net_rpc_info},
6019                 {"join", net_rpc_join},
6020                 {"oldjoin", net_rpc_oldjoin},
6021                 {"testjoin", net_rpc_testjoin},
6022                 {"user", net_rpc_user},
6023                 {"password", rpc_user_password},
6024                 {"group", net_rpc_group},
6025                 {"share", net_rpc_share},
6026                 {"file", net_rpc_file},
6027                 {"printer", net_rpc_printer},
6028                 {"changetrustpw", net_rpc_changetrustpw},
6029                 {"trustdom", rpc_trustdom},
6030                 {"abortshutdown", rpc_shutdown_abort},
6031                 {"shutdown", rpc_shutdown},
6032                 {"samdump", rpc_samdump},
6033                 {"vampire", rpc_vampire},
6034                 {"getsid", net_rpc_getsid},
6035                 {"rights", net_rpc_rights},
6036                 {"service", net_rpc_service},
6037                 {"registry", net_rpc_registry},
6038                 {"help", net_rpc_help},
6039                 {NULL, NULL}
6040         };
6041         return net_run_function(argc, argv, func, net_rpc_usage);
6042 }