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