Change net rpc join several ways: \n\t1) expose \n\t2) eliminate oldstyle subcommand...
[sfrench/samba-autobuild/.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
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19  
20 #include "includes.h"
21 #include "../utils/net.h"
22
23 /**
24  * @file net_rpc.c
25  *
26  * @brief RPC based subcommands for the 'net' utility.
27  *
28  * This file should contain much of the functionality that used to
29  * be found in rpcclient, execpt that the commands should change 
30  * less often, and the fucntionality should be sane (the user is not 
31  * expected to know a rid/sid before they conduct an operation etc.)
32  *
33  * @todo Perhaps eventually these should be split out into a number
34  * of files, as this could get quite big.
35  **/
36
37
38 /* A function of this type is passed to the 'run_rpc_command' wrapper */
39 typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, struct cli_state *, TALLOC_CTX *, int, const char **);
40
41 /**
42  * Many of the RPC functions need the domain sid.  This function gets
43  *  it at the start of every run 
44  *
45  * @param cli A cli_state already connected to the remote machine
46  *
47  * @return The Domain SID of the remote machine.
48  **/
49
50 static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
51 {
52         DOM_SID *domain_sid;
53         POLICY_HND pol;
54         NTSTATUS result = NT_STATUS_OK;
55         uint32 info_class = 5;
56         fstring domain_name;
57         TALLOC_CTX *mem_ctx;
58         
59         if (!(domain_sid = malloc(sizeof(DOM_SID)))){
60                 DEBUG(0,("fetch_domain_sid: malloc returned NULL!\n"));
61                 goto error;
62         }
63             
64         if (!(mem_ctx=talloc_init()))
65         {
66                 DEBUG(0,("fetch_domain_sid: talloc_init returned NULL!\n"));
67                 goto error;
68         }
69
70
71         if (!cli_nt_session_open (cli, PIPE_LSARPC)) {
72                 fprintf(stderr, "could not initialise lsa pipe\n");
73                 goto error;
74         }
75         
76         result = cli_lsa_open_policy(cli, mem_ctx, True, 
77                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
78                                      &pol);
79         if (!NT_STATUS_IS_OK(result)) {
80                 goto error;
81         }
82
83         result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, 
84                                            domain_name, domain_sid);
85         if (!NT_STATUS_IS_OK(result)) {
86                 goto error;
87         }
88
89         cli_lsa_close(cli, mem_ctx, &pol);
90         cli_nt_session_close(cli);
91         talloc_destroy(mem_ctx);
92
93         return domain_sid;
94
95  error:
96         fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
97
98         if (!NT_STATUS_IS_OK(result)) {
99                 fprintf(stderr, "error: %s\n", get_nt_error_msg(result));
100         }
101
102         exit(1);
103 }
104
105 /**
106  * Run a single RPC command, from start to finish.
107  *
108  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
109  * @param conn_flag a NET_FLAG_ combination.  Passed to 
110  *                   net_make_ipc_connection.
111  * @param argc  Standard main() style argc
112  * @param argc  Standard main() style argv.  Initial components are already
113  *              stripped
114  * @return A shell status integer (0 for success)
115  */
116
117 static int run_rpc_command(const char *pipe_name, int conn_flags,
118                            rpc_command_fn fn,
119                            int argc, const char **argv) 
120 {
121         struct cli_state *cli = net_make_ipc_connection(conn_flags);
122         TALLOC_CTX *mem_ctx;
123         NTSTATUS nt_status;
124         DOM_SID *domain_sid;
125
126         if (!cli) {
127                 return -1;
128         }
129
130         domain_sid = net_get_remote_domain_sid(cli);
131
132         /* Create mem_ctx */
133         
134         if (!(mem_ctx = talloc_init())) {
135                 DEBUG(0, ("talloc_init() failed\n"));
136                 cli_shutdown(cli);
137                 return -1;
138         }
139         
140         if (!cli_nt_session_open(cli, pipe_name)) {
141                 DEBUG(0, ("Could not initialise samr pipe\n"));
142         }
143         
144         nt_status = fn(domain_sid, cli, mem_ctx, argc, argv);
145         
146         if (!NT_STATUS_IS_OK(nt_status)) {
147                 DEBUG(0, ("rpc command function failed! (%s)\n", get_nt_error_msg(nt_status)));
148         } else {
149                 DEBUG(5, ("rpc command function succedded\n"));
150         }
151                 
152             
153         if (cli->nt_pipe_fnum)
154                 cli_nt_session_close(cli);
155         
156         talloc_destroy(mem_ctx);
157
158         return (!NT_STATUS_IS_OK(nt_status));
159 }
160
161
162 /****************************************************************************/
163
164
165 /** 
166  * Force a change of the trust acccount password.
167  *
168  * All paramaters are provided by the run_rpc_command funcion, except for
169  * argc, argv which are passes through. 
170  *
171  * @param domain_sid The domain sid aquired from the remote server
172  * @param cli A cli_state connected to the server.
173  * @param mem_ctx Talloc context, destoyed on compleation of the function.
174  * @param argc  Standard main() style argc
175  * @param argc  Standard main() style argv.  Initial components are already
176  *              stripped
177  *
178  * @return Normal NTSTATUS return.
179  **/
180
181 static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
182                                        int argc, const char **argv) {
183         
184         return trust_pw_find_change_and_store_it(cli, mem_ctx, opt_target_workgroup);
185 }
186
187 /** 
188  * Force a change of the trust acccount password.
189  *
190  * @param argc  Standard main() style argc
191  * @param argc  Standard main() style argv.  Initial components are already
192  *              stripped
193  *
194  * @return A shell status integer (0 for success)
195  **/
196
197 static int rpc_changetrustpw(int argc, const char **argv) 
198 {
199         return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_changetrustpw_internals,
200                                argc, argv);
201 }
202
203
204 /****************************************************************************/
205
206
207 /** 
208  * Join a domain, the old way.
209  *
210  * This uses 'machinename' as the inital password, and changes it. 
211  *
212  * The password should be created with 'server manager' or eqiv first.
213  *
214  * All paramaters are provided by the run_rpc_command funcion, except for
215  * argc, argv which are passes through. 
216  *
217  * @param domain_sid The domain sid aquired from the remote server
218  * @param cli A cli_state connected to the server.
219  * @param mem_ctx Talloc context, destoyed on compleation of the function.
220  * @param argc  Standard main() style argc
221  * @param argc  Standard main() style argv.  Initial components are already
222  *              stripped
223  *
224  * @return Normal NTSTATUS return.
225  **/
226
227 static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
228                                        int argc, const char **argv) {
229         
230         extern pstring global_myname;
231         fstring trust_passwd;
232         unsigned char orig_trust_passwd_hash[16];
233
234         fstrcpy(trust_passwd, global_myname);
235         strlower(trust_passwd);
236         E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash);
237
238         return trust_pw_change_and_store_it(cli, mem_ctx, orig_trust_passwd_hash);
239 }
240
241 /** 
242  * Join a domain, the old way.
243  *
244  * @param argc  Standard main() style argc
245  * @param argc  Standard main() style argv.  Initial components are already
246  *              stripped
247  *
248  * @return A shell status integer (0 for success)
249  **/
250
251 static int net_rpc_join_oldstyle(int argc, const char **argv) 
252 {
253         return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_join_oldstyle_internals,
254                                argc, argv);
255 }
256
257 /** 
258  * Basic usage function for 'net rpc join'
259  * @param argc  Standard main() style argc
260  * @param argc  Standard main() style argv.  Initial components are already
261  *              stripped
262  **/
263
264 static int rpc_join_usage(int argc, const char **argv) 
265 {       
266         d_printf("net rpc join -U <username>[%%password] [options]\n"\
267                  "\t to join a domain with admin username & password\n"\
268                  "\t\t password will be prompted if none is specified\n");
269         d_printf("net rpc join [options except -U]\n"\
270                  "\t to join a domain created in server manager\n\n\n");
271
272         net_common_flags_usage(argc, argv);
273         return -1;
274 }
275
276 /** 
277  * 'net rpc join' entrypoint.
278  * @param argc  Standard main() style argc
279  * @param argc  Standard main() style argv.  Initial components are already
280  *              stripped
281  *
282  * Main 'net_rpc_join()' (where the admain username/password is used) is 
283  * in net_rpc_join.c
284  * Assume if a -U is specified, it's the new style, otherwise it's the
285  * old style
286  **/
287
288 int net_rpc_join(int argc, const char **argv) 
289 {
290         if ((net_rpc_join_oldstyle(argc, argv) == 0))
291                 return 0;
292         
293         return net_rpc_join_newstyle(argc, argv);
294 }
295
296
297 /****************************************************************************/
298
299
300 /** 
301  * Add a new user to a remote RPC server
302  *
303  * All paramaters are provided by the run_rpc_command funcion, except for
304  * argc, argv which are passes through. 
305  *
306  * @param domain_sid The domain sid acquired from the remote server
307  * @param cli A cli_state connected to the server.
308  * @param mem_ctx Talloc context, destoyed on completion of the function.
309  * @param argc  Standard main() style argc
310  * @param argc  Standard main() style argv.  Initial components are already
311  *              stripped
312  *
313  * @return Normal NTSTATUS return.
314  **/
315
316 static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
317                                        int argc, const char **argv) {
318         
319         POLICY_HND connect_pol, domain_pol, user_pol;
320         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
321         const char *acct_name;
322         uint16 acb_info;
323         uint32 unknown, user_rid;
324
325         if (argc != 1) {
326                 d_printf("Usage: net rpc user add username\n");
327                 return NT_STATUS_OK;
328         }
329
330         acct_name = argv[0];
331
332         /* Get sam policy handle */
333         
334         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
335                                   &connect_pol);
336         if (!NT_STATUS_IS_OK(result)) {
337                 goto done;
338         }
339         
340         /* Get domain policy handle */
341         
342         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
343                                       MAXIMUM_ALLOWED_ACCESS,
344                                       domain_sid, &domain_pol);
345         if (!NT_STATUS_IS_OK(result)) {
346                 goto done;
347         }
348
349         /* Create domain user */
350
351         acb_info = ACB_NORMAL;
352         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
353
354         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
355                                           acct_name, acb_info, unknown,
356                                           &user_pol, &user_rid);
357         if (!NT_STATUS_IS_OK(result)) {
358                 goto done;
359         }
360
361  done:
362         if (!NT_STATUS_IS_OK(result)) {
363                 d_printf("Failed to add user %s - %s\n", acct_name, 
364                          get_nt_error_msg(result));
365         } else {
366                 d_printf("Added user %s\n", acct_name);
367         }
368         return result;
369 }
370
371 /** 
372  * Add a new user to a remote RPC server
373  *
374  * @param argc  Standard main() style argc
375  * @param argc  Standard main() style argv.  Initial components are already
376  *              stripped
377  *
378  * @return A shell status integer (0 for success)
379  **/
380
381 static int rpc_user_add(int argc, const char **argv) 
382 {
383         return run_rpc_command(PIPE_SAMR, 0, rpc_user_add_internals,
384                                argc, argv);
385 }
386
387 /** 
388  * Basic usage function for 'net rpc user'
389  * @param argc  Standard main() style argc
390  * @param argc  Standard main() style argv.  Initial components are already
391  *              stripped
392  **/
393
394 static int rpc_user_usage(int argc, const char **argv) 
395 {
396         d_printf("  net rpc user add \t to add a user\n");
397         return -1;
398 }
399
400 /** 
401  * 'net rpc user' entrypoint.
402  * @param argc  Standard main() style argc
403  * @param argc  Standard main() style argv.  Initial components are already
404  *              stripped
405  **/
406
407 static int rpc_user(int argc, const char **argv) 
408 {
409         struct functable func[] = {
410                 {"add", rpc_user_add},
411                 {NULL, NULL}
412         };
413         
414         if (argc == 0) {
415                 return rpc_user_usage(argc, argv);
416         }
417
418         return net_run_function(argc, argv, func, rpc_user_usage);
419 }
420
421
422 /****************************************************************************/
423
424
425
426 /** 
427  * ABORT the shutdown of a remote RPC Server
428  *
429  * All paramaters are provided by the run_rpc_command funcion, except for
430  * argc, argv which are passed through. 
431  *
432  * @param domain_sid The domain sid aquired from the remote server
433  * @param cli A cli_state connected to the server.
434  * @param mem_ctx Talloc context, destoyed on compleation of the function.
435  * @param argc  Standard main() style argc
436  * @param argc  Standard main() style argv.  Initial components are already
437  *              stripped
438  *
439  * @return Normal NTSTATUS return.
440  **/
441
442 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
443                                              int argc, const char **argv) 
444 {
445         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
446         
447         result = cli_reg_abort_shutdown(cli, mem_ctx);
448         
449         if (NT_STATUS_IS_OK(result))
450                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
451         else
452                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
453         
454         return result;
455 }
456
457
458 /** 
459  * ABORT the Shut down of a remote RPC server
460  *
461  * @param argc  Standard main() style argc
462  * @param argc  Standard main() style argv.  Initial components are already
463  *              stripped
464  *
465  * @return A shell status integer (0 for success)
466  **/
467
468 static int rpc_shutdown_abort(int argc, const char **argv) 
469 {
470         return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_abort_internals,
471                                argc, argv);
472 }
473
474 /** 
475  * Shut down a remote RPC Server
476  *
477  * All paramaters are provided by the run_rpc_command funcion, except for
478  * argc, argv which are passes through. 
479  *
480  * @param domain_sid The domain sid aquired from the remote server
481  * @param cli A cli_state connected to the server.
482  * @param mem_ctx Talloc context, destoyed on compleation of the function.
483  * @param argc  Standard main() style argc
484  * @param argc  Standard main() style argv.  Initial components are already
485  *              stripped
486  *
487  * @return Normal NTSTATUS return.
488  **/
489
490 static NTSTATUS rpc_shutdown_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
491                                        int argc, const char **argv) 
492 {
493         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
494         char *msg = "This machine will be shutdown shortly";
495         uint32 timeout = 20;
496         uint16 flgs = 0;
497         BOOL reboot = opt_reboot;
498         BOOL force = opt_force;
499 #if 0
500         poptContext pc;
501         int rc;
502
503         struct poptOption long_options[] = {
504                 {"message",    'm', POPT_ARG_STRING, &msg},
505                 {"timeout",    't', POPT_ARG_INT,    &timeout},
506                 {"reboot",     'r', POPT_ARG_NONE,   &reboot},
507                 {"force",      'f', POPT_ARG_NONE,   &force},
508                 { 0, 0, 0, 0}
509         };
510
511         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
512                             POPT_CONTEXT_KEEP_FIRST);
513
514         rc = poptGetNextOpt(pc);
515         
516         if (rc < -1) {
517                 /* an error occurred during option processing */
518                 DEBUG(0, ("%s: %s\n",
519                           poptBadOption(pc, POPT_BADOPTION_NOALIAS),
520                           poptStrerror(rc)));
521                 return NT_STATUS_INVALID_PARAMETER;
522         }
523 #endif
524         if (reboot) {
525                 flgs |= REG_REBOOT_ON_SHUTDOWN;
526         }
527         if (force) {
528                 flgs |= REG_FORCE_SHUTDOWN;
529         }
530         if (opt_comment) {
531                 msg = opt_comment;
532         }
533         if (opt_timeout) {
534                 timeout = opt_timeout;
535         }
536
537         /* create an entry */
538         result = cli_reg_shutdown(cli, mem_ctx, msg, timeout, flgs);
539
540         if (NT_STATUS_IS_OK(result))
541                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
542         else
543                 DEBUG(0,("Shutdown of remote machine failed!\n"));
544
545         return result;
546 }
547
548 /** 
549  * Shut down a remote RPC server
550  *
551  * @param argc  Standard main() style argc
552  * @param argc  Standard main() style argv.  Initial components are already
553  *              stripped
554  *
555  * @return A shell status integer (0 for success)
556  **/
557
558 static int rpc_shutdown(int argc, const char **argv) 
559 {
560         return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_internals,
561                                        argc, argv);
562 }
563
564 /***************************************************************************
565   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
566   
567  ***************************************************************************/
568
569 /**
570  * Add interdomain trust account to the RPC server.
571  * All parameters (except for argc and argv) are passed by run_rpc_command
572  * function.
573  *
574  * @param domain_sid The domain sid acquired from the server
575  * @param cli A cli_state connected to the server.
576  * @param mem_ctx Talloc context, destoyed on completion of the function.
577  * @param argc  Standard main() style argc
578  * @param argc  Standard main() style argv.  Initial components are already
579  *              stripped
580  *
581  * @return normal NTSTATUS return code
582  */
583
584 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
585                                        int argc, const char **argv) {
586
587         POLICY_HND connect_pol, domain_pol, user_pol;
588         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
589         char *acct_name;
590         uint16 acb_info;
591         uint32 unknown, user_rid;
592
593         if (argc != 1) {
594                 d_printf("Usage: net rpc trustdom add <domain_name>\n");
595                 return NT_STATUS_OK;
596         }
597
598         /* 
599          * Make valid trusting domain account (ie. uppercased and with '$' appended)
600          */
601          
602         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
603                 return NT_STATUS_NO_MEMORY;
604         }
605
606         strupper(acct_name);
607
608         /* Get sam policy handle */
609         
610         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
611                                   &connect_pol);
612         if (!NT_STATUS_IS_OK(result)) {
613                 goto done;
614         }
615         
616         /* Get domain policy handle */
617         
618         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
619                                       MAXIMUM_ALLOWED_ACCESS,
620                                       domain_sid, &domain_pol);
621         if (!NT_STATUS_IS_OK(result)) {
622                 goto done;
623         }
624
625         /* Create trusting domain's account */
626
627         acb_info = ACB_DOMTRUST;
628         unknown = 0xe005000b; /* No idea what this is - a permission mask? 
629                                  Is it needed for interdomain account also ? */
630
631         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
632                                           acct_name, acb_info, unknown,
633                                           &user_pol, &user_rid);
634         if (!NT_STATUS_IS_OK(result)) {
635                 goto done;
636         }
637
638  done:
639         SAFE_FREE(acct_name);
640         return result;
641 }
642
643 /**
644  * Create interdomain trust account for a remote domain.
645  *
646  * @param argc standard argc
647  * @param argv standard argv without initial components
648  *
649  * @return Integer status (0 means success)
650  **/
651
652 static int rpc_trustdom_add(int argc, const char **argv)
653 {
654         return run_rpc_command(PIPE_SAMR, 0, rpc_trustdom_add_internals,
655                                argc, argv);
656 }
657
658
659 /**
660  * Delete interdomain trust account for a remote domain.
661  *
662  * @param argc standard argc
663  * @param argv standard argv without initial components
664  *
665  * @return Integer status (0 means success)
666  **/
667  
668 static int rpc_trustdom_del(int argc, const char **argv)
669 {
670         d_printf("Sorry, not yet implemented.\n");
671         return -1;
672 }
673
674  
675 /**
676  * Establish trust relationship to a trusting domain.
677  * Interdomain account must already be created on remote PDC.
678  *
679  * @param argc standard argc
680  * @param argv standard argv without initial components
681  *
682  * @return Integer status (0 means success)
683  **/
684
685 extern char *opt_user_name;
686 extern char *opt_password;
687
688 static int rpc_trustdom_establish(int argc, const char **argv) {
689
690         struct cli_state *cli;
691         struct in_addr server_ip;
692         POLICY_HND connect_hnd;
693         TALLOC_CTX *mem_ctx;
694         NTSTATUS nt_status;
695         DOM_SID domain_sid;
696         WKS_INFO_100 wks_info;
697         
698         char* domain_name;
699         char* acct_name;
700         fstring pdc_name;
701
702         /*
703          * Connect to \\server\ipc$ as 'our domain' account with password
704          */
705
706         domain_name = smb_xstrdup(argv[0]);
707         strupper(domain_name);
708         
709         asprintf(&acct_name, "%s$", lp_workgroup());
710         strupper(acct_name);
711         
712         opt_user_name = (char*)malloc(strlen(acct_name) + 1);
713         safe_strcpy(opt_user_name, acct_name, strlen(acct_name) + 1);
714
715         /* find the domain controller */
716         if (!net_find_dc(&server_ip, pdc_name, domain_name)) {
717                 DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name));
718                 return -1;
719         }
720
721         /* connect to ipc$ as username/password */
722         nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
723         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
724
725                 /* Is it trusting domain account for sure ? */
726                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
727                         get_nt_error_msg(nt_status)));
728                 return -1;
729         }
730         
731         /*
732          * Connect to \\server\ipc$ again (this time anonymously)
733          */
734         
735         nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
736         
737         if (NT_STATUS_IS_ERR(nt_status)) {
738                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
739                         domain_name, get_nt_error_msg(nt_status)));
740         }
741
742         /*
743          * Use NetServerEnum2 to make sure we're talking to a proper server
744          */
745          
746         if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
747                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
748                          for domain %s\n", domain_name));
749         }
750          
751         /*
752          * Call WksQueryInfo to check remote server's capabilities
753          * FIXME:Is really necessary ? nt serv does this, but from samba's
754          *       point of view it doesn't seem to make the difference
755          * IDEA: It may be used to get info about type of pdc we're talking to
756          *       (e.g. WinNT or Win2k)
757          */
758         
759         if (!cli_nt_session_open(cli, PIPE_WKSSVC)) {
760                 DEBUG(0, ("Couldn't not initialise wkssvc pipe\n"));
761                 return -1;
762         }
763
764         /* TODO: convert this call from rpc_client/cli_wkssvc.c
765            to cli_wks_query_info() in libsmb/cli_wkssvc.c
766            UPDATE: already done :)
767         */
768
769         if (!(mem_ctx = talloc_init())) {
770                 DEBUG(0, ("talloc_init() failed\n"));
771                 cli_shutdown(cli);
772                 return -1;
773         }
774         
775         nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info);
776         
777         if (NT_STATUS_IS_ERR(nt_status)) {
778                 DEBUG(0, ("WksQueryInfo call failed.\n"));
779                 return -1;
780         }
781
782         if (cli->nt_pipe_fnum) {
783                 cli_nt_session_close(cli);
784                 talloc_destroy(mem_ctx);
785         }
786
787
788         /*
789          * Call LsaOpenPolicy and LsaQueryInfo
790          */
791          
792         if (!(mem_ctx = talloc_init())) {
793                 DEBUG(0, ("talloc_init() failed\n"));
794                 cli_shutdown(cli);
795                 return -1;
796         }
797
798         if (!cli_nt_session_open(cli, PIPE_LSARPC)) {
799                 DEBUG(0, ("Could not initialise lsa pipe\n"));
800         }
801
802         nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
803                                         &connect_hnd);
804         if (NT_STATUS_IS_ERR(nt_status)) {
805                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
806                         get_nt_error_msg(nt_status)));
807                 return -1;
808         }
809
810         /* Querying info level 5 */
811         
812         nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
813                                         5 /* info level */, domain_name, &domain_sid);
814         if (NT_STATUS_IS_ERR(nt_status)) {
815                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
816                         get_nt_error_msg(nt_status)));
817                 return -1;
818         }
819
820
821         /* There should be actually query info level 3 (following nt serv behaviour),
822            but I still don't know if it's _really_ necessary */
823                         
824         /*
825          * Close the pipes and clean up
826          */
827          
828         nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
829         if (NT_STATUS_IS_ERR(nt_status)) {
830                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
831                         get_nt_error_msg(nt_status)));
832                 return -1;
833         }
834
835         if (cli->nt_pipe_fnum)
836                 cli_nt_session_close(cli);
837
838         talloc_destroy(mem_ctx);
839          
840          
841         /*
842          * Store the password in secrets db
843          */
844
845         if (!secrets_store_trusted_domain_password(domain_name, opt_password,
846                                                    domain_sid)) {
847                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
848                 return -1;
849         }
850         
851         DEBUG(0, ("Success!\n"));
852         return 0;
853 }
854
855 /**
856  * Revoke trust relationship to the remote domain
857  *
858  * @param argc standard argc
859  * @param argv standard argv without initial components
860  *
861  * @return Integer status (0 means success)
862  **/
863
864 static int rpc_trustdom_revoke(int argc, const char **argv) {
865
866         char* domain_name;
867
868         if (argc < 1) return -1;
869         
870         /* generate upper cased domain name */
871         domain_name = smb_xstrdup(argv[0]);
872         strupper(domain_name);
873
874         /* delete password of the trust */
875         if (!trusted_domain_password_delete(domain_name)) {
876                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
877                           domain_name));
878                 return -1;
879         };
880         
881         return 0;
882 }
883
884 /**
885  * Usage for 'net rpc trustdom' command
886  *
887  * @param argc standard argc
888  * @param argv standard argv without inital components
889  *
890  * @return Integer status returned to shell
891  **/
892  
893 static int rpc_trustdom_usage(int argc, const char **argv) {
894         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
895         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
896         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
897         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
898         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
899         return -1;
900 }
901
902
903 /**
904  * Entrypoint for 'net rpc trustdom' code
905  *
906  * @param argc standard argc
907  * @param argv standard argv without initial components
908  *
909  * @return Integer status (0 means success)
910  */
911
912 static int rpc_trustdom(int argc, const char **argv)
913 {
914         struct functable func[] = {
915                 {"add", rpc_trustdom_add},
916                 {"del", rpc_trustdom_del},
917                 {"establish", rpc_trustdom_establish},
918                 {"revoke", rpc_trustdom_revoke},
919                 {"help", rpc_trustdom_usage},
920                 {NULL, NULL}
921         };
922
923         if (argc == 0) {
924                 rpc_trustdom_usage(argc, argv);
925                 return -1;
926         }
927
928         return (net_run_function(argc, argv, func, rpc_user_usage));
929 }
930
931 /****************************************************************************/
932
933
934 /** 
935  * Basic usage function for 'net rpc'
936  * @param argc  Standard main() style argc
937  * @param argv  Standard main() style argv.  Initial components are already
938  *              stripped
939  **/
940
941 int net_rpc_usage(int argc, const char **argv) 
942 {
943         d_printf("  net rpc join \t\t\tto join a domain \n");
944         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
945         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
946         d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
947         d_printf("  net rpc abortshutdown \tto to abort the shutdown of a remote server\n");
948         d_printf("  net rpc shutdown \t\tto to shutdown a remote server\n");
949         d_printf("\n");
950         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
951         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
952         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
953         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
954         d_printf("\t-c or --comment=<message>\ttext message to display on impending shutdown\n");
955         return -1;
956 }
957
958
959 /**
960  * Help function for 'net rpc'.  Calls command specific help if requested
961  * or displays usage of net rpc
962  * @param argc  Standard main() style argc
963  * @param argv  Standard main() style argv.  Initial components are already
964  *              stripped
965  **/
966
967 int net_rpc_help(int argc, const char **argv)
968 {
969         struct functable func[] = {
970                 {"join", rpc_join_usage},
971                 {"user", rpc_user_usage},
972                 //{"changetrustpw", rpc_changetrustpw_usage},
973                 {"trustdom", rpc_trustdom_usage},
974                 //{"abortshutdown", rpc_shutdown_abort_usage},
975                 //{"shutdown", rpc_shutdown_usage},
976                 {NULL, NULL}
977         };
978
979         if (argc == 0) {
980                 net_rpc_usage(argc, argv);
981                 return -1;
982         }
983
984         return (net_run_function(argc, argv, func, rpc_user_usage));
985 }
986
987
988 /** 
989  * 'net rpc' entrypoint.
990  * @param argc  Standard main() style argc
991  * @param argv  Standard main() style argv.  Initial components are already
992  *              stripped
993  **/
994
995 int net_rpc(int argc, const char **argv)
996 {
997         struct functable func[] = {
998                 {"join", net_rpc_join},
999                 {"user", rpc_user},
1000                 {"changetrustpw", rpc_changetrustpw},
1001                 {"trustdom", rpc_trustdom},
1002                 {"abortshutdown", rpc_shutdown_abort},
1003                 {"shutdown", rpc_shutdown},
1004                 {"help", net_rpc_help},
1005                 {NULL, NULL}
1006         };
1007         return net_run_function(argc, argv, func, net_rpc_usage);
1008 }