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