Lots more net consistency work:
[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 extern pstring global_myname;
24
25 /**
26  * @file net_rpc.c
27  *
28  * @brief RPC based subcommands for the 'net' utility.
29  *
30  * This file should contain much of the functionality that used to
31  * be found in rpcclient, execpt that the commands should change 
32  * less often, and the fucntionality should be sane (the user is not 
33  * expected to know a rid/sid before they conduct an operation etc.)
34  *
35  * @todo Perhaps eventually these should be split out into a number
36  * of files, as this could get quite big.
37  **/
38
39
40 /* A function of this type is passed to the 'run_rpc_command' wrapper */
41 typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, struct cli_state *, TALLOC_CTX *, int, const char **);
42
43 /**
44  * Many of the RPC functions need the domain sid.  This function gets
45  *  it at the start of every run 
46  *
47  * @param cli A cli_state already connected to the remote machine
48  *
49  * @return The Domain SID of the remote machine.
50  **/
51
52 static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
53 {
54         DOM_SID *domain_sid;
55         POLICY_HND pol;
56         NTSTATUS result = NT_STATUS_OK;
57         uint32 info_class = 5;
58         fstring domain_name;
59         TALLOC_CTX *mem_ctx;
60         
61         if (!(domain_sid = malloc(sizeof(DOM_SID)))){
62                 DEBUG(0,("fetch_domain_sid: malloc returned NULL!\n"));
63                 goto error;
64         }
65             
66         if (!(mem_ctx=talloc_init()))
67         {
68                 DEBUG(0,("fetch_domain_sid: talloc_init returned NULL!\n"));
69                 goto error;
70         }
71
72
73         if (!cli_nt_session_open (cli, PIPE_LSARPC)) {
74                 fprintf(stderr, "could not initialise lsa pipe\n");
75                 goto error;
76         }
77         
78         result = cli_lsa_open_policy(cli, mem_ctx, True, 
79                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
80                                      &pol);
81         if (!NT_STATUS_IS_OK(result)) {
82                 goto error;
83         }
84
85         result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, 
86                                            domain_name, domain_sid);
87         if (!NT_STATUS_IS_OK(result)) {
88                 goto error;
89         }
90
91         cli_lsa_close(cli, mem_ctx, &pol);
92         cli_nt_session_close(cli);
93         talloc_destroy(mem_ctx);
94
95         return domain_sid;
96
97  error:
98         fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
99
100         if (!NT_STATUS_IS_OK(result)) {
101                 fprintf(stderr, "error: %s\n", nt_errstr(result));
102         }
103
104         exit(1);
105 }
106
107 /**
108  * Run a single RPC command, from start to finish.
109  *
110  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
111  * @param conn_flag a NET_FLAG_ combination.  Passed to 
112  *                   net_make_ipc_connection.
113  * @param argc  Standard main() style argc
114  * @param argc  Standard main() style argv.  Initial components are already
115  *              stripped
116  * @return A shell status integer (0 for success)
117  */
118
119 static int run_rpc_command(const char *pipe_name, int conn_flags,
120                            rpc_command_fn fn,
121                            int argc, const char **argv) 
122 {
123         struct cli_state *cli = net_make_ipc_connection(conn_flags);
124         TALLOC_CTX *mem_ctx;
125         NTSTATUS nt_status;
126         DOM_SID *domain_sid;
127
128         if (!cli) {
129                 return -1;
130         }
131
132         domain_sid = net_get_remote_domain_sid(cli);
133
134         /* Create mem_ctx */
135         
136         if (!(mem_ctx = talloc_init())) {
137                 DEBUG(0, ("talloc_init() failed\n"));
138                 cli_shutdown(cli);
139                 return -1;
140         }
141         
142         if (!cli_nt_session_open(cli, pipe_name)) {
143                 DEBUG(0, ("Could not initialise samr pipe\n"));
144         }
145         
146         nt_status = fn(domain_sid, cli, mem_ctx, argc, argv);
147         
148         if (!NT_STATUS_IS_OK(nt_status)) {
149                 DEBUG(0, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
150         } else {
151                 DEBUG(5, ("rpc command function succedded\n"));
152         }
153                 
154             
155         if (cli->nt_pipe_fnum)
156                 cli_nt_session_close(cli);
157         
158         talloc_destroy(mem_ctx);
159
160         return (!NT_STATUS_IS_OK(nt_status));
161 }
162
163
164 /****************************************************************************/
165
166
167 /** 
168  * Force a change of the trust acccount password.
169  *
170  * All paramaters are provided by the run_rpc_command funcion, except for
171  * argc, argv which are passes through. 
172  *
173  * @param domain_sid The domain sid aquired from the remote server
174  * @param cli A cli_state connected to the server.
175  * @param mem_ctx Talloc context, destoyed on compleation of the function.
176  * @param argc  Standard main() style argc
177  * @param argc  Standard main() style argv.  Initial components are already
178  *              stripped
179  *
180  * @return Normal NTSTATUS return.
181  **/
182
183 static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
184                                        int argc, const char **argv) {
185         
186         return trust_pw_find_change_and_store_it(cli, mem_ctx, opt_target_workgroup);
187 }
188
189 /** 
190  * Force a change of the trust acccount password.
191  *
192  * @param argc  Standard main() style argc
193  * @param argc  Standard main() style argv.  Initial components are already
194  *              stripped
195  *
196  * @return A shell status integer (0 for success)
197  **/
198
199 static int rpc_changetrustpw(int argc, const char **argv) 
200 {
201         return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_changetrustpw_internals,
202                                argc, argv);
203 }
204
205
206 /****************************************************************************/
207
208
209 /** 
210  * Join a domain, the old way.
211  *
212  * This uses 'machinename' as the inital password, and changes it. 
213  *
214  * The password should be created with 'server manager' or eqiv first.
215  *
216  * All paramaters are provided by the run_rpc_command funcion, except for
217  * argc, argv which are passes through. 
218  *
219  * @param domain_sid The domain sid aquired from the remote server
220  * @param cli A cli_state connected to the server.
221  * @param mem_ctx Talloc context, destoyed on compleation of the function.
222  * @param argc  Standard main() style argc
223  * @param argc  Standard main() style argv.  Initial components are already
224  *              stripped
225  *
226  * @return Normal NTSTATUS return.
227  **/
228
229 static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
230                                        int argc, const char **argv) {
231         
232         extern pstring global_myname;
233         fstring trust_passwd;
234         unsigned char orig_trust_passwd_hash[16];
235
236         fstrcpy(trust_passwd, global_myname);
237         strlower(trust_passwd);
238         E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash);
239
240         return trust_pw_change_and_store_it(cli, mem_ctx, orig_trust_passwd_hash);
241 }
242
243 /** 
244  * Join a domain, the old way.
245  *
246  * @param argc  Standard main() style argc
247  * @param argc  Standard main() style argv.  Initial components are already
248  *              stripped
249  *
250  * @return A shell status integer (0 for success)
251  **/
252
253 static int net_rpc_join_oldstyle(int argc, const char **argv) 
254 {
255         return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_join_oldstyle_internals,
256                                argc, argv);
257 }
258
259 /** 
260  * Basic usage function for 'net rpc join'
261  * @param argc  Standard main() style argc
262  * @param argc  Standard main() style argv.  Initial components are already
263  *              stripped
264  **/
265
266 static int rpc_join_usage(int argc, const char **argv) 
267 {       
268         d_printf("net rpc join -U <username>[%%password] [options]\n"\
269                  "\t to join a domain with admin username & password\n"\
270                  "\t\t password will be prompted if none is specified\n");
271         d_printf("net rpc join [options except -U]\n"\
272                  "\t to join a domain created in server manager\n\n\n");
273
274         net_common_flags_usage(argc, argv);
275         return -1;
276 }
277
278 /** 
279  * 'net rpc join' entrypoint.
280  * @param argc  Standard main() style argc
281  * @param argc  Standard main() style argv.  Initial components are already
282  *              stripped
283  *
284  * Main 'net_rpc_join()' (where the admain username/password is used) is 
285  * in net_rpc_join.c
286  * Assume if a -U is specified, it's the new style, otherwise it's the
287  * old style
288  **/
289
290 int net_rpc_join(int argc, const char **argv) 
291 {
292         if ((net_rpc_join_oldstyle(argc, argv) == 0))
293                 return 0;
294         
295         return net_rpc_join_newstyle(argc, argv);
296 }
297
298
299 /****************************************************************************/
300
301 /**
302  * Basic usage function for 'net rpc user'
303  * @param argc  Standard main() style argc.
304  * @param argv  Standard main() style argv.  Initial components are already
305  *              stripped.
306  **/
307
308 static int rpc_user_usage(int argc, const char **argv)
309 {
310         return net_help_user(argc, argv);
311 }
312
313 /** 
314  * Add a new user to a remote RPC server
315  *
316  * All paramaters are provided by the run_rpc_command funcion, except for
317  * argc, argv which are passes through. 
318  *
319  * @param domain_sid The domain sid acquired from the remote server
320  * @param cli A cli_state connected to the server.
321  * @param mem_ctx Talloc context, destoyed on completion of the function.
322  * @param argc  Standard main() style argc
323  * @param argv  Standard main() style argv.  Initial components are already
324  *              stripped
325  *
326  * @return Normal NTSTATUS return.
327  **/
328
329 static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
330                                        int argc, const char **argv) {
331         
332         POLICY_HND connect_pol, domain_pol, user_pol;
333         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
334         const char *acct_name;
335         uint16 acb_info;
336         uint32 unknown, user_rid;
337
338         if (argc != 1) {
339                 d_printf("User must be specified\n");
340                 rpc_user_usage(argc, argv);
341                 return NT_STATUS_OK;
342         }
343
344         acct_name = argv[0];
345
346         /* Get sam policy handle */
347         
348         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
349                                   &connect_pol);
350         if (!NT_STATUS_IS_OK(result)) {
351                 goto done;
352         }
353         
354         /* Get domain policy handle */
355         
356         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
357                                       MAXIMUM_ALLOWED_ACCESS,
358                                       domain_sid, &domain_pol);
359         if (!NT_STATUS_IS_OK(result)) {
360                 goto done;
361         }
362
363         /* Create domain user */
364
365         acb_info = ACB_NORMAL;
366         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
367
368         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
369                                           acct_name, acb_info, unknown,
370                                           &user_pol, &user_rid);
371         if (!NT_STATUS_IS_OK(result)) {
372                 goto done;
373         }
374
375  done:
376         if (!NT_STATUS_IS_OK(result)) {
377                 d_printf("Failed to add user %s - %s\n", acct_name, 
378                          nt_errstr(result));
379         } else {
380                 d_printf("Added user %s\n", acct_name);
381         }
382         return result;
383 }
384
385 /** 
386  * Add a new user to a remote RPC server
387  *
388  * @param argc  Standard main() style argc
389  * @param argv  Standard main() style argv.  Initial components are already
390  *              stripped
391  *
392  * @return A shell status integer (0 for success)
393  **/
394
395 static int rpc_user_add(int argc, const char **argv) 
396 {
397         return run_rpc_command(PIPE_SAMR, 0, rpc_user_add_internals,
398                                argc, argv);
399 }
400
401 /** 
402  * Delete a user from a remote RPC server
403  *
404  * All paramaters are provided by the run_rpc_command funcion, except for
405  * argc, argv which are passes through. 
406  *
407  * @param domain_sid The domain sid acquired from the remote server
408  * @param cli A cli_state connected to the server.
409  * @param mem_ctx Talloc context, destoyed on completion of the function.
410  * @param argc  Standard main() style argc
411  * @param argv  Standard main() style argv.  Initial components are already
412  *              stripped
413  *
414  * @return Normal NTSTATUS return.
415  **/
416
417 static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, 
418                                        struct cli_state *cli, 
419                                        TALLOC_CTX *mem_ctx, 
420                                        int argc, const char **argv)
421 {
422         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
423         POLICY_HND connect_pol, domain_pol, user_pol;
424
425         if (argc < 1) {
426                 d_printf("User must be specified\n");
427                 rpc_user_usage(argc, argv);
428                 return NT_STATUS_OK;
429         }
430         /* Get sam policy and domain handles */
431
432         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
433                                   &connect_pol);
434
435         if (!NT_STATUS_IS_OK(result)) {
436                 goto done;
437         }
438
439         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
440                                       MAXIMUM_ALLOWED_ACCESS,
441                                       domain_sid, &domain_pol);
442
443         if (!NT_STATUS_IS_OK(result)) {
444                 goto done;
445         }
446
447         /* Get handle on user */
448
449         {
450                 uint32 *user_rids, num_rids, *name_types;
451                 uint32 flags = 0x000003e8; /* Unknown */
452
453                 result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
454                                                flags, 1, (char **) &argv[0],
455                                                &num_rids, &user_rids,
456                                                &name_types);
457
458                 if (!NT_STATUS_IS_OK(result)) {
459                         goto done;
460                 }
461
462                 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
463                                             MAXIMUM_ALLOWED_ACCESS,
464                                             user_rids[0], &user_pol);
465
466                 if (!NT_STATUS_IS_OK(result)) {
467                         goto done;
468                 }
469         }
470
471         /* Delete user */
472
473         result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
474
475         if (!NT_STATUS_IS_OK(result)) {
476                 goto done;
477         }
478
479         /* Display results */
480
481  done:
482         return result;
483
484 }       
485
486 /** 
487  * Delete a user from a remote RPC server
488  *
489  * @param argc  Standard main() style argc
490  * @param argv  Standard main() style argv.  Initial components are already
491  *              stripped
492  *
493  * @return A shell status integer (0 for success)
494  **/
495
496 static int rpc_user_delete(int argc, const char **argv) 
497 {
498         return run_rpc_command(PIPE_SAMR, 0, rpc_user_del_internals,
499                                argc, argv);
500 }
501
502 /** 
503  * List user's groups on a remote RPC server
504  *
505  * All paramaters are provided by the run_rpc_command funcion, except for
506  * argc, argv which are passes through. 
507  *
508  * @param domain_sid The domain sid acquired from the remote server
509  * @param cli A cli_state connected to the server.
510  * @param mem_ctx Talloc context, destoyed on completion of the function.
511  * @param argc  Standard main() style argc
512  * @param argv  Standard main() style argv.  Initial components are already
513  *              stripped
514  *
515  * @return Normal NTSTATUS return.
516  **/
517
518 static NTSTATUS 
519 rpc_user_info_internals(const DOM_SID *domain_sid, struct cli_state *cli,
520                         TALLOC_CTX *mem_ctx, int argc, const char **argv)
521 {
522         POLICY_HND connect_pol, domain_pol, user_pol;
523         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
524         uint32 *rids, num_rids, *name_types, num_names;
525         uint32 flags = 0x000003e8; /* Unknown */
526         int i;
527         char **names;
528         DOM_GID *user_gids;
529
530         if (argc < 1) {
531                 d_printf("User must be specified\n");
532                 rpc_user_usage(argc, argv);
533                 return NT_STATUS_OK;
534         }
535         /* Get sam policy handle */
536         
537         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
538                                   &connect_pol);
539         if (!NT_STATUS_IS_OK(result)) goto done;
540         
541         /* Get domain policy handle */
542         
543         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
544                                       MAXIMUM_ALLOWED_ACCESS,
545                                       domain_sid, &domain_pol);
546         if (!NT_STATUS_IS_OK(result)) goto done;
547
548         /* Get handle on user */
549
550         result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
551                                        flags, 1, (char **) &argv[0],
552                                        &num_rids, &rids, &name_types);
553
554         if (!NT_STATUS_IS_OK(result)) goto done;
555
556         result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
557                                     MAXIMUM_ALLOWED_ACCESS,
558                                     rids[0], &user_pol);
559         if (!NT_STATUS_IS_OK(result)) goto done;
560
561         result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
562                                            &num_rids, &user_gids);
563
564         /* Look up rids */
565
566         rids = (uint32 *)talloc(mem_ctx, sizeof(uint32) * num_rids);
567
568         for (i = 0; i < num_rids; i++)
569                 rids[i] = user_gids[i].g_rid;
570
571         result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
572                                       flags, num_rids, rids,
573                                       &num_names, &names, &name_types);
574
575         if (!NT_STATUS_IS_OK(result)) {
576                 goto done;
577         }
578
579         /* Display results */
580
581         for (i = 0; i < num_names; i++)
582                 printf("%s\n", names[i]);
583
584  done:
585         return result;
586 }
587
588 /** 
589  * List a user's groups from a remote RPC server
590  *
591  * @param argc  Standard main() style argc
592  * @param argv  Standard main() style argv.  Initial components are already
593  *              stripped
594  *
595  * @return A shell status integer (0 for success)
596  **/
597
598 static int rpc_user_info(int argc, const char **argv) 
599 {
600         return run_rpc_command(PIPE_SAMR, 0, rpc_user_info_internals,
601                                argc, argv);
602 }
603
604 /** 
605  * List users on a remote RPC server
606  *
607  * All paramaters are provided by the run_rpc_command funcion, except for
608  * argc, argv which are passes through. 
609  *
610  * @param domain_sid The domain sid acquired from the remote server
611  * @param cli A cli_state connected to the server.
612  * @param mem_ctx Talloc context, destoyed on completion of the function.
613  * @param argc  Standard main() style argc
614  * @param argv  Standard main() style argv.  Initial components are already
615  *              stripped
616  *
617  * @return Normal NTSTATUS return.
618  **/
619
620 static NTSTATUS 
621 rpc_user_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
622                         TALLOC_CTX *mem_ctx, int argc, const char **argv)
623 {
624         POLICY_HND connect_pol, domain_pol;
625         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
626         uint32 start_idx=0, max_entries=250, num_entries, i;
627         SAM_DISPINFO_CTR ctr;
628         SAM_DISPINFO_1 info1;
629
630         /* Get sam policy handle */
631         
632         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
633                                   &connect_pol);
634         if (!NT_STATUS_IS_OK(result)) {
635                 goto done;
636         }
637         
638         /* Get domain policy handle */
639         
640         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
641                                       MAXIMUM_ALLOWED_ACCESS,
642                                       domain_sid, &domain_pol);
643         if (!NT_STATUS_IS_OK(result)) {
644                 goto done;
645         }
646
647         /* Query domain users */
648         ZERO_STRUCT(ctr);
649         ZERO_STRUCT(info1);
650         ctr.sam.info1 = &info1;
651         if (opt_long_list_entries)
652                 d_printf("\nUser name             Comment"\
653                          "\n-----------------------------\n");
654         do {
655                 fstring user, desc;
656                 result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
657                                                  &start_idx, 1, &num_entries,
658                                                  max_entries, &ctr);
659                 for (i = 0; i < num_entries; i++) {
660                         unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user)-1);
661                         if (opt_long_list_entries) 
662                                 unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1);
663                         
664                         if (opt_long_list_entries)
665                                 printf("%-21.21s %-50.50s\n", user, desc);
666                         else
667                                 printf("%-21.21s\n", user);
668                 }
669         } while (!NT_STATUS_IS_OK(result));
670
671  done:
672         return result;
673 }
674
675 /** 
676  * 'net rpc user' entrypoint.
677  * @param argc  Standard main() style argc
678  * @param argc  Standard main() style argv.  Initial components are already
679  *              stripped
680  **/
681
682 int net_rpc_user(int argc, const char **argv) 
683 {
684         struct functable func[] = {
685                 {"add", rpc_user_add},
686                 {"info", rpc_user_info},
687                 {"delete", rpc_user_delete},
688                 {NULL, NULL}
689         };
690         
691         if (argc == 0) {
692                 if (opt_long_list_entries) {
693                 } else {
694                 }
695                         return run_rpc_command(PIPE_SAMR, 0, 
696                                                rpc_user_list_internals,
697                                                argc, argv);
698         }
699
700         return net_run_function(argc, argv, func, rpc_user_usage);
701 }
702
703
704 /****************************************************************************/
705
706
707
708 /** 
709  * ABORT the shutdown of a remote RPC Server
710  *
711  * All paramaters are provided by the run_rpc_command funcion, except for
712  * argc, argv which are passed through. 
713  *
714  * @param domain_sid The domain sid aquired from the remote server
715  * @param cli A cli_state connected to the server.
716  * @param mem_ctx Talloc context, destoyed on compleation of the function.
717  * @param argc  Standard main() style argc
718  * @param argc  Standard main() style argv.  Initial components are already
719  *              stripped
720  *
721  * @return Normal NTSTATUS return.
722  **/
723
724 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
725                                              int argc, const char **argv) 
726 {
727         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
728         
729         result = cli_reg_abort_shutdown(cli, mem_ctx);
730         
731         if (NT_STATUS_IS_OK(result))
732                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
733         else
734                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
735         
736         return result;
737 }
738
739
740 /** 
741  * ABORT the Shut down of a remote RPC server
742  *
743  * @param argc  Standard main() style argc
744  * @param argc  Standard main() style argv.  Initial components are already
745  *              stripped
746  *
747  * @return A shell status integer (0 for success)
748  **/
749
750 static int rpc_shutdown_abort(int argc, const char **argv) 
751 {
752         return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_abort_internals,
753                                argc, argv);
754 }
755
756 /** 
757  * Shut down a remote RPC Server
758  *
759  * All paramaters are provided by the run_rpc_command funcion, except for
760  * argc, argv which are passes through. 
761  *
762  * @param domain_sid The domain sid aquired from the remote server
763  * @param cli A cli_state connected to the server.
764  * @param mem_ctx Talloc context, destoyed on compleation of the function.
765  * @param argc  Standard main() style argc
766  * @param argc  Standard main() style argv.  Initial components are already
767  *              stripped
768  *
769  * @return Normal NTSTATUS return.
770  **/
771
772 static NTSTATUS rpc_shutdown_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
773                                        int argc, const char **argv) 
774 {
775         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
776         char *msg = "This machine will be shutdown shortly";
777         uint32 timeout = 20;
778         uint16 flgs = 0;
779         BOOL reboot = opt_reboot;
780         BOOL force = opt_force;
781 #if 0
782         poptContext pc;
783         int rc;
784
785         struct poptOption long_options[] = {
786                 {"message",    'm', POPT_ARG_STRING, &msg},
787                 {"timeout",    't', POPT_ARG_INT,    &timeout},
788                 {"reboot",     'r', POPT_ARG_NONE,   &reboot},
789                 {"force",      'f', POPT_ARG_NONE,   &force},
790                 { 0, 0, 0, 0}
791         };
792
793         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
794                             POPT_CONTEXT_KEEP_FIRST);
795
796         rc = poptGetNextOpt(pc);
797         
798         if (rc < -1) {
799                 /* an error occurred during option processing */
800                 DEBUG(0, ("%s: %s\n",
801                           poptBadOption(pc, POPT_BADOPTION_NOALIAS),
802                           poptStrerror(rc)));
803                 return NT_STATUS_INVALID_PARAMETER;
804         }
805 #endif
806         if (reboot) {
807                 flgs |= REG_REBOOT_ON_SHUTDOWN;
808         }
809         if (force) {
810                 flgs |= REG_FORCE_SHUTDOWN;
811         }
812         if (opt_comment) {
813                 msg = opt_comment;
814         }
815         if (opt_timeout) {
816                 timeout = opt_timeout;
817         }
818
819         /* create an entry */
820         result = cli_reg_shutdown(cli, mem_ctx, msg, timeout, flgs);
821
822         if (NT_STATUS_IS_OK(result))
823                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
824         else
825                 DEBUG(0,("Shutdown of remote machine failed!\n"));
826
827         return result;
828 }
829
830 /** 
831  * Shut down a remote RPC server
832  *
833  * @param argc  Standard main() style argc
834  * @param argc  Standard main() style argv.  Initial components are already
835  *              stripped
836  *
837  * @return A shell status integer (0 for success)
838  **/
839
840 static int rpc_shutdown(int argc, const char **argv) 
841 {
842         return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_internals,
843                                        argc, argv);
844 }
845
846 /***************************************************************************
847   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
848   
849  ***************************************************************************/
850
851 /**
852  * Add interdomain trust account to the RPC server.
853  * All parameters (except for argc and argv) are passed by run_rpc_command
854  * function.
855  *
856  * @param domain_sid The domain sid acquired from the server
857  * @param cli A cli_state connected to the server.
858  * @param mem_ctx Talloc context, destoyed on completion of the function.
859  * @param argc  Standard main() style argc
860  * @param argc  Standard main() style argv.  Initial components are already
861  *              stripped
862  *
863  * @return normal NTSTATUS return code
864  */
865
866 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
867                                        int argc, const char **argv) {
868
869         POLICY_HND connect_pol, domain_pol, user_pol;
870         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
871         char *acct_name;
872         uint16 acb_info;
873         uint32 unknown, user_rid;
874
875         if (argc != 1) {
876                 d_printf("Usage: net rpc trustdom add <domain_name>\n");
877                 return NT_STATUS_OK;
878         }
879
880         /* 
881          * Make valid trusting domain account (ie. uppercased and with '$' appended)
882          */
883          
884         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
885                 return NT_STATUS_NO_MEMORY;
886         }
887
888         strupper(acct_name);
889
890         /* Get sam policy handle */
891         
892         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
893                                   &connect_pol);
894         if (!NT_STATUS_IS_OK(result)) {
895                 goto done;
896         }
897         
898         /* Get domain policy handle */
899         
900         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
901                                       MAXIMUM_ALLOWED_ACCESS,
902                                       domain_sid, &domain_pol);
903         if (!NT_STATUS_IS_OK(result)) {
904                 goto done;
905         }
906
907         /* Create trusting domain's account */
908
909         acb_info = ACB_DOMTRUST;
910         unknown = 0xe005000b; /* No idea what this is - a permission mask? 
911                                  Is it needed for interdomain account also ? */
912
913         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
914                                           acct_name, acb_info, unknown,
915                                           &user_pol, &user_rid);
916         if (!NT_STATUS_IS_OK(result)) {
917                 goto done;
918         }
919
920  done:
921         SAFE_FREE(acct_name);
922         return result;
923 }
924
925 /**
926  * Create interdomain trust account for a remote domain.
927  *
928  * @param argc standard argc
929  * @param argv standard argv without initial components
930  *
931  * @return Integer status (0 means success)
932  **/
933
934 static int rpc_trustdom_add(int argc, const char **argv)
935 {
936         return run_rpc_command(PIPE_SAMR, 0, rpc_trustdom_add_internals,
937                                argc, argv);
938 }
939
940
941 /**
942  * Delete interdomain trust account for a remote domain.
943  *
944  * @param argc standard argc
945  * @param argv standard argv without initial components
946  *
947  * @return Integer status (0 means success)
948  **/
949  
950 static int rpc_trustdom_del(int argc, const char **argv)
951 {
952         d_printf("Sorry, not yet implemented.\n");
953         return -1;
954 }
955
956  
957 /**
958  * Establish trust relationship to a trusting domain.
959  * Interdomain account must already be created on remote PDC.
960  *
961  * @param argc standard argc
962  * @param argv standard argv without initial components
963  *
964  * @return Integer status (0 means success)
965  **/
966
967 extern char *opt_user_name;
968 extern char *opt_password;
969
970 static int rpc_trustdom_establish(int argc, const char **argv) {
971
972         struct cli_state *cli;
973         struct in_addr server_ip;
974         POLICY_HND connect_hnd;
975         TALLOC_CTX *mem_ctx;
976         NTSTATUS nt_status;
977         DOM_SID domain_sid;
978         WKS_INFO_100 wks_info;
979         
980         char* domain_name;
981         char* acct_name;
982         fstring pdc_name;
983
984         /*
985          * Connect to \\server\ipc$ as 'our domain' account with password
986          */
987
988         domain_name = smb_xstrdup(argv[0]);
989         strupper(domain_name);
990         
991         asprintf(&acct_name, "%s$", lp_workgroup());
992         strupper(acct_name);
993         
994         opt_user_name = (char*)malloc(strlen(acct_name) + 1);
995         safe_strcpy(opt_user_name, acct_name, strlen(acct_name) + 1);
996
997         /* find the domain controller */
998         if (!net_find_dc(&server_ip, pdc_name, domain_name)) {
999                 DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name));
1000                 return -1;
1001         }
1002
1003         /* connect to ipc$ as username/password */
1004         nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
1005         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
1006
1007                 /* Is it trusting domain account for sure ? */
1008                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
1009                         nt_errstr(nt_status)));
1010                 return -1;
1011         }
1012         
1013         /*
1014          * Connect to \\server\ipc$ again (this time anonymously)
1015          */
1016         
1017         nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
1018         
1019         if (NT_STATUS_IS_ERR(nt_status)) {
1020                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
1021                         domain_name, nt_errstr(nt_status)));
1022         }
1023
1024         /*
1025          * Use NetServerEnum2 to make sure we're talking to a proper server
1026          */
1027          
1028         if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
1029                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
1030                          for domain %s\n", domain_name));
1031         }
1032          
1033         /*
1034          * Call WksQueryInfo to check remote server's capabilities
1035          * FIXME:Is really necessary ? nt serv does this, but from samba's
1036          *       point of view it doesn't seem to make the difference
1037          * IDEA: It may be used to get info about type of pdc we're talking to
1038          *       (e.g. WinNT or Win2k)
1039          */
1040         
1041         if (!cli_nt_session_open(cli, PIPE_WKSSVC)) {
1042                 DEBUG(0, ("Couldn't not initialise wkssvc pipe\n"));
1043                 return -1;
1044         }
1045
1046         /* TODO: convert this call from rpc_client/cli_wkssvc.c
1047            to cli_wks_query_info() in libsmb/cli_wkssvc.c
1048            UPDATE: already done :)
1049         */
1050
1051         if (!(mem_ctx = talloc_init())) {
1052                 DEBUG(0, ("talloc_init() failed\n"));
1053                 cli_shutdown(cli);
1054                 return -1;
1055         }
1056         
1057         nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info);
1058         
1059         if (NT_STATUS_IS_ERR(nt_status)) {
1060                 DEBUG(0, ("WksQueryInfo call failed.\n"));
1061                 return -1;
1062         }
1063
1064         if (cli->nt_pipe_fnum) {
1065                 cli_nt_session_close(cli);
1066                 talloc_destroy(mem_ctx);
1067         }
1068
1069
1070         /*
1071          * Call LsaOpenPolicy and LsaQueryInfo
1072          */
1073          
1074         if (!(mem_ctx = talloc_init())) {
1075                 DEBUG(0, ("talloc_init() failed\n"));
1076                 cli_shutdown(cli);
1077                 return -1;
1078         }
1079
1080         if (!cli_nt_session_open(cli, PIPE_LSARPC)) {
1081                 DEBUG(0, ("Could not initialise lsa pipe\n"));
1082         }
1083
1084         nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
1085                                         &connect_hnd);
1086         if (NT_STATUS_IS_ERR(nt_status)) {
1087                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
1088                         nt_errstr(nt_status)));
1089                 return -1;
1090         }
1091
1092         /* Querying info level 5 */
1093         
1094         nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
1095                                         5 /* info level */, domain_name, &domain_sid);
1096         if (NT_STATUS_IS_ERR(nt_status)) {
1097                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
1098                         nt_errstr(nt_status)));
1099                 return -1;
1100         }
1101
1102
1103         /* There should be actually query info level 3 (following nt serv behaviour),
1104            but I still don't know if it's _really_ necessary */
1105                         
1106         /*
1107          * Close the pipes and clean up
1108          */
1109          
1110         nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
1111         if (NT_STATUS_IS_ERR(nt_status)) {
1112                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
1113                         nt_errstr(nt_status)));
1114                 return -1;
1115         }
1116
1117         if (cli->nt_pipe_fnum)
1118                 cli_nt_session_close(cli);
1119
1120         talloc_destroy(mem_ctx);
1121          
1122          
1123         /*
1124          * Store the password in secrets db
1125          */
1126
1127         if (!secrets_store_trusted_domain_password(domain_name, opt_password,
1128                                                    domain_sid)) {
1129                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
1130                 return -1;
1131         }
1132         
1133         DEBUG(0, ("Success!\n"));
1134         return 0;
1135 }
1136
1137 /**
1138  * Revoke trust relationship to the remote domain
1139  *
1140  * @param argc standard argc
1141  * @param argv standard argv without initial components
1142  *
1143  * @return Integer status (0 means success)
1144  **/
1145
1146 static int rpc_trustdom_revoke(int argc, const char **argv) {
1147
1148         char* domain_name;
1149
1150         if (argc < 1) return -1;
1151         
1152         /* generate upper cased domain name */
1153         domain_name = smb_xstrdup(argv[0]);
1154         strupper(domain_name);
1155
1156         /* delete password of the trust */
1157         if (!trusted_domain_password_delete(domain_name)) {
1158                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
1159                           domain_name));
1160                 return -1;
1161         };
1162         
1163         return 0;
1164 }
1165
1166 /**
1167  * Usage for 'net rpc trustdom' command
1168  *
1169  * @param argc standard argc
1170  * @param argv standard argv without inital components
1171  *
1172  * @return Integer status returned to shell
1173  **/
1174  
1175 static int rpc_trustdom_usage(int argc, const char **argv) {
1176         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
1177         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
1178         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
1179         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
1180         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
1181         return -1;
1182 }
1183
1184
1185 /**
1186  * Entrypoint for 'net rpc trustdom' code
1187  *
1188  * @param argc standard argc
1189  * @param argv standard argv without initial components
1190  *
1191  * @return Integer status (0 means success)
1192  */
1193
1194 static int rpc_trustdom(int argc, const char **argv)
1195 {
1196         struct functable func[] = {
1197                 {"add", rpc_trustdom_add},
1198                 {"del", rpc_trustdom_del},
1199                 {"establish", rpc_trustdom_establish},
1200                 {"revoke", rpc_trustdom_revoke},
1201                 {"help", rpc_trustdom_usage},
1202                 {NULL, NULL}
1203         };
1204
1205         if (argc == 0) {
1206                 rpc_trustdom_usage(argc, argv);
1207                 return -1;
1208         }
1209
1210         return (net_run_function(argc, argv, func, rpc_user_usage));
1211 }
1212
1213 /**
1214  * Check if a server will take rpc commands
1215  * @param flags Type of server to connect to (PDC, DMB, localhost)
1216  *              if the host is not explicitly specified
1217  * @return  BOOL (true means rpc supported)
1218  */
1219 BOOL net_rpc_check(unsigned flags)
1220 {
1221         struct cli_state cli;
1222         BOOL ret = False;
1223         struct in_addr server_ip;
1224         char *server_name = NULL;
1225
1226         /* flags (i.e. server type) may depend on command */
1227         if (!net_find_server(flags, &server_ip, &server_name))
1228                 goto done;
1229
1230         ZERO_STRUCT(cli);
1231         if (cli_initialise(&cli) == False)
1232                 return False;
1233
1234         if (!cli_connect(&cli, server_name, &server_ip))
1235                 goto done;
1236         if (!attempt_netbios_session_request(&cli, global_myname, 
1237                                              server_name, &server_ip))
1238                 goto done;
1239         if (!cli_negprot(&cli))
1240                 goto done;
1241         if (cli.protocol < PROTOCOL_NT1)
1242                 goto done;
1243
1244         ret = True;
1245  done:
1246         cli_shutdown(&cli);
1247         return ret;
1248 }
1249
1250
1251 /****************************************************************************/
1252
1253
1254 /** 
1255  * Basic usage function for 'net rpc'
1256  * @param argc  Standard main() style argc
1257  * @param argv  Standard main() style argv.  Initial components are already
1258  *              stripped
1259  **/
1260
1261 int net_rpc_usage(int argc, const char **argv) 
1262 {
1263         d_printf("  net rpc join \t\t\tto join a domain \n");
1264         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
1265         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
1266         d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
1267         d_printf("  net rpc abortshutdown \tto to abort the shutdown of a remote server\n");
1268         d_printf("  net rpc shutdown \t\tto to shutdown a remote server\n");
1269         d_printf("\n");
1270         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
1271         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
1272         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
1273         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
1274         d_printf("\t-c or --comment=<message>\ttext message to display on impending shutdown\n");
1275         return -1;
1276 }
1277
1278
1279 /**
1280  * Help function for 'net rpc'.  Calls command specific help if requested
1281  * or displays usage of net rpc
1282  * @param argc  Standard main() style argc
1283  * @param argv  Standard main() style argv.  Initial components are already
1284  *              stripped
1285  **/
1286
1287 int net_rpc_help(int argc, const char **argv)
1288 {
1289         struct functable func[] = {
1290                 {"join", rpc_join_usage},
1291                 {"user", net_help_user},
1292                 /*{"changetrustpw", rpc_changetrustpw_usage}, */
1293                 {"trustdom", rpc_trustdom_usage},
1294                 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
1295                 /*{"shutdown", rpc_shutdown_usage}, */
1296                 {NULL, NULL}
1297         };
1298
1299         if (argc == 0) {
1300                 net_rpc_usage(argc, argv);
1301                 return -1;
1302         }
1303
1304         return (net_run_function(argc, argv, func, rpc_user_usage));
1305 }
1306
1307
1308 /** 
1309  * 'net rpc' entrypoint.
1310  * @param argc  Standard main() style argc
1311  * @param argv  Standard main() style argv.  Initial components are already
1312  *              stripped
1313  **/
1314
1315 int net_rpc(int argc, const char **argv)
1316 {
1317         struct functable func[] = {
1318                 {"join", net_rpc_join},
1319                 {"user", net_rpc_user},
1320                 {"changetrustpw", rpc_changetrustpw},
1321                 {"trustdom", rpc_trustdom},
1322                 {"abortshutdown", rpc_shutdown_abort},
1323                 {"shutdown", rpc_shutdown},
1324                 {"help", net_rpc_help},
1325                 {NULL, NULL}
1326         };
1327         return net_run_function(argc, argv, func, net_rpc_usage);
1328 }