This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.
[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
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20  
21 #include "includes.h"
22 #include "../utils/net.h"
23
24 /**
25  * @file net_rpc.c
26  *
27  * @brief RPC based subcommands for the 'net' utility.
28  *
29  * This file should contain much of the functionality that used to
30  * be found in rpcclient, execpt that the commands should change 
31  * less often, and the fucntionality should be sane (the user is not 
32  * expected to know a rid/sid before they conduct an operation etc.)
33  *
34  * @todo Perhaps eventually these should be split out into a number
35  * of files, as this could get quite big.
36  **/
37
38
39 /* A function of this type is passed to the 'run_rpc_command' wrapper */
40 typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, struct cli_state *, TALLOC_CTX *, int, const char **);
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)
52 {
53         DOM_SID *domain_sid;
54         POLICY_HND pol;
55         NTSTATUS result = NT_STATUS_OK;
56         uint32 info_class = 5;
57         fstring domain_name;
58         TALLOC_CTX *mem_ctx;
59         
60         if (!(domain_sid = malloc(sizeof(DOM_SID)))){
61                 DEBUG(0,("net_get_remote_domain_sid: malloc returned NULL!\n"));
62                 goto error;
63         }
64             
65         if (!(mem_ctx=talloc_init("net_get_remote_domain_sid")))
66         {
67                 DEBUG(0,("net_get_remote_domain_sid: talloc_init returned NULL!\n"));
68                 goto error;
69         }
70
71
72         if (!cli_nt_session_open (cli, PI_LSARPC)) {
73                 fprintf(stderr, "could not initialise lsa pipe\n");
74                 goto error;
75         }
76         
77         result = cli_lsa_open_policy(cli, mem_ctx, False, 
78                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
79                                      &pol);
80         if (!NT_STATUS_IS_OK(result)) {
81                 goto error;
82         }
83
84         result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, 
85                                            domain_name, domain_sid);
86         if (!NT_STATUS_IS_OK(result)) {
87                 goto error;
88         }
89
90         cli_lsa_close(cli, mem_ctx, &pol);
91         cli_nt_session_close(cli);
92         talloc_destroy(mem_ctx);
93
94         return domain_sid;
95
96  error:
97         fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
98
99         if (!NT_STATUS_IS_OK(result)) {
100                 fprintf(stderr, "error: %s\n", nt_errstr(result));
101         }
102
103         exit(1);
104 }
105
106 /**
107  * Run a single RPC command, from start to finish.
108  *
109  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
110  * @param conn_flag a NET_FLAG_ combination.  Passed to 
111  *                   net_make_ipc_connection.
112  * @param argc  Standard main() style argc
113  * @param argc  Standard main() style argv.  Initial components are already
114  *              stripped
115  * @return A shell status integer (0 for success)
116  */
117
118 static int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int conn_flags,
119                            rpc_command_fn fn,
120                            int argc, const char **argv) 
121 {
122         struct cli_state *cli = NULL;
123         TALLOC_CTX *mem_ctx;
124         NTSTATUS nt_status;
125         DOM_SID *domain_sid;
126
127         /* make use of cli_state handed over as an argument, if possible */
128         if (!cli_arg)
129                 cli = net_make_ipc_connection(conn_flags);
130         else
131                 cli = cli_arg;
132
133         if (!cli) {
134                 return -1;
135         }
136
137         domain_sid = net_get_remote_domain_sid(cli);
138
139         /* Create mem_ctx */
140         
141         if (!(mem_ctx = talloc_init("run_rpc_command"))) {
142                 DEBUG(0, ("talloc_init() failed\n"));
143                 cli_shutdown(cli);
144                 return -1;
145         }
146         
147         if (!cli_nt_session_open(cli, pipe_idx)) {
148                 DEBUG(0, ("Could not initialise pipe\n"));
149         }
150         
151         nt_status = fn(domain_sid, cli, mem_ctx, argc, argv);
152         
153         if (!NT_STATUS_IS_OK(nt_status)) {
154                 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
155         } else {
156                 DEBUG(5, ("rpc command function succedded\n"));
157         }
158                 
159             
160         if (cli->nt_pipe_fnum)
161                 cli_nt_session_close(cli);
162         
163         /* close the connection only if it was opened here */
164         if (!cli_arg)
165                 cli_shutdown(cli);
166         
167         talloc_destroy(mem_ctx);
168
169         return (!NT_STATUS_IS_OK(nt_status));
170 }
171
172
173 /****************************************************************************/
174
175
176 /** 
177  * Force a change of the trust acccount password.
178  *
179  * All parameters are provided by the run_rpc_command function, except for
180  * argc, argv which are passes through. 
181  *
182  * @param domain_sid The domain sid aquired from the remote server
183  * @param cli A cli_state connected to the server.
184  * @param mem_ctx Talloc context, destoyed on compleation of the function.
185  * @param argc  Standard main() style argc
186  * @param argc  Standard main() style argv.  Initial components are already
187  *              stripped
188  *
189  * @return Normal NTSTATUS return.
190  **/
191
192 static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
193                                        int argc, const char **argv) {
194         
195         return trust_pw_find_change_and_store_it(cli, mem_ctx, opt_target_workgroup);
196 }
197
198 /** 
199  * Force a change of the trust acccount password.
200  *
201  * @param argc  Standard main() style argc
202  * @param argc  Standard main() style argv.  Initial components are already
203  *              stripped
204  *
205  * @return A shell status integer (0 for success)
206  **/
207
208 int net_rpc_changetrustpw(int argc, const char **argv) 
209 {
210         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_changetrustpw_internals,
211                                argc, argv);
212 }
213
214
215 /****************************************************************************/
216
217
218 /** 
219  * Join a domain, the old way.
220  *
221  * This uses 'machinename' as the inital password, and changes it. 
222  *
223  * The password should be created with 'server manager' or equiv first.
224  *
225  * All parameters are provided by the run_rpc_command function, except for
226  * argc, argv which are passes through. 
227  *
228  * @param domain_sid The domain sid aquired from the remote server
229  * @param cli A cli_state connected to the server.
230  * @param mem_ctx Talloc context, destoyed on compleation of the function.
231  * @param argc  Standard main() style argc
232  * @param argc  Standard main() style argv.  Initial components are already
233  *              stripped
234  *
235  * @return Normal NTSTATUS return.
236  **/
237
238 static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, struct cli_state *cli, 
239                                             TALLOC_CTX *mem_ctx, 
240                                             int argc, const char **argv) {
241         
242         fstring trust_passwd;
243         unsigned char orig_trust_passwd_hash[16];
244         NTSTATUS result;
245         uint32 sec_channel_type;
246
247         /* 
248            check what type of join - if the user want's to join as
249            a BDC, the server must agree that we are a BDC.
250         */
251         if (argc >= 0) {
252                 sec_channel_type = get_sec_channel_type(argv[0]);
253         } else {
254                 sec_channel_type = get_sec_channel_type(NULL);
255         }
256         
257         fstrcpy(trust_passwd, global_myname());
258         strlower(trust_passwd);
259
260         /*
261          * Machine names can be 15 characters, but the max length on
262          * a password is 14.  --jerry
263          */
264
265         trust_passwd[14] = '\0';
266
267         E_md4hash(trust_passwd, orig_trust_passwd_hash);
268
269         result = trust_pw_change_and_store_it(cli, mem_ctx, opt_target_workgroup,
270                                               orig_trust_passwd_hash,
271                                               sec_channel_type);
272
273         if (NT_STATUS_IS_OK(result))
274                 printf("Joined domain %s.\n",opt_target_workgroup);
275
276
277         if (!secrets_store_domain_sid(opt_target_workgroup, domain_sid)) {
278                 DEBUG(0, ("error storing domain sid for %s\n", opt_target_workgroup));
279                 result = NT_STATUS_UNSUCCESSFUL;
280         }
281
282         return result;
283 }
284
285 /** 
286  * Join a domain, the old way.
287  *
288  * @param argc  Standard main() style argc
289  * @param argc  Standard main() style argv.  Initial components are already
290  *              stripped
291  *
292  * @return A shell status integer (0 for success)
293  **/
294
295 static int net_rpc_oldjoin(int argc, const char **argv) 
296 {
297         return run_rpc_command(NULL, PI_NETLOGON, 
298                                NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
299                                rpc_oldjoin_internals,
300                                argc, argv);
301 }
302
303 /** 
304  * Basic usage function for 'net rpc join'
305  * @param argc  Standard main() style argc
306  * @param argc  Standard main() style argv.  Initial components are already
307  *              stripped
308  **/
309
310 static int rpc_join_usage(int argc, const char **argv) 
311 {       
312         d_printf("net rpc join -U <username>[%%password] <type>[options]\n"\
313                  "\t to join a domain with admin username & password\n"\
314                  "\t\t password will be prompted if needed and none is specified\n"\
315                  "\t <type> can be (default MEMBER)\n"\
316                  "\t\t BDC - Join as a BDC\n"\
317                  "\t\t PDC - Join as a PDC\n"\
318                  "\t\t MEMBER - Join as a MEMBER server\n");
319
320         net_common_flags_usage(argc, argv);
321         return -1;
322 }
323
324 /** 
325  * 'net rpc join' entrypoint.
326  * @param argc  Standard main() style argc
327  * @param argc  Standard main() style argv.  Initial components are already
328  *              stripped
329  *
330  * Main 'net_rpc_join()' (where the admain username/password is used) is 
331  * in net_rpc_join.c
332  * Try to just change the password, but if that doesn't work, use/prompt
333  * for a username/password.
334  **/
335
336 int net_rpc_join(int argc, const char **argv) 
337 {
338         if ((net_rpc_oldjoin(argc, argv) == 0))
339                 return 0;
340         
341         return net_rpc_join_newstyle(argc, argv);
342 }
343
344
345
346 /** 
347  * display info about a rpc domain
348  *
349  * All parameters are provided by the run_rpc_command function, except for
350  * argc, argv which are passed through. 
351  *
352  * @param domain_sid The domain sid acquired from the remote server
353  * @param cli A cli_state connected to the server.
354  * @param mem_ctx Talloc context, destoyed on completion of the function.
355  * @param argc  Standard main() style argc
356  * @param argv  Standard main() style argv.  Initial components are already
357  *              stripped
358  *
359  * @return Normal NTSTATUS return.
360  **/
361
362 static NTSTATUS 
363 rpc_info_internals(const DOM_SID *domain_sid, struct cli_state *cli,
364                    TALLOC_CTX *mem_ctx, int argc, const char **argv)
365 {
366         POLICY_HND connect_pol, domain_pol;
367         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
368         SAM_UNK_CTR ctr;
369         fstring sid_str;
370
371         sid_to_string(sid_str, domain_sid);
372
373         /* Get sam policy handle */     
374         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
375                                   &connect_pol);
376         if (!NT_STATUS_IS_OK(result)) {
377                 goto done;
378         }
379         
380         /* Get domain policy handle */
381         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
382                                       MAXIMUM_ALLOWED_ACCESS,
383                                       domain_sid, &domain_pol);
384         if (!NT_STATUS_IS_OK(result)) {
385                 goto done;
386         }
387
388         ZERO_STRUCT(ctr);
389         result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
390                                          2, &ctr);
391         if (NT_STATUS_IS_OK(result)) {
392                 TALLOC_CTX *ctx = talloc_init("rpc_info_internals");
393                 d_printf("Domain Name: %s\n", unistr2_tdup(ctx, &ctr.info.inf2.uni_domain));
394                 d_printf("Domain SID: %s\n", sid_str);
395                 d_printf("Sequence number: %u\n", ctr.info.inf2.seq_num);
396                 d_printf("Num users: %u\n", ctr.info.inf2.num_domain_usrs);
397                 d_printf("Num domain groups: %u\n", ctr.info.inf2.num_domain_grps);
398                 d_printf("Num local groups: %u\n", ctr.info.inf2.num_local_grps);
399                 talloc_destroy(ctx);
400         }
401
402  done:
403         return result;
404 }
405
406
407 /** 
408  * 'net rpc info' entrypoint.
409  * @param argc  Standard main() style argc
410  * @param argc  Standard main() style argv.  Initial components are already
411  *              stripped
412  **/
413 int net_rpc_info(int argc, const char **argv) 
414 {
415         return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
416                                rpc_info_internals,
417                                argc, argv);
418 }
419
420
421 /** 
422  * Fetch domain SID into the local secrets.tdb
423  *
424  * All parameters are provided by the run_rpc_command function, except for
425  * argc, argv which are passes through. 
426  *
427  * @param domain_sid The domain sid acquired from the remote server
428  * @param cli A cli_state connected to the server.
429  * @param mem_ctx Talloc context, destoyed on completion of the function.
430  * @param argc  Standard main() style argc
431  * @param argv  Standard main() style argv.  Initial components are already
432  *              stripped
433  *
434  * @return Normal NTSTATUS return.
435  **/
436
437 static NTSTATUS 
438 rpc_getsid_internals(const DOM_SID *domain_sid, struct cli_state *cli,
439                    TALLOC_CTX *mem_ctx, int argc, const char **argv)
440 {
441         fstring sid_str;
442
443         sid_to_string(sid_str, domain_sid);
444         d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
445                  sid_str, lp_workgroup());
446
447         if (!secrets_store_domain_sid(global_myname(), domain_sid)) {
448                 DEBUG(0,("Can't store domain SID\n"));
449                 return NT_STATUS_UNSUCCESSFUL;
450         }
451
452         return NT_STATUS_OK;
453 }
454
455
456 /** 
457  * 'net rpc getsid' entrypoint.
458  * @param argc  Standard main() style argc
459  * @param argc  Standard main() style argv.  Initial components are already
460  *              stripped
461  **/
462 int net_rpc_getsid(int argc, const char **argv) 
463 {
464         return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
465                                rpc_getsid_internals,
466                                argc, argv);
467 }
468
469
470 /****************************************************************************/
471
472 /**
473  * Basic usage function for 'net rpc user'
474  * @param argc  Standard main() style argc.
475  * @param argv  Standard main() style argv.  Initial components are already
476  *              stripped.
477  **/
478
479 static int rpc_user_usage(int argc, const char **argv)
480 {
481         return net_help_user(argc, argv);
482 }
483
484 /** 
485  * Add a new user to a remote RPC server
486  *
487  * All parameters are provided by the run_rpc_command function, except for
488  * argc, argv which are passes through. 
489  *
490  * @param domain_sid The domain sid acquired from the remote server
491  * @param cli A cli_state connected to the server.
492  * @param mem_ctx Talloc context, destoyed on completion of the function.
493  * @param argc  Standard main() style argc
494  * @param argv  Standard main() style argv.  Initial components are already
495  *              stripped
496  *
497  * @return Normal NTSTATUS return.
498  **/
499
500 static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
501                                        int argc, const char **argv) {
502         
503         POLICY_HND connect_pol, domain_pol, user_pol;
504         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
505         const char *acct_name;
506         uint16 acb_info;
507         uint32 unknown, user_rid;
508
509         if (argc != 1) {
510                 d_printf("User must be specified\n");
511                 rpc_user_usage(argc, argv);
512                 return NT_STATUS_OK;
513         }
514
515         acct_name = argv[0];
516
517         /* Get sam policy handle */
518         
519         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
520                                   &connect_pol);
521         if (!NT_STATUS_IS_OK(result)) {
522                 goto done;
523         }
524         
525         /* Get domain policy handle */
526         
527         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
528                                       MAXIMUM_ALLOWED_ACCESS,
529                                       domain_sid, &domain_pol);
530         if (!NT_STATUS_IS_OK(result)) {
531                 goto done;
532         }
533
534         /* Create domain user */
535
536         acb_info = ACB_NORMAL;
537         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
538
539         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
540                                           acct_name, acb_info, unknown,
541                                           &user_pol, &user_rid);
542         if (!NT_STATUS_IS_OK(result)) {
543                 goto done;
544         }
545
546  done:
547         if (!NT_STATUS_IS_OK(result)) {
548                 d_printf("Failed to add user %s - %s\n", acct_name, 
549                          nt_errstr(result));
550         } else {
551                 d_printf("Added user %s\n", acct_name);
552         }
553         return result;
554 }
555
556 /** 
557  * Add a new user to a remote RPC server
558  *
559  * @param argc  Standard main() style argc
560  * @param argv  Standard main() style argv.  Initial components are already
561  *              stripped
562  *
563  * @return A shell status integer (0 for success)
564  **/
565
566 static int rpc_user_add(int argc, const char **argv) 
567 {
568         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_add_internals,
569                                argc, argv);
570 }
571
572 /** 
573  * Delete a user from a remote RPC server
574  *
575  * All parameters are provided by the run_rpc_command function, except for
576  * argc, argv which are passes through. 
577  *
578  * @param domain_sid The domain sid acquired from the remote server
579  * @param cli A cli_state connected to the server.
580  * @param mem_ctx Talloc context, destoyed on completion of the function.
581  * @param argc  Standard main() style argc
582  * @param argv  Standard main() style argv.  Initial components are already
583  *              stripped
584  *
585  * @return Normal NTSTATUS return.
586  **/
587
588 static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, 
589                                        struct cli_state *cli, 
590                                        TALLOC_CTX *mem_ctx, 
591                                        int argc, const char **argv)
592 {
593         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
594         POLICY_HND connect_pol, domain_pol, user_pol;
595
596         if (argc < 1) {
597                 d_printf("User must be specified\n");
598                 rpc_user_usage(argc, argv);
599                 return NT_STATUS_OK;
600         }
601         /* Get sam policy and domain handles */
602
603         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
604                                   &connect_pol);
605
606         if (!NT_STATUS_IS_OK(result)) {
607                 goto done;
608         }
609
610         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
611                                       MAXIMUM_ALLOWED_ACCESS,
612                                       domain_sid, &domain_pol);
613
614         if (!NT_STATUS_IS_OK(result)) {
615                 goto done;
616         }
617
618         /* Get handle on user */
619
620         {
621                 uint32 *user_rids, num_rids, *name_types;
622                 uint32 flags = 0x000003e8; /* Unknown */
623
624                 result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
625                                                flags, 1, &argv[0],
626                                                &num_rids, &user_rids,
627                                                &name_types);
628
629                 if (!NT_STATUS_IS_OK(result)) {
630                         goto done;
631                 }
632
633                 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
634                                             MAXIMUM_ALLOWED_ACCESS,
635                                             user_rids[0], &user_pol);
636
637                 if (!NT_STATUS_IS_OK(result)) {
638                         goto done;
639                 }
640         }
641
642         /* Delete user */
643
644         result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
645
646         if (!NT_STATUS_IS_OK(result)) {
647                 goto done;
648         }
649
650         /* Display results */
651
652  done:
653         return result;
654
655 }       
656
657 /** 
658  * Delete a user from a remote RPC server
659  *
660  * @param argc  Standard main() style argc
661  * @param argv  Standard main() style argv.  Initial components are already
662  *              stripped
663  *
664  * @return A shell status integer (0 for success)
665  **/
666
667 static int rpc_user_delete(int argc, const char **argv) 
668 {
669         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_del_internals,
670                                argc, argv);
671 }
672
673 /** 
674  * List user's groups on a remote RPC server
675  *
676  * All parameters are provided by the run_rpc_command function, except for
677  * argc, argv which are passes through. 
678  *
679  * @param domain_sid The domain sid acquired from the remote server
680  * @param cli A cli_state connected to the server.
681  * @param mem_ctx Talloc context, destoyed on completion of the function.
682  * @param argc  Standard main() style argc
683  * @param argv  Standard main() style argv.  Initial components are already
684  *              stripped
685  *
686  * @return Normal NTSTATUS return.
687  **/
688
689 static NTSTATUS 
690 rpc_user_info_internals(const DOM_SID *domain_sid, struct cli_state *cli,
691                         TALLOC_CTX *mem_ctx, int argc, const char **argv)
692 {
693         POLICY_HND connect_pol, domain_pol, user_pol;
694         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
695         uint32 *rids, num_rids, *name_types, num_names;
696         uint32 flags = 0x000003e8; /* Unknown */
697         int i;
698         char **names;
699         DOM_GID *user_gids;
700
701         if (argc < 1) {
702                 d_printf("User must be specified\n");
703                 rpc_user_usage(argc, argv);
704                 return NT_STATUS_OK;
705         }
706         /* Get sam policy handle */
707         
708         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
709                                   &connect_pol);
710         if (!NT_STATUS_IS_OK(result)) goto done;
711         
712         /* Get domain policy handle */
713         
714         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
715                                       MAXIMUM_ALLOWED_ACCESS,
716                                       domain_sid, &domain_pol);
717         if (!NT_STATUS_IS_OK(result)) goto done;
718
719         /* Get handle on user */
720
721         result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
722                                        flags, 1, &argv[0],
723                                        &num_rids, &rids, &name_types);
724
725         if (!NT_STATUS_IS_OK(result)) goto done;
726
727         result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
728                                     MAXIMUM_ALLOWED_ACCESS,
729                                     rids[0], &user_pol);
730         if (!NT_STATUS_IS_OK(result)) goto done;
731
732         result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
733                                            &num_rids, &user_gids);
734
735         /* Look up rids */
736
737         rids = (uint32 *)talloc(mem_ctx, sizeof(uint32) * num_rids);
738
739         for (i = 0; i < num_rids; i++)
740                 rids[i] = user_gids[i].g_rid;
741
742         result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
743                                       flags, num_rids, rids,
744                                       &num_names, &names, &name_types);
745
746         if (!NT_STATUS_IS_OK(result)) {
747                 goto done;
748         }
749
750         /* Display results */
751
752         for (i = 0; i < num_names; i++)
753                 printf("%s\n", names[i]);
754
755  done:
756         return result;
757 }
758
759 /** 
760  * List a user's groups from a remote RPC server
761  *
762  * @param argc  Standard main() style argc
763  * @param argv  Standard main() style argv.  Initial components are already
764  *              stripped
765  *
766  * @return A shell status integer (0 for success)
767  **/
768
769 static int rpc_user_info(int argc, const char **argv) 
770 {
771         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_info_internals,
772                                argc, argv);
773 }
774
775 /** 
776  * List users on a remote RPC server
777  *
778  * All parameters are provided by the run_rpc_command function, except for
779  * argc, argv which are passes through. 
780  *
781  * @param domain_sid The domain sid acquired from the remote server
782  * @param cli A cli_state connected to the server.
783  * @param mem_ctx Talloc context, destoyed on completion of the function.
784  * @param argc  Standard main() style argc
785  * @param argv  Standard main() style argv.  Initial components are already
786  *              stripped
787  *
788  * @return Normal NTSTATUS return.
789  **/
790
791 static NTSTATUS 
792 rpc_user_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
793                         TALLOC_CTX *mem_ctx, int argc, const char **argv)
794 {
795         POLICY_HND connect_pol, domain_pol;
796         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
797         uint32 start_idx=0, num_entries, i, loop_count = 0;
798         SAM_DISPINFO_CTR ctr;
799         SAM_DISPINFO_1 info1;
800
801         /* Get sam policy handle */
802         
803         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
804                                   &connect_pol);
805         if (!NT_STATUS_IS_OK(result)) {
806                 goto done;
807         }
808         
809         /* Get domain policy handle */
810         
811         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
812                                       MAXIMUM_ALLOWED_ACCESS,
813                                       domain_sid, &domain_pol);
814         if (!NT_STATUS_IS_OK(result)) {
815                 goto done;
816         }
817
818         /* Query domain users */
819         ZERO_STRUCT(ctr);
820         ZERO_STRUCT(info1);
821         ctr.sam.info1 = &info1;
822         if (opt_long_list_entries)
823                 d_printf("\nUser name             Comment"\
824                          "\n-----------------------------\n");
825         do {
826                 fstring user, desc;
827                 uint32 max_entries, max_size;
828
829                 get_query_dispinfo_params(
830                         loop_count, &max_entries, &max_size);
831
832                 result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
833                                                  &start_idx, 1, &num_entries,
834                                                  max_entries, max_size, &ctr);
835                 loop_count++;
836
837                 for (i = 0; i < num_entries; i++) {
838                         unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user)-1);
839                         if (opt_long_list_entries) 
840                                 unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1);
841                         
842                         if (opt_long_list_entries)
843                                 printf("%-21.21s %s\n", user, desc);
844                         else
845                                 printf("%s\n", user);
846                 }
847         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
848
849  done:
850         return result;
851 }
852
853 /** 
854  * 'net rpc user' entrypoint.
855  * @param argc  Standard main() style argc
856  * @param argc  Standard main() style argv.  Initial components are already
857  *              stripped
858  **/
859
860 int net_rpc_user(int argc, const char **argv) 
861 {
862         struct functable func[] = {
863                 {"add", rpc_user_add},
864                 {"info", rpc_user_info},
865                 {"delete", rpc_user_delete},
866                 {NULL, NULL}
867         };
868         
869         if (argc == 0) {
870                 if (opt_long_list_entries) {
871                 } else {
872                 }
873                         return run_rpc_command(NULL,PI_SAMR, 0, 
874                                                rpc_user_list_internals,
875                                                argc, argv);
876         }
877
878         return net_run_function(argc, argv, func, rpc_user_usage);
879 }
880
881
882 /****************************************************************************/
883
884 /**
885  * Basic usage function for 'net rpc group'
886  * @param argc  Standard main() style argc.
887  * @param argv  Standard main() style argv.  Initial components are already
888  *              stripped.
889  **/
890
891 static int rpc_group_usage(int argc, const char **argv)
892 {
893         return net_help_group(argc, argv);
894 }
895
896 /** 
897  * List groups on a remote RPC server
898  *
899  * All parameters are provided by the run_rpc_command function, except for
900  * argc, argv which are passes through. 
901  *
902  * @param domain_sid The domain sid acquired from the remote server
903  * @param cli A cli_state connected to the server.
904  * @param mem_ctx Talloc context, destoyed on completion of the function.
905  * @param argc  Standard main() style argc
906  * @param argv  Standard main() style argv.  Initial components are already
907  *              stripped
908  *
909  * @return Normal NTSTATUS return.
910  **/
911
912 static NTSTATUS 
913 rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
914                          TALLOC_CTX *mem_ctx, int argc, const char **argv)
915 {
916         POLICY_HND connect_pol, domain_pol;
917         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
918         uint32 start_idx=0, max_entries=250, num_entries, i;
919         struct acct_info *groups;
920         DOM_SID global_sid_Builtin;
921
922         string_to_sid(&global_sid_Builtin, "S-1-5-32");
923
924         /* Get sam policy handle */
925         
926         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
927                                   &connect_pol);
928         if (!NT_STATUS_IS_OK(result)) {
929                 goto done;
930         }
931         
932         /* Get domain policy handle */
933         
934         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
935                                       MAXIMUM_ALLOWED_ACCESS,
936                                       domain_sid, &domain_pol);
937         if (!NT_STATUS_IS_OK(result)) {
938                 goto done;
939         }
940
941         /* Query domain groups */
942         if (opt_long_list_entries)
943                 d_printf("\nGroup name            Comment"\
944                          "\n-----------------------------\n");
945         do {
946                 result = cli_samr_enum_dom_groups(cli, mem_ctx, &domain_pol,
947                                                   &start_idx, max_entries,
948                                                   &groups, &num_entries);
949                                                  
950                 for (i = 0; i < num_entries; i++) {
951                         if (opt_long_list_entries)
952                                 printf("%-21.21s %-50.50s\n", 
953                                        groups[i].acct_name,
954                                        groups[i].acct_desc);
955                         else
956                                 printf("%-21.21s\n", groups[i].acct_name);
957                 }
958         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
959         /* query domain aliases */
960         do {
961                 result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
962                                                   &start_idx, max_entries,
963                                                   &groups, &num_entries);
964                                                  
965                 for (i = 0; i < num_entries; i++) {
966                         if (opt_long_list_entries)
967                                 printf("%-21.21s %-50.50s\n", 
968                                        groups[i].acct_name,
969                                        groups[i].acct_desc);
970                         else
971                                 printf("%-21.21s\n", groups[i].acct_name);
972                 }
973         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
974         cli_samr_close(cli, mem_ctx, &domain_pol);
975         /* Get builtin policy handle */
976         
977         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
978                                       MAXIMUM_ALLOWED_ACCESS,
979                                       &global_sid_Builtin, &domain_pol);
980         if (!NT_STATUS_IS_OK(result)) {
981                 goto done;
982         }
983         /* query builtin aliases */
984         do {
985                 result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
986                                                   &start_idx, max_entries,
987                                                   &groups, &num_entries);
988                                                  
989                 for (i = 0; i < num_entries; i++) {
990                         if (opt_long_list_entries)
991                                 printf("%-21.21s %-50.50s\n", 
992                                        groups[i].acct_name,
993                                        groups[i].acct_desc);
994                         else
995                                 printf("%s\n", groups[i].acct_name);
996                 }
997         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
998
999  done:
1000         return result;
1001 }
1002
1003 /** 
1004  * 'net rpc group' entrypoint.
1005  * @param argc  Standard main() style argc
1006  * @param argc  Standard main() style argv.  Initial components are already
1007  *              stripped
1008  **/
1009
1010 int net_rpc_group(int argc, const char **argv) 
1011 {
1012         struct functable func[] = {
1013 #if 0
1014                 {"add", rpc_group_add},
1015                 {"delete", rpc_group_delete},
1016 #endif
1017                 {NULL, NULL}
1018         };
1019         
1020         if (argc == 0) {
1021                 if (opt_long_list_entries) {
1022                 } else {
1023                 }
1024                 return run_rpc_command(NULL, PI_SAMR, 0, 
1025                                        rpc_group_list_internals,
1026                                        argc, argv);
1027         }
1028
1029         return net_run_function(argc, argv, func, rpc_group_usage);
1030 }
1031
1032 /****************************************************************************/
1033
1034 static int rpc_share_usage(int argc, const char **argv)
1035 {
1036         return net_help_share(argc, argv);
1037 }
1038
1039 /** 
1040  * Add a share on a remote RPC server
1041  *
1042  * All parameters are provided by the run_rpc_command function, except for
1043  * argc, argv which are passes through. 
1044  *
1045  * @param domain_sid The domain sid acquired from the remote server
1046  * @param cli A cli_state connected to the server.
1047  * @param mem_ctx Talloc context, destoyed on completion of the function.
1048  * @param argc  Standard main() style argc
1049  * @param argv  Standard main() style argv.  Initial components are already
1050  *              stripped
1051  *
1052  * @return Normal NTSTATUS return.
1053  **/
1054 static NTSTATUS 
1055 rpc_share_add_internals(const DOM_SID *domain_sid, struct cli_state *cli,
1056                         TALLOC_CTX *mem_ctx,int argc, const char **argv)
1057 {
1058         WERROR result;
1059         char *sharename=talloc_strdup(mem_ctx, argv[0]);
1060         char *path;
1061         uint32 type=0; /* only allow disk shares to be added */
1062         uint32 num_users=0, perms=0;
1063         char *password=NULL; /* don't allow a share password */
1064
1065         path = strchr(sharename, '=');
1066         if (!path)
1067                 return NT_STATUS_UNSUCCESSFUL;
1068         *path++ = '\0';
1069
1070         result = cli_srvsvc_net_share_add(cli, mem_ctx, sharename, type,
1071                                           opt_comment, perms, opt_maxusers,
1072                                           num_users, path, password);
1073         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1074 }
1075
1076 static int rpc_share_add(int argc, const char **argv)
1077 {
1078         if ((argc < 1) || !strchr(argv[0], '=')) {
1079                 DEBUG(1,("Sharename or path not specified on add\n"));
1080                 return rpc_share_usage(argc, argv);
1081         }
1082         return run_rpc_command(NULL, PI_SRVSVC, 0, 
1083                                rpc_share_add_internals,
1084                                argc, argv);
1085 }
1086
1087 /** 
1088  * Delete a share on a remote RPC server
1089  *
1090  * All parameters are provided by the run_rpc_command function, except for
1091  * argc, argv which are passes through. 
1092  *
1093  * @param domain_sid The domain sid acquired from the remote server
1094  * @param cli A cli_state connected to the server.
1095  * @param mem_ctx Talloc context, destoyed on completion of the function.
1096  * @param argc  Standard main() style argc
1097  * @param argv  Standard main() style argv.  Initial components are already
1098  *              stripped
1099  *
1100  * @return Normal NTSTATUS return.
1101  **/
1102 static NTSTATUS 
1103 rpc_share_del_internals(const DOM_SID *domain_sid, struct cli_state *cli,
1104                         TALLOC_CTX *mem_ctx,int argc, const char **argv)
1105 {
1106         WERROR result;
1107
1108         result = cli_srvsvc_net_share_del(cli, mem_ctx, argv[0]);
1109         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1110 }
1111
1112 /** 
1113  * Delete a share on a remote RPC server
1114  *
1115  * @param domain_sid The domain sid acquired from the remote server
1116  * @param argc  Standard main() style argc
1117  * @param argv  Standard main() style argv.  Initial components are already
1118  *              stripped
1119  *
1120  * @return A shell status integer (0 for success)
1121  **/
1122 static int rpc_share_delete(int argc, const char **argv)
1123 {
1124         if (argc < 1) {
1125                 DEBUG(1,("Sharename not specified on delete\n"));
1126                 return rpc_share_usage(argc, argv);
1127         }
1128         return run_rpc_command(NULL, PI_SRVSVC, 0, 
1129                                rpc_share_del_internals,
1130                                argc, argv);
1131 }
1132
1133 /**
1134  * Formatted print of share info
1135  *
1136  * @param info1  pointer to SRV_SHARE_INFO_1 to format
1137  **/
1138  
1139 static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
1140 {
1141         fstring netname = "", remark = "";
1142
1143         rpcstr_pull_unistr2_fstring(netname, &info1->info_1_str.uni_netname);
1144         rpcstr_pull_unistr2_fstring(remark, &info1->info_1_str.uni_remark);
1145
1146         if (opt_long_list_entries) {
1147                 d_printf("%-12.12s %-8.8s %-50.50s\n",
1148                          netname, share_type[info1->info_1.type], remark);
1149         } else {
1150                 d_printf("%-12.12s\n", netname);
1151         }
1152
1153 }
1154
1155 /** 
1156  * List shares on a remote RPC server
1157  *
1158  * All parameters are provided by the run_rpc_command function, except for
1159  * argc, argv which are passes through. 
1160  *
1161  * @param domain_sid The domain sid acquired from the remote server
1162  * @param cli A cli_state connected to the server.
1163  * @param mem_ctx Talloc context, destoyed on completion of the function.
1164  * @param argc  Standard main() style argc
1165  * @param argv  Standard main() style argv.  Initial components are already
1166  *              stripped
1167  *
1168  * @return Normal NTSTATUS return.
1169  **/
1170
1171 static NTSTATUS 
1172 rpc_share_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
1173                          TALLOC_CTX *mem_ctx, int argc, const char **argv)
1174 {
1175         SRV_SHARE_INFO_CTR ctr;
1176         WERROR result;
1177         ENUM_HND hnd;
1178         uint32 preferred_len = 0xffffffff, i;
1179
1180         init_enum_hnd(&hnd, 0);
1181
1182         result = cli_srvsvc_net_share_enum(
1183                 cli, mem_ctx, 1, &ctr, preferred_len, &hnd);
1184
1185         if (!W_ERROR_IS_OK(result))
1186                 goto done;
1187
1188         /* Display results */
1189
1190         if (opt_long_list_entries) {
1191                 d_printf(
1192         "\nEnumerating shared resources (exports) on remote server:\n\n"\
1193         "\nShare name   Type     Description\n"\
1194         "----------   ----     -----------\n");
1195         }
1196         for (i = 0; i < ctr.num_entries; i++)
1197                 display_share_info_1(&ctr.share.info1[i]);
1198  done:
1199         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1200 }
1201
1202 /** 
1203  * 'net rpc share' entrypoint.
1204  * @param argc  Standard main() style argc
1205  * @param argv  Standard main() style argv.  Initial components are already
1206  *              stripped
1207  **/
1208
1209 int net_rpc_share(int argc, const char **argv) 
1210 {
1211         struct functable func[] = {
1212                 {"add", rpc_share_add},
1213                 {"delete", rpc_share_delete},
1214                 {NULL, NULL}
1215         };
1216
1217         if (argc == 0)
1218                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
1219                                        rpc_share_list_internals,
1220                                        argc, argv);
1221
1222         return net_run_function(argc, argv, func, rpc_share_usage);
1223 }
1224
1225 /****************************************************************************/
1226
1227 static int rpc_file_usage(int argc, const char **argv)
1228 {
1229         return net_help_file(argc, argv);
1230 }
1231
1232 /** 
1233  * Close a file on a remote RPC server
1234  *
1235  * All parameters are provided by the run_rpc_command function, except for
1236  * argc, argv which are passes through. 
1237  *
1238  * @param domain_sid The domain sid acquired from the remote server
1239  * @param cli A cli_state connected to the server.
1240  * @param mem_ctx Talloc context, destoyed on completion of the function.
1241  * @param argc  Standard main() style argc
1242  * @param argv  Standard main() style argv.  Initial components are already
1243  *              stripped
1244  *
1245  * @return Normal NTSTATUS return.
1246  **/
1247 static NTSTATUS 
1248 rpc_file_close_internals(const DOM_SID *domain_sid, struct cli_state *cli,
1249                          TALLOC_CTX *mem_ctx, int argc, const char **argv)
1250 {
1251         WERROR result;
1252         result = cli_srvsvc_net_file_close(cli, mem_ctx, atoi(argv[0]));
1253         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1254 }
1255
1256 /** 
1257  * Close a file on a remote RPC server
1258  *
1259  * @param argc  Standard main() style argc
1260  * @param argv  Standard main() style argv.  Initial components are already
1261  *              stripped
1262  *
1263  * @return A shell status integer (0 for success)
1264  **/
1265 static int rpc_file_close(int argc, const char **argv)
1266 {
1267         if (argc < 1) {
1268                 DEBUG(1, ("No fileid given on close\n"));
1269                 return(rpc_file_usage(argc, argv));
1270         }
1271
1272         return run_rpc_command(NULL, PI_SRVSVC, 0, 
1273                                rpc_file_close_internals,
1274                                argc, argv);
1275 }
1276
1277 /** 
1278  * Formatted print of open file info 
1279  *
1280  * @param info3  FILE_INFO_3 contents
1281  * @param str3   strings for FILE_INFO_3
1282  **/
1283
1284 static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
1285 {
1286         fstring user = "", path = "";
1287
1288         rpcstr_pull_unistr2_fstring(user, &str3->uni_user_name);
1289         rpcstr_pull_unistr2_fstring(path, &str3->uni_path_name);
1290
1291         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
1292                  info3->id, user, info3->perms, info3->num_locks, path);
1293 }
1294
1295 /** 
1296  * List open files on a remote RPC server
1297  *
1298  * All parameters are provided by the run_rpc_command function, except for
1299  * argc, argv which are passes through. 
1300  *
1301  * @param domain_sid The domain sid acquired from the remote server
1302  * @param cli A cli_state connected to the server.
1303  * @param mem_ctx Talloc context, destoyed on completion of the function.
1304  * @param argc  Standard main() style argc
1305  * @param argv  Standard main() style argv.  Initial components are already
1306  *              stripped
1307  *
1308  * @return Normal NTSTATUS return.
1309  **/
1310
1311 static NTSTATUS 
1312 rpc_file_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
1313                         TALLOC_CTX *mem_ctx, int argc, const char **argv)
1314 {
1315         SRV_FILE_INFO_CTR ctr;
1316         WERROR result;
1317         ENUM_HND hnd;
1318         uint32 preferred_len = 0xffffffff, i;
1319         const char *username=NULL;
1320
1321         init_enum_hnd(&hnd, 0);
1322
1323         /* if argc > 0, must be user command */
1324         if (argc > 0)
1325                 username = smb_xstrdup(argv[0]);
1326                 
1327         result = cli_srvsvc_net_file_enum(
1328                 cli, mem_ctx, 3, username, &ctr, preferred_len, &hnd);
1329
1330         if (!W_ERROR_IS_OK(result))
1331                 goto done;
1332
1333         /* Display results */
1334
1335         d_printf(
1336                  "\nEnumerating open files on remote server:\n\n"\
1337                  "\nFileId  Opened by            Perms  Locks  Path"\
1338                  "\n------  ---------            -----  -----  ---- \n");
1339         for (i = 0; i < ctr.num_entries; i++)
1340                 display_file_info_3(&ctr.file.info3[i].info_3, 
1341                                     &ctr.file.info3[i].info_3_str);
1342  done:
1343         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1344 }
1345
1346
1347 /** 
1348  * List files for a user on a remote RPC server
1349  *
1350  * @param argc  Standard main() style argc
1351  * @param argv  Standard main() style argv.  Initial components are already
1352  *              stripped
1353  *
1354  * @return A shell status integer (0 for success)
1355  **/
1356 static int rpc_file_user(int argc, const char **argv)
1357 {
1358         if (argc < 1) {
1359                 DEBUG(1, ("No username given\n"));
1360                 return(rpc_file_usage(argc, argv));
1361         }
1362
1363         return run_rpc_command(NULL, PI_SRVSVC, 0, 
1364                                rpc_file_list_internals,
1365                                argc, argv);
1366 }
1367
1368
1369 /** 
1370  * 'net rpc file' entrypoint.
1371  * @param argc  Standard main() style argc
1372  * @param argv  Standard main() style argv.  Initial components are already
1373  *              stripped
1374  **/
1375
1376 int net_rpc_file(int argc, const char **argv) 
1377 {
1378         struct functable func[] = {
1379                 {"close", rpc_file_close},
1380                 {"user", rpc_file_user},
1381 #if 0
1382                 {"info", rpc_file_info},
1383 #endif
1384                 {NULL, NULL}
1385         };
1386
1387         if (argc == 0)
1388                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
1389                                        rpc_file_list_internals,
1390                                        argc, argv);
1391
1392         return net_run_function(argc, argv, func, rpc_file_usage);
1393 }
1394
1395 /****************************************************************************/
1396
1397
1398
1399 /** 
1400  * ABORT the shutdown of a remote RPC Server
1401  *
1402  * All parameters are provided by the run_rpc_command function, except for
1403  * argc, argv which are passed through. 
1404  *
1405  * @param domain_sid The domain sid aquired from the remote server
1406  * @param cli A cli_state connected to the server.
1407  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1408  * @param argc  Standard main() style argc
1409  * @param argv  Standard main() style argv.  Initial components are already
1410  *              stripped
1411  *
1412  * @return Normal NTSTATUS return.
1413  **/
1414
1415 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1416                                              int argc, const char **argv) 
1417 {
1418         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1419         
1420         result = cli_reg_abort_shutdown(cli, mem_ctx);
1421         
1422         if (NT_STATUS_IS_OK(result))
1423                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
1424         else
1425                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
1426         
1427         return result;
1428 }
1429
1430
1431 /** 
1432  * ABORT the Shut down of a remote RPC server
1433  *
1434  * @param argc  Standard main() style argc
1435  * @param argv  Standard main() style argv.  Initial components are already
1436  *              stripped
1437  *
1438  * @return A shell status integer (0 for success)
1439  **/
1440
1441 static int rpc_shutdown_abort(int argc, const char **argv) 
1442 {
1443         return run_rpc_command(NULL, PI_WINREG, 0, rpc_shutdown_abort_internals,
1444                                argc, argv);
1445 }
1446
1447 /** 
1448  * Shut down a remote RPC Server
1449  *
1450  * All parameters are provided by the run_rpc_command function, except for
1451  * argc, argv which are passes through. 
1452  *
1453  * @param domain_sid The domain sid aquired from the remote server
1454  * @param cli A cli_state connected to the server.
1455  * @param mem_ctx Talloc context, destoyed on compleation of the function.
1456  * @param argc  Standard main() style argc
1457  * @param argc  Standard main() style argv.  Initial components are already
1458  *              stripped
1459  *
1460  * @return Normal NTSTATUS return.
1461  **/
1462
1463 static NTSTATUS rpc_shutdown_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1464                                        int argc, const char **argv) 
1465 {
1466         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1467         const char *msg = "This machine will be shutdown shortly";
1468         uint32 timeout = 20;
1469 #if 0
1470         poptContext pc;
1471         int rc;
1472
1473         struct poptOption long_options[] = {
1474                 {"message",    'm', POPT_ARG_STRING, &msg},
1475                 {"timeout",    't', POPT_ARG_INT,    &timeout},
1476                 {"reboot",     'r', POPT_ARG_NONE,   &reboot},
1477                 {"force",      'f', POPT_ARG_NONE,   &force},
1478                 { 0, 0, 0, 0}
1479         };
1480
1481         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
1482                             POPT_CONTEXT_KEEP_FIRST);
1483
1484         rc = poptGetNextOpt(pc);
1485         
1486         if (rc < -1) {
1487                 /* an error occurred during option processing */
1488                 DEBUG(0, ("%s: %s\n",
1489                           poptBadOption(pc, POPT_BADOPTION_NOALIAS),
1490                           poptStrerror(rc)));
1491                 return NT_STATUS_INVALID_PARAMETER;
1492         }
1493 #endif
1494         if (opt_comment) {
1495                 msg = opt_comment;
1496         }
1497         if (opt_timeout) {
1498                 timeout = opt_timeout;
1499         }
1500
1501         /* create an entry */
1502         result = cli_reg_shutdown(cli, mem_ctx, msg, timeout, opt_reboot, opt_force);
1503
1504         if (NT_STATUS_IS_OK(result))
1505                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
1506         else
1507                 DEBUG(0,("Shutdown of remote machine failed!\n"));
1508
1509         return result;
1510 }
1511
1512 /** 
1513  * Shut down a remote RPC server
1514  *
1515  * @param argc  Standard main() style argc
1516  * @param argc  Standard main() style argv.  Initial components are already
1517  *              stripped
1518  *
1519  * @return A shell status integer (0 for success)
1520  **/
1521
1522 static int rpc_shutdown(int argc, const char **argv) 
1523 {
1524         return run_rpc_command(NULL, PI_WINREG, 0, rpc_shutdown_internals,
1525                                        argc, argv);
1526 }
1527
1528 /***************************************************************************
1529   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
1530   
1531  ***************************************************************************/
1532
1533 /**
1534  * Add interdomain trust account to the RPC server.
1535  * All parameters (except for argc and argv) are passed by run_rpc_command
1536  * function.
1537  *
1538  * @param domain_sid The domain sid acquired from the server
1539  * @param cli A cli_state connected to the server.
1540  * @param mem_ctx Talloc context, destoyed on completion of the function.
1541  * @param argc  Standard main() style argc
1542  * @param argc  Standard main() style argv.  Initial components are already
1543  *              stripped
1544  *
1545  * @return normal NTSTATUS return code
1546  */
1547
1548 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1549                                            int argc, const char **argv) {
1550
1551         POLICY_HND connect_pol, domain_pol, user_pol;
1552         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1553         char *acct_name;
1554         uint16 acb_info;
1555         uint32 unknown, user_rid;
1556
1557         if (argc != 2) {
1558                 d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
1559                 return NT_STATUS_INVALID_PARAMETER;
1560         }
1561
1562         /* 
1563          * Make valid trusting domain account (ie. uppercased and with '$' appended)
1564          */
1565          
1566         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
1567                 return NT_STATUS_NO_MEMORY;
1568         }
1569
1570         strupper(acct_name);
1571
1572         /* Get samr policy handle */
1573         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1574                                   &connect_pol);
1575         if (!NT_STATUS_IS_OK(result)) {
1576                 goto done;
1577         }
1578         
1579         /* Get domain policy handle */
1580         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1581                                       MAXIMUM_ALLOWED_ACCESS,
1582                                       domain_sid, &domain_pol);
1583         if (!NT_STATUS_IS_OK(result)) {
1584                 goto done;
1585         }
1586
1587         /* Create trusting domain's account */
1588         acb_info = ACB_DOMTRUST;
1589         unknown = 0xe00500b0; /* No idea what this is - a permission mask?
1590                                  mimir: yes, most probably it is */
1591
1592         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1593                                           acct_name, acb_info, unknown,
1594                                           &user_pol, &user_rid);
1595         if (!NT_STATUS_IS_OK(result)) {
1596                 goto done;
1597         }
1598
1599         {
1600                 SAM_USERINFO_CTR ctr;
1601                 SAM_USER_INFO_24 p24;
1602                 fstring ucs2_trust_password;
1603                 int ucs2_pw_len;
1604                 uchar pwbuf[516];
1605
1606                 ucs2_pw_len = push_ucs2(NULL, ucs2_trust_password, argv[1],
1607                                         sizeof(ucs2_trust_password), 0);
1608
1609                 encode_pw_buffer((char *)pwbuf, ucs2_trust_password,
1610                                  ucs2_pw_len);
1611
1612                 ZERO_STRUCT(ctr);
1613                 ZERO_STRUCT(p24);
1614
1615                 init_sam_user_info24(&p24, (char *)pwbuf, 24);
1616
1617                 ctr.switch_value = 24;
1618                 ctr.info.id24 = &p24;
1619
1620                 result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24,
1621                                                cli->user_session_key, &ctr);
1622
1623                 if (!NT_STATUS_IS_OK(result)) {
1624                         DEBUG(0,("Could not set trust account password: %s\n",
1625                                  nt_errstr(result)));
1626                         goto done;
1627                 }
1628         }
1629
1630  done:
1631         SAFE_FREE(acct_name);
1632         return result;
1633 }
1634
1635 /**
1636  * Create interdomain trust account for a remote domain.
1637  *
1638  * @param argc standard argc
1639  * @param argv standard argv without initial components
1640  *
1641  * @return Integer status (0 means success)
1642  **/
1643
1644 static int rpc_trustdom_add(int argc, const char **argv)
1645 {
1646         return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
1647                                argc, argv);
1648 }
1649
1650
1651 /**
1652  * Delete interdomain trust account for a remote domain.
1653  *
1654  * @param argc standard argc
1655  * @param argv standard argv without initial components
1656  *
1657  * @return Integer status (0 means success)
1658  **/
1659  
1660 static int rpc_trustdom_del(int argc, const char **argv)
1661 {
1662         d_printf("Sorry, not yet implemented.\n");
1663         return -1;
1664 }
1665
1666  
1667 /**
1668  * Establish trust relationship to a trusting domain.
1669  * Interdomain account must already be created on remote PDC.
1670  *
1671  * @param argc standard argc
1672  * @param argv standard argv without initial components
1673  *
1674  * @return Integer status (0 means success)
1675  **/
1676
1677 static int rpc_trustdom_establish(int argc, const char **argv)
1678 {
1679         struct cli_state *cli;
1680         struct in_addr server_ip;
1681         POLICY_HND connect_hnd;
1682         TALLOC_CTX *mem_ctx;
1683         NTSTATUS nt_status;
1684         DOM_SID domain_sid;
1685         WKS_INFO_100 wks_info;
1686         
1687         char* domain_name;
1688         char* acct_name;
1689         fstring pdc_name;
1690
1691         /*
1692          * Connect to \\server\ipc$ as 'our domain' account with password
1693          */
1694
1695         if (argc != 1) {
1696                 d_printf("Usage: net rpc trustdom establish <domain_name>\n");
1697                 return -1;
1698         }
1699
1700         domain_name = smb_xstrdup(argv[0]);
1701         strupper(domain_name);
1702
1703         /* account name used at first is our domain's name with '$' */
1704         asprintf(&acct_name, "%s$", lp_workgroup());
1705         strupper(acct_name);
1706         
1707         /*
1708          * opt_workgroup will be used by connection functions further,
1709          * hence it should be set to remote domain name instead of ours
1710          */
1711         if (opt_workgroup) {
1712                 opt_workgroup = smb_xstrdup(domain_name);
1713         };
1714         
1715         opt_user_name = acct_name;
1716
1717         /* find the domain controller */
1718         if (!net_find_dc(&server_ip, pdc_name, domain_name)) {
1719                 DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name));
1720                 return -1;
1721         }
1722
1723         /* connect to ipc$ as username/password */
1724         nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
1725         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
1726
1727                 /* Is it trusting domain account for sure ? */
1728                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
1729                         nt_errstr(nt_status)));
1730                 return -1;
1731         }
1732         
1733         /*
1734          * Connect to \\server\ipc$ again (this time anonymously)
1735          */
1736         
1737         nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
1738         
1739         if (NT_STATUS_IS_ERR(nt_status)) {
1740                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
1741                         domain_name, nt_errstr(nt_status)));
1742         }
1743
1744         /*
1745          * Use NetServerEnum2 to make sure we're talking to a proper server
1746          */
1747          
1748         if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
1749                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
1750                          for domain %s\n", domain_name));
1751         }
1752          
1753         /*
1754          * Call WksQueryInfo to check remote server's capabilities
1755          * note: It is now used only to get unicode domain name
1756          */
1757         
1758         if (!cli_nt_session_open(cli, PI_WKSSVC)) {
1759                 DEBUG(0, ("Couldn't not initialise wkssvc pipe\n"));
1760                 return -1;
1761         }
1762
1763         if (!(mem_ctx = talloc_init("establishing trust relationship to domain %s",
1764                         domain_name))) {
1765                 DEBUG(0, ("talloc_init() failed\n"));
1766                 cli_shutdown(cli);
1767                 return -1;
1768         }
1769         
1770         nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info);
1771         
1772         if (NT_STATUS_IS_ERR(nt_status)) {
1773                 DEBUG(0, ("WksQueryInfo call failed.\n"));
1774                 return -1;
1775         }
1776
1777         if (cli->nt_pipe_fnum)
1778                 cli_nt_session_close(cli);
1779
1780
1781         /*
1782          * Call LsaOpenPolicy and LsaQueryInfo
1783          */
1784          
1785         if (!(mem_ctx = talloc_init("rpc_trustdom_establish"))) {
1786                 DEBUG(0, ("talloc_init() failed\n"));
1787                 cli_shutdown(cli);
1788                 return -1;
1789         }
1790
1791         if (!cli_nt_session_open(cli, PI_LSARPC)) {
1792                 DEBUG(0, ("Could not initialise lsa pipe\n"));
1793                 cli_shutdown(cli);
1794                 return -1;
1795         }
1796
1797         nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
1798                                          &connect_hnd);
1799         if (NT_STATUS_IS_ERR(nt_status)) {
1800                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
1801                         nt_errstr(nt_status)));
1802                 return -1;
1803         }
1804
1805         /* Querying info level 5 */
1806         
1807         nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
1808                                               5 /* info level */, domain_name,
1809                                               &domain_sid);
1810         if (NT_STATUS_IS_ERR(nt_status)) {
1811                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
1812                         nt_errstr(nt_status)));
1813                 return -1;
1814         }
1815
1816
1817
1818
1819         /* There should be actually query info level 3 (following nt serv behaviour),
1820            but I still don't know if it's _really_ necessary */
1821                         
1822         /*
1823          * Store the password in secrets db
1824          */
1825
1826         if (!secrets_store_trusted_domain_password(domain_name, wks_info.uni_lan_grp.buffer,
1827                                                    wks_info.uni_lan_grp.uni_str_len, opt_password,
1828                                                    domain_sid)) {
1829                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
1830                 return -1;
1831         }
1832         
1833         /*
1834          * Close the pipes and clean up
1835          */
1836          
1837         nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
1838         if (NT_STATUS_IS_ERR(nt_status)) {
1839                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
1840                         nt_errstr(nt_status)));
1841                 return -1;
1842         }
1843
1844         if (cli->nt_pipe_fnum)
1845                 cli_nt_session_close(cli);
1846          
1847         talloc_destroy(mem_ctx);
1848          
1849         DEBUG(0, ("Success!\n"));
1850         return 0;
1851 }
1852
1853 /**
1854  * Revoke trust relationship to the remote domain
1855  *
1856  * @param argc standard argc
1857  * @param argv standard argv without initial components
1858  *
1859  * @return Integer status (0 means success)
1860  **/
1861
1862 static int rpc_trustdom_revoke(int argc, const char **argv)
1863 {
1864         char* domain_name;
1865
1866         if (argc < 1) return -1;
1867         
1868         /* generate upper cased domain name */
1869         domain_name = smb_xstrdup(argv[0]);
1870         strupper(domain_name);
1871
1872         /* delete password of the trust */
1873         if (!trusted_domain_password_delete(domain_name)) {
1874                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
1875                           domain_name));
1876                 return -1;
1877         };
1878         
1879         return 0;
1880 }
1881
1882 /**
1883  * Usage for 'net rpc trustdom' command
1884  *
1885  * @param argc standard argc
1886  * @param argv standard argv without inital components
1887  *
1888  * @return Integer status returned to shell
1889  **/
1890  
1891 static int rpc_trustdom_usage(int argc, const char **argv)
1892 {
1893         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
1894         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
1895         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
1896         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
1897         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
1898         return -1;
1899 }
1900
1901
1902 static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
1903                               int argc, const char **argv)
1904 {
1905         fstring str_sid;
1906         sid_to_string(str_sid, domain_sid);
1907         d_printf("%s\n", str_sid);
1908         return NT_STATUS_OK;
1909 };
1910
1911
1912 static int rpc_trustdom_list(int argc, const char **argv)
1913 {
1914         /* common variables */
1915         TALLOC_CTX* mem_ctx;
1916         struct cli_state *cli, *remote_cli;
1917         NTSTATUS nt_status;
1918         const char *domain_name = NULL;
1919         DOM_SID queried_dom_sid;
1920         fstring ascii_sid, padding;
1921         int ascii_dom_name_len;
1922         POLICY_HND connect_hnd;
1923         
1924         /* trusted domains listing variables */
1925         int enum_ctx = 0;
1926         int num_domains, i, pad_len, col_len = 20;
1927         DOM_SID *domain_sids;
1928         char **trusted_dom_names;
1929         fstring pdc_name, dummy;
1930         
1931         /* trusting domains listing variables */
1932         POLICY_HND domain_hnd;
1933         char **trusting_dom_names;
1934         uint32 *trusting_dom_rids;
1935         
1936         /*
1937          * Listing trusted domains (stored in secrets.tdb, if local)
1938          */
1939
1940         mem_ctx = talloc_init("trust relationships listing");
1941
1942         /*
1943          * set domain and pdc name to local samba server (default)
1944          * or to remote one given in command line
1945          */
1946         
1947         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
1948                 domain_name = opt_workgroup;
1949                 opt_target_workgroup = opt_workgroup;
1950         } else {
1951                 fstrcpy(pdc_name, global_myname());
1952                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
1953                 opt_target_workgroup = domain_name;
1954         };
1955
1956         /* open \PIPE\lsarpc and open policy handle */
1957         if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
1958                 DEBUG(0, ("Couldn't connect to domain controller\n"));
1959                 return -1;
1960         };
1961
1962         if (!cli_nt_session_open(cli, PI_LSARPC)) {
1963                 DEBUG(0, ("Could not initialise lsa pipe\n"));
1964                 return -1;
1965         };
1966
1967         nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
1968                                         &connect_hnd);
1969         if (NT_STATUS_IS_ERR(nt_status)) {
1970                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
1971                         nt_errstr(nt_status)));
1972                 return -1;
1973         };
1974         
1975         /* query info level 5 to obtain sid of a domain being queried */
1976         nt_status = cli_lsa_query_info_policy(
1977                 cli, mem_ctx, &connect_hnd, 5 /* info level */, 
1978                 dummy, &queried_dom_sid);
1979
1980         if (NT_STATUS_IS_ERR(nt_status)) {
1981                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
1982                         nt_errstr(nt_status)));
1983                 return -1;
1984         }
1985                 
1986         /*
1987          * Keep calling LsaEnumTrustdom over opened pipe until
1988          * the end of enumeration is reached
1989          */
1990          
1991         d_printf("Trusted domains list:\n\n");
1992
1993         do {
1994                 nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx,
1995                                                    &num_domains,
1996                                                    &trusted_dom_names, &domain_sids);
1997                 
1998                 if (NT_STATUS_IS_ERR(nt_status)) {
1999                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
2000                                 nt_errstr(nt_status)));
2001                         return -1;
2002                 };
2003                 
2004                 for (i = 0; i < num_domains; i++) {
2005                         /* convert sid into ascii string */
2006                         sid_to_string(ascii_sid, &(domain_sids[i]));
2007                 
2008                         /* calculate padding space for d_printf to look nicer */
2009                         pad_len = col_len - strlen(trusted_dom_names[i]);
2010                         padding[pad_len] = 0;
2011                         do padding[--pad_len] = ' '; while (pad_len);
2012                         
2013                         d_printf("%s%s%s\n", trusted_dom_names[i], padding, ascii_sid);
2014                 };
2015                 
2016                 /*
2017                  * in case of no trusted domains say something rather
2018                  * than just display blank line
2019                  */
2020                 if (!num_domains) d_printf("none\n");
2021
2022         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
2023
2024         /* close this connection before doing next one */
2025         nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
2026         if (NT_STATUS_IS_ERR(nt_status)) {
2027                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
2028                         nt_errstr(nt_status)));
2029                 return -1;
2030         };
2031         
2032         cli_nt_session_close(cli);
2033
2034         /*
2035          * Listing trusting domains (stored in passdb backend, if local)
2036          */
2037         
2038         d_printf("\nTrusting domains list:\n\n");
2039
2040         /*
2041          * Open \PIPE\samr and get needed policy handles
2042          */
2043         if (!cli_nt_session_open(cli, PI_SAMR)) {
2044                 DEBUG(0, ("Could not initialise samr pipe\n"));
2045                 return -1;
2046         };
2047         
2048         /* SamrConnect */
2049         nt_status = cli_samr_connect(cli, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN,
2050                                                                  &connect_hnd);
2051         if (!NT_STATUS_IS_OK(nt_status)) {
2052                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
2053                         nt_errstr(nt_status)));
2054                 return -1;
2055         };
2056         
2057         /* SamrOpenDomain - we have to open domain policy handle in order to be
2058            able to enumerate accounts*/
2059         nt_status = cli_samr_open_domain(cli, mem_ctx, &connect_hnd,
2060                                                                          SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
2061                                                                          &queried_dom_sid, &domain_hnd);                                                                         
2062         if (!NT_STATUS_IS_OK(nt_status)) {
2063                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
2064                         nt_errstr(nt_status)));
2065                 return -1;
2066         };
2067         
2068         /*
2069          * perform actual enumeration
2070          */
2071          
2072         enum_ctx = 0;   /* reset enumeration context from last enumeration */
2073         do {
2074                         
2075                 nt_status = cli_samr_enum_dom_users(cli, mem_ctx, &domain_hnd,
2076                                                     &enum_ctx, ACB_DOMTRUST, 0xffff,
2077                                                     &trusting_dom_names, &trusting_dom_rids,
2078                                                     &num_domains);
2079                 if (NT_STATUS_IS_ERR(nt_status)) {
2080                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
2081                                 nt_errstr(nt_status)));
2082                         return -1;
2083                 };
2084                 
2085                 for (i = 0; i < num_domains; i++) {
2086
2087                         /*
2088                          * get each single domain's sid (do we _really_ need this ?):
2089                          *  1) connect to domain's pdc
2090                          *  2) query the pdc for domain's sid
2091                          */
2092
2093                         /* get rid of '$' tail */
2094                         ascii_dom_name_len = strlen(trusting_dom_names[i]);
2095                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
2096                                 trusting_dom_names[i][ascii_dom_name_len - 1] = '\0';
2097                         
2098                         /* calculate padding space for d_printf to look nicer */
2099                         pad_len = col_len - strlen(trusting_dom_names[i]);
2100                         padding[pad_len] = 0;
2101                         do padding[--pad_len] = ' '; while (pad_len);
2102
2103                         /* set opt_* variables to remote domain */
2104                         strupper(trusting_dom_names[i]);
2105                         opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]);
2106                         opt_target_workgroup = opt_workgroup;
2107                         
2108                         d_printf("%s%s", trusting_dom_names[i], padding);
2109                         
2110                         /* connect to remote domain controller */
2111                         remote_cli = net_make_ipc_connection(NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS);
2112                         if (remote_cli) {                       
2113                                 /* query for domain's sid */
2114                                 if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
2115                                         d_printf("couldn't get domain's sid\n");
2116
2117                                 cli_shutdown(remote_cli);
2118                         
2119                         } else {
2120                                 d_printf("domain controller is not responding\n");
2121                         };
2122                 };
2123                 
2124                 if (!num_domains) d_printf("none\n");
2125                 
2126         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
2127
2128         /* close opened samr and domain policy handles */
2129         nt_status = cli_samr_close(cli, mem_ctx, &domain_hnd);
2130         if (!NT_STATUS_IS_OK(nt_status)) {
2131                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
2132         };
2133         
2134         nt_status = cli_samr_close(cli, mem_ctx, &connect_hnd);
2135         if (!NT_STATUS_IS_OK(nt_status)) {
2136                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
2137         };
2138         
2139         /* close samr pipe and connection to IPC$ */
2140         cli_nt_session_close(cli);
2141         cli_shutdown(cli);
2142
2143         talloc_destroy(mem_ctx);         
2144         return 0;
2145 }
2146
2147 /**
2148  * Entrypoint for 'net rpc trustdom' code
2149  *
2150  * @param argc standard argc
2151  * @param argv standard argv without initial components
2152  *
2153  * @return Integer status (0 means success)
2154  */
2155
2156 static int rpc_trustdom(int argc, const char **argv)
2157 {
2158         struct functable func[] = {
2159                 {"add", rpc_trustdom_add},
2160                 {"del", rpc_trustdom_del},
2161                 {"establish", rpc_trustdom_establish},
2162                 {"revoke", rpc_trustdom_revoke},
2163                 {"help", rpc_trustdom_usage},
2164                 {"list", rpc_trustdom_list},
2165                 {NULL, NULL}
2166         };
2167
2168         if (argc == 0) {
2169                 rpc_trustdom_usage(argc, argv);
2170                 return -1;
2171         }
2172
2173         return (net_run_function(argc, argv, func, rpc_user_usage));
2174 }
2175
2176 /**
2177  * Check if a server will take rpc commands
2178  * @param flags Type of server to connect to (PDC, DMB, localhost)
2179  *              if the host is not explicitly specified
2180  * @return  BOOL (true means rpc supported)
2181  */
2182 BOOL net_rpc_check(unsigned flags)
2183 {
2184         struct cli_state cli;
2185         BOOL ret = False;
2186         struct in_addr server_ip;
2187         char *server_name = NULL;
2188
2189         /* flags (i.e. server type) may depend on command */
2190         if (!net_find_server(flags, &server_ip, &server_name))
2191                 return False;
2192
2193         ZERO_STRUCT(cli);
2194         if (cli_initialise(&cli) == False)
2195                 return False;
2196
2197         if (!cli_connect(&cli, server_name, &server_ip))
2198                 goto done;
2199         if (!attempt_netbios_session_request(&cli, global_myname(), 
2200                                              server_name, &server_ip))
2201                 goto done;
2202         if (!cli_negprot(&cli))
2203                 goto done;
2204         if (cli.protocol < PROTOCOL_NT1)
2205                 goto done;
2206
2207         ret = True;
2208  done:
2209         cli_shutdown(&cli);
2210         return ret;
2211 }
2212
2213
2214 /****************************************************************************/
2215
2216
2217 /** 
2218  * Basic usage function for 'net rpc'
2219  * @param argc  Standard main() style argc
2220  * @param argv  Standard main() style argv.  Initial components are already
2221  *              stripped
2222  **/
2223
2224 int net_rpc_usage(int argc, const char **argv) 
2225 {
2226         d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
2227         d_printf("  net rpc join \t\t\tto join a domain \n");
2228         d_printf("  net rpc oldjoin \t\t\tto join a domain created in server manager\n\n\n");
2229         d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
2230         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
2231         d_printf("  net rpc group \t\tto list groups\n");
2232         d_printf("  net rpc share \t\tto add, delete, and list shares\n");
2233         d_printf("  net rpc file \t\t\tto list open files\n");
2234         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
2235         d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
2236         d_printf("  net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
2237         d_printf("  net rpc samdump \t\tdiplay an NT PDC's users, groups and other data\n");
2238         d_printf("  net rpc trustdom \t\tto create trusting domain's account\n"
2239                  "\t\t\t\t\tor establish trust\n");
2240         d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
2241         d_printf("  net rpc shutdown \t\tto shutdown a remote server\n");
2242         d_printf("\n");
2243         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
2244         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
2245         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
2246         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
2247         d_printf("\t-c or --comment=<message>\ttext message to display on impending shutdown\n");
2248         return -1;
2249 }
2250
2251
2252 /**
2253  * Help function for 'net rpc'.  Calls command specific help if requested
2254  * or displays usage of net rpc
2255  * @param argc  Standard main() style argc
2256  * @param argv  Standard main() style argv.  Initial components are already
2257  *              stripped
2258  **/
2259
2260 int net_rpc_help(int argc, const char **argv)
2261 {
2262         struct functable func[] = {
2263                 {"join", rpc_join_usage},
2264                 {"user", rpc_user_usage},
2265                 {"group", rpc_group_usage},
2266                 {"share", rpc_share_usage},
2267                 /*{"changetrustpw", rpc_changetrustpw_usage}, */
2268                 {"trustdom", rpc_trustdom_usage},
2269                 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
2270                 /*{"shutdown", rpc_shutdown_usage}, */
2271                 {NULL, NULL}
2272         };
2273
2274         if (argc == 0) {
2275                 net_rpc_usage(argc, argv);
2276                 return -1;
2277         }
2278
2279         return (net_run_function(argc, argv, func, rpc_user_usage));
2280 }
2281
2282
2283 /** 
2284  * 'net rpc' entrypoint.
2285  * @param argc  Standard main() style argc
2286  * @param argv  Standard main() style argv.  Initial components are already
2287  *              stripped
2288  **/
2289
2290 int net_rpc(int argc, const char **argv)
2291 {
2292         struct functable func[] = {
2293                 {"info", net_rpc_info},
2294                 {"join", net_rpc_join},
2295                 {"oldjoin", net_rpc_oldjoin},
2296                 {"testjoin", net_rpc_testjoin},
2297                 {"user", net_rpc_user},
2298                 {"group", net_rpc_group},
2299                 {"share", net_rpc_share},
2300                 {"file", net_rpc_file},
2301                 {"changetrustpw", net_rpc_changetrustpw},
2302                 {"trustdom", rpc_trustdom},
2303                 {"abortshutdown", rpc_shutdown_abort},
2304                 {"shutdown", rpc_shutdown},
2305                 {"samdump", rpc_samdump},
2306                 {"vampire", rpc_vampire},
2307                 {"getsid", net_rpc_getsid},
2308                 {"help", net_rpc_help},
2309                 {NULL, NULL}
2310         };
2311         return net_run_function(argc, argv, func, net_rpc_usage);
2312 }