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