Some help cleanups. Formatting and consistency issues. Line up text nicely, and...
[bbaumbach/samba-autobuild/.git] / source / utils / net_rpc.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5
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 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 \t to join a domain with admin username & password\n");
267         d_printf("  net rpc join oldstyle \t to join a domain created in server manager\n");
268         return -1;
269 }
270
271 /** 
272  * 'net rpc join' entrypoint.
273  * @param argc  Standard main() style argc
274  * @param argc  Standard main() style argv.  Initial components are already
275  *              stripped
276  *
277  * Main 'net_rpc_join()' (where the admain username/password is used) is 
278  * in net_rpc_join.c
279  **/
280
281 static int rpc_join(int argc, const char **argv) 
282 {
283         struct functable func[] = {
284                 {"oldstyle", rpc_join_oldstyle},
285                 {NULL, NULL}
286         };
287         
288         if (argc == 0) {
289                 return net_rpc_join(argc, argv);
290         }
291
292         return net_run_function(argc, argv, func, rpc_join_usage);
293 }
294
295
296 /****************************************************************************/
297
298
299 /** 
300  * Add a new user to a remote RPC server
301  *
302  * All paramaters are provided by the run_rpc_command funcion, except for
303  * argc, argv which are passes through. 
304  *
305  * @param domain_sid The domain sid acquired from the remote server
306  * @param cli A cli_state connected to the server.
307  * @param mem_ctx Talloc context, destoyed on completion of the function.
308  * @param argc  Standard main() style argc
309  * @param argc  Standard main() style argv.  Initial components are already
310  *              stripped
311  *
312  * @return Normal NTSTATUS return.
313  **/
314
315 static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
316                                        int argc, const char **argv) {
317         
318         POLICY_HND connect_pol, domain_pol, user_pol;
319         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
320         const char *acct_name;
321         uint16 acb_info;
322         uint32 unknown, user_rid;
323
324         if (argc != 1) {
325                 d_printf("Usage: net rpc user add username\n");
326                 return NT_STATUS_OK;
327         }
328
329         acct_name = argv[0];
330
331         /* Get sam policy handle */
332         
333         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
334                                   &connect_pol);
335         if (!NT_STATUS_IS_OK(result)) {
336                 goto done;
337         }
338         
339         /* Get domain policy handle */
340         
341         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
342                                       MAXIMUM_ALLOWED_ACCESS,
343                                       domain_sid, &domain_pol);
344         if (!NT_STATUS_IS_OK(result)) {
345                 goto done;
346         }
347
348         /* Create domain user */
349
350         acb_info = ACB_NORMAL;
351         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
352
353         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
354                                           acct_name, acb_info, unknown,
355                                           &user_pol, &user_rid);
356         if (!NT_STATUS_IS_OK(result)) {
357                 goto done;
358         }
359
360  done:
361         if (!NT_STATUS_IS_OK(result)) {
362                 d_printf("Failed to add user %s - %s\n", acct_name, 
363                          get_nt_error_msg(result));
364         } else {
365                 d_printf("Added user %s\n", acct_name);
366         }
367         return result;
368 }
369
370 /** 
371  * Add a new user to a remote RPC server
372  *
373  * @param argc  Standard main() style argc
374  * @param argc  Standard main() style argv.  Initial components are already
375  *              stripped
376  *
377  * @return A shell status integer (0 for success)
378  **/
379
380 static int rpc_user_add(int argc, const char **argv) 
381 {
382         return run_rpc_command(PIPE_SAMR, 0, rpc_user_add_internals,
383                                argc, argv);
384 }
385
386 /** 
387  * Basic usage function for 'net rpc user'
388  * @param argc  Standard main() style argc
389  * @param argc  Standard main() style argv.  Initial components are already
390  *              stripped
391  **/
392
393 static int rpc_user_usage(int argc, const char **argv) 
394 {
395         d_printf("  net rpc user add \t to add a user\n");
396         return -1;
397 }
398
399 /** 
400  * 'net rpc user' entrypoint.
401  * @param argc  Standard main() style argc
402  * @param argc  Standard main() style argv.  Initial components are already
403  *              stripped
404  **/
405
406 static int rpc_user(int argc, const char **argv) 
407 {
408         struct functable func[] = {
409                 {"add", rpc_user_add},
410                 {NULL, NULL}
411         };
412         
413         if (argc == 0) {
414                 return rpc_user_usage(argc, argv);
415         }
416
417         return net_run_function(argc, argv, func, rpc_user_usage);
418 }
419
420
421 /****************************************************************************/
422
423
424
425 /** 
426  * ABORT the shutdown of a remote RPC Server
427  *
428  * All paramaters are provided by the run_rpc_command funcion, except for
429  * argc, argv which are passed through. 
430  *
431  * @param domain_sid The domain sid aquired from the remote server
432  * @param cli A cli_state connected to the server.
433  * @param mem_ctx Talloc context, destoyed on compleation of the function.
434  * @param argc  Standard main() style argc
435  * @param argc  Standard main() style argv.  Initial components are already
436  *              stripped
437  *
438  * @return Normal NTSTATUS return.
439  **/
440
441 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
442                                              int argc, const char **argv) 
443 {
444         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
445         
446         result = cli_reg_abort_shutdown(cli, mem_ctx);
447         
448         if (NT_STATUS_IS_OK(result))
449                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
450         else
451                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
452         
453         return result;
454 }
455
456
457 /** 
458  * ABORT the Shut down of a remote RPC server
459  *
460  * @param argc  Standard main() style argc
461  * @param argc  Standard main() style argv.  Initial components are already
462  *              stripped
463  *
464  * @return A shell status integer (0 for success)
465  **/
466
467 static int rpc_shutdown_abort(int argc, const char **argv) 
468 {
469         return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_abort_internals,
470                                argc, argv);
471 }
472
473 /** 
474  * Shut down a remote RPC Server
475  *
476  * All paramaters are provided by the run_rpc_command funcion, except for
477  * argc, argv which are passes through. 
478  *
479  * @param domain_sid The domain sid aquired from the remote server
480  * @param cli A cli_state connected to the server.
481  * @param mem_ctx Talloc context, destoyed on compleation of the function.
482  * @param argc  Standard main() style argc
483  * @param argc  Standard main() style argv.  Initial components are already
484  *              stripped
485  *
486  * @return Normal NTSTATUS return.
487  **/
488
489 static NTSTATUS rpc_shutdown_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
490                                        int argc, const char **argv) 
491 {
492         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
493         char *msg = "This machine will be shutdown shortly";
494         uint32 timeout = 20;
495         uint16 flgs = 0;
496         BOOL reboot = opt_reboot;
497         BOOL force = opt_force;
498 #if 0
499         poptContext pc;
500         int rc;
501
502         struct poptOption long_options[] = {
503                 {"message",    'm', POPT_ARG_STRING, &msg},
504                 {"timeout",    't', POPT_ARG_INT,    &timeout},
505                 {"reboot",     'r', POPT_ARG_NONE,   &reboot},
506                 {"force",      'f', POPT_ARG_NONE,   &force},
507                 { 0, 0, 0, 0}
508         };
509
510         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
511                             POPT_CONTEXT_KEEP_FIRST);
512
513         rc = poptGetNextOpt(pc);
514         
515         if (rc < -1) {
516                 /* an error occurred during option processing */
517                 DEBUG(0, ("%s: %s\n",
518                           poptBadOption(pc, POPT_BADOPTION_NOALIAS),
519                           poptStrerror(rc)));
520                 return NT_STATUS_INVALID_PARAMETER;
521         }
522 #endif
523         if (reboot) {
524                 flgs |= REG_REBOOT_ON_SHUTDOWN;
525         }
526         if (force) {
527                 flgs |= REG_FORCE_SHUTDOWN;
528         }
529         if (opt_comment) {
530                 msg = opt_comment;
531         }
532         if (opt_timeout) {
533                 timeout = opt_timeout;
534         }
535
536         /* create an entry */
537         result = cli_reg_shutdown(cli, mem_ctx, msg, timeout, flgs);
538
539         if (NT_STATUS_IS_OK(result))
540                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
541         else
542                 DEBUG(0,("Shutdown of remote machine failed!\n"));
543
544         return result;
545 }
546
547 /** 
548  * Shut down a remote RPC server
549  *
550  * @param argc  Standard main() style argc
551  * @param argc  Standard main() style argv.  Initial components are already
552  *              stripped
553  *
554  * @return A shell status integer (0 for success)
555  **/
556
557 static int rpc_shutdown(int argc, const char **argv) 
558 {
559         return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_internals,
560                                        argc, argv);
561 }
562
563 /***************************************************************************
564   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
565   
566  ***************************************************************************/
567
568 /**
569  * Add interdomain trust account to the RPC server.
570  * All parameters (except for argc and argv) are passed by run_rpc_command
571  * function.
572  *
573  * @param domain_sid The domain sid acquired from the server
574  * @param cli A cli_state connected to the server.
575  * @param mem_ctx Talloc context, destoyed on completion of the function.
576  * @param argc  Standard main() style argc
577  * @param argc  Standard main() style argv.  Initial components are already
578  *              stripped
579  *
580  * @return normal NTSTATUS return code
581  */
582
583 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
584                                        int argc, const char **argv) {
585
586         POLICY_HND connect_pol, domain_pol, user_pol;
587         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
588         char *acct_name;
589         uint16 acb_info;
590         uint32 unknown, user_rid;
591
592         if (argc != 1) {
593                 d_printf("Usage: net rpc trustdom add <domain_name>\n");
594                 return NT_STATUS_OK;
595         }
596
597         /* 
598          * Make valid trusting domain account (ie. uppercased and with '$' appended)
599          */
600          
601         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
602                 return NT_STATUS_NO_MEMORY;
603         }
604
605         strupper(acct_name);
606
607         /* Get sam policy handle */
608         
609         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
610                                   &connect_pol);
611         if (!NT_STATUS_IS_OK(result)) {
612                 goto done;
613         }
614         
615         /* Get domain policy handle */
616         
617         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
618                                       MAXIMUM_ALLOWED_ACCESS,
619                                       domain_sid, &domain_pol);
620         if (!NT_STATUS_IS_OK(result)) {
621                 goto done;
622         }
623
624         /* Create trusting domain's account */
625
626         acb_info = ACB_DOMTRUST;
627         unknown = 0xe005000b; /* No idea what this is - a permission mask? 
628                                  Is it needed for interdomain account also ? */
629
630         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
631                                           acct_name, acb_info, unknown,
632                                           &user_pol, &user_rid);
633         if (!NT_STATUS_IS_OK(result)) {
634                 goto done;
635         }
636
637  done:
638         SAFE_FREE(acct_name);
639         return result;
640 }
641
642 /**
643  * Create interdomain trust account for a remote domain.
644  *
645  * @param argc standard argc
646  * @param argv standard argv without initial components
647  *
648  * @return Integer status (0 means success)
649  **/
650
651 static int rpc_trustdom_add(int argc, const char **argv)
652 {
653         return run_rpc_command(PIPE_SAMR, 0, rpc_trustdom_add_internals,
654                                argc, argv);
655 }
656
657
658 /**
659  * Delete interdomain trust account for a remote domain.
660  *
661  * @param argc standard argc
662  * @param argv standard argv without initial components
663  *
664  * @return Integer status (0 means success)
665  **/
666  
667 static int rpc_trustdom_del(int argc, const char **argv)
668 {
669         d_printf("Sorry, not yet implemented.\n");
670         return -1;
671 }
672
673  
674 /**
675  * Establish trust relationship to a trusting domain.
676  * Interdomain account must already be created on remote PDC.
677  *
678  * @param argc standard argc
679  * @param argv standard argv without initial components
680  *
681  * @return Integer status (0 means success)
682  **/
683
684 extern char *opt_user_name;
685 extern char *opt_password;
686
687 static int rpc_trustdom_establish(int argc, const char **argv) {
688
689         struct cli_state *cli;
690         struct in_addr server_ip;
691         POLICY_HND connect_hnd;
692         TALLOC_CTX *mem_ctx;
693         NTSTATUS nt_status;
694         DOM_SID domain_sid;
695         WKS_INFO_100 wks_info;
696         
697         char* domain_name;
698         char* acct_name;
699         fstring pdc_name;
700
701         /*
702          * Connect to \\server\ipc$ as 'our domain' account with password
703          */
704
705         domain_name = smb_xstrdup(argv[0]);
706         strupper(domain_name);
707         
708         asprintf(&acct_name, "%s$", lp_workgroup());
709         strupper(acct_name);
710         
711         opt_user_name = (char*)malloc(strlen(acct_name) + 1);
712         safe_strcpy(opt_user_name, acct_name, strlen(acct_name) + 1);
713
714         /* find the domain controller */
715         if (!net_find_dc(&server_ip, pdc_name, domain_name)) {
716                 DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name));
717                 return -1;
718         }
719
720         /* connect to ipc$ as username/password */
721         nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
722         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
723
724                 /* Is it trusting domain account for sure ? */
725                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
726                         get_nt_error_msg(nt_status)));
727                 return -1;
728         }
729         
730         /*
731          * Connect to \\server\ipc$ again (this time anonymously)
732          */
733         
734         nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
735         
736         if (NT_STATUS_IS_ERR(nt_status)) {
737                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
738                         domain_name, get_nt_error_msg(nt_status)));
739         }
740
741         /*
742          * Use NetServerEnum2 to make sure we're talking to a proper server
743          */
744          
745         if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
746                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
747                          for domain %s\n", domain_name));
748         }
749          
750         /*
751          * Call WksQueryInfo to check remote server's capabilities
752          * FIXME:Is really necessary ? nt serv does this, but from samba's
753          *       point of view it doesn't seem to make the difference
754          * IDEA: It may be used to get info about type of pdc we're talking to
755          *       (e.g. WinNT or Win2k)
756          */
757         
758         if (!cli_nt_session_open(cli, PIPE_WKSSVC)) {
759                 DEBUG(0, ("Couldn't not initialise wkssvc pipe\n"));
760                 return -1;
761         }
762
763         /* TODO: convert this call from rpc_client/cli_wkssvc.c
764            to cli_wks_query_info() in libsmb/cli_wkssvc.c
765            UPDATE: already done :)
766         */
767
768         if (!(mem_ctx = talloc_init())) {
769                 DEBUG(0, ("talloc_init() failed\n"));
770                 cli_shutdown(cli);
771                 return -1;
772         }
773         
774         nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info);
775         
776         if (NT_STATUS_IS_ERR(nt_status)) {
777                 DEBUG(0, ("WksQueryInfo call failed.\n"));
778                 return -1;
779         }
780
781         if (cli->nt_pipe_fnum) {
782                 cli_nt_session_close(cli);
783                 talloc_destroy(mem_ctx);
784         }
785
786
787         /*
788          * Call LsaOpenPolicy and LsaQueryInfo
789          */
790          
791         if (!(mem_ctx = talloc_init())) {
792                 DEBUG(0, ("talloc_init() failed\n"));
793                 cli_shutdown(cli);
794                 return -1;
795         }
796
797         if (!cli_nt_session_open(cli, PIPE_LSARPC)) {
798                 DEBUG(0, ("Could not initialise lsa pipe\n"));
799         }
800
801         nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
802                                         &connect_hnd);
803         if (NT_STATUS_IS_ERR(nt_status)) {
804                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
805                         get_nt_error_msg(nt_status)));
806                 return -1;
807         }
808
809         /* Querying info level 5 */
810         
811         nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
812                                         5 /* info level */, domain_name, &domain_sid);
813         if (NT_STATUS_IS_ERR(nt_status)) {
814                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
815                         get_nt_error_msg(nt_status)));
816                 return -1;
817         }
818
819
820         /* There should be actually query info level 3 (following nt serv behaviour),
821            but I still don't know if it's _really_ necessary */
822                         
823         /*
824          * Close the pipes and clean up
825          */
826          
827         nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
828         if (NT_STATUS_IS_ERR(nt_status)) {
829                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
830                         get_nt_error_msg(nt_status)));
831                 return -1;
832         }
833
834         if (cli->nt_pipe_fnum)
835                 cli_nt_session_close(cli);
836
837         talloc_destroy(mem_ctx);
838          
839          
840         /*
841          * Store the password in secrets db
842          */
843
844         if (!secrets_store_trusted_domain_password(domain_name, opt_password,
845                                                    domain_sid)) {
846                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
847                 return -1;
848         }
849         
850         DEBUG(0, ("Success!\n"));
851         return 0;
852 }
853
854 /**
855  * Revoke trust relationship to the remote domain
856  *
857  * @param argc standard argc
858  * @param argv standard argv without initial components
859  *
860  * @return Integer status (0 means success)
861  **/
862
863 static int rpc_trustdom_revoke(int argc, const char **argv) {
864
865         char* domain_name;
866
867         if (argc < 1) return -1;
868         
869         /* generate upper cased domain name */
870         domain_name = smb_xstrdup(argv[0]);
871         strupper(domain_name);
872
873         /* delete password of the trust */
874         if (!trusted_domain_password_delete(domain_name)) {
875                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
876                           domain_name));
877                 return -1;
878         };
879         
880         return 0;
881 }
882
883 /**
884  * Usage for 'net rpc trustdom' command
885  *
886  * @param argc standard argc
887  * @param argv standard argv without inital components
888  *
889  * @return Integer status returned to shell
890  **/
891  
892 static int rpc_trustdom_usage(int argc, const char **argv) {
893         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
894         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
895         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
896         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
897         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
898         return -1;
899 }
900
901
902 /**
903  * Entrypoint for 'net rpc trustdom' code
904  *
905  * @param argc standard argc
906  * @param argv standard argv without initial components
907  *
908  * @return Integer status (0 means success)
909  */
910
911 static int rpc_trustdom(int argc, const char **argv)
912 {
913         struct functable func[] = {
914                 {"add", rpc_trustdom_add},
915                 {"del", rpc_trustdom_del},
916                 {"establish", rpc_trustdom_establish},
917                 {"revoke", rpc_trustdom_revoke},
918                 {"help", rpc_trustdom_usage},
919                 {NULL, NULL}
920         };
921
922         if (argc == 0) {
923                 rpc_trustdom_usage(argc, argv);
924                 return -1;
925         }
926
927         return (net_run_function(argc, argv, func, rpc_user_usage));
928 }
929
930 /****************************************************************************/
931
932
933 /** 
934  * Basic usage function for 'net rpc'
935  * @param argc  Standard main() style argc
936  * @param argv  Standard main() style argv.  Initial components are already
937  *              stripped
938  **/
939
940 int net_rpc_usage(int argc, const char **argv) 
941 {
942         d_printf("  net rpc join \t\t\tto join a domain \n");
943         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
944         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
945         d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
946         d_printf("  net rpc abortshutdown \tto to abort the shutdown of a remote server\n");
947         d_printf("  net rpc shutdown \t\tto to shutdown a remote server\n");
948         d_printf("\n");
949         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
950         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
951         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
952         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
953         d_printf("\t-c or --comment=<message>\ttext message to display on impending shutdown\n");
954         return -1;
955 }
956
957
958 /**
959  * Help function for 'net rpc'.  Calls command specific help if requested
960  * or displays usage of net rpc
961  * @param argc  Standard main() style argc
962  * @param argv  Standard main() style argv.  Initial components are already
963  *              stripped
964  **/
965
966 int rpc_help(int argc, const char **argv)
967 {
968         struct functable func[] = {
969                 {"join", rpc_join_usage},
970                 {"user", rpc_user_usage},
971                 //{"changetrustpw", rpc_changetrustpw_usage},
972                 {"trustdom", rpc_trustdom_usage},
973                 //{"abortshutdown", rpc_shutdown_abort_usage},
974                 //{"shutdown", rpc_shutdown_usage},
975                 {NULL, NULL}
976         };
977
978         if (argc == 0) {
979                 net_rpc_usage(argc, argv);
980                 return -1;
981         }
982
983         return (net_run_function(argc, argv, func, rpc_user_usage));
984 }
985
986
987 /** 
988  * 'net rpc' entrypoint.
989  * @param argc  Standard main() style argc
990  * @param argv  Standard main() style argv.  Initial components are already
991  *              stripped
992  **/
993
994 int net_rpc(int argc, const char **argv)
995 {
996         struct functable func[] = {
997                 {"join", rpc_join},
998                 {"user", rpc_user},
999                 {"changetrustpw", rpc_changetrustpw},
1000                 {"trustdom", rpc_trustdom},
1001                 {"abortshutdown", rpc_shutdown_abort},
1002                 {"shutdown", rpc_shutdown},
1003                 {"help", rpc_help},
1004                 {NULL, NULL}
1005         };
1006         return net_run_function(argc, argv, func, net_rpc_usage);
1007 }