561be2a41e69ad410635706c524b752345322b71
[tprouty/samba.git] / source / utils / net_rpc.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
6    Copyright (C) 2004 Guenther Deschner (gd@samba.org)
7    Copyright (C) 2005 Jeremy Allison (jra@samba.org)
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
22  
23 #include "includes.h"
24 #include "utils/net.h"
25
26 static int net_mode_share;
27
28 /**
29  * @file net_rpc.c
30  *
31  * @brief RPC based subcommands for the 'net' utility.
32  *
33  * This file should contain much of the functionality that used to
34  * be found in rpcclient, execpt that the commands should change 
35  * less often, and the fucntionality should be sane (the user is not 
36  * expected to know a rid/sid before they conduct an operation etc.)
37  *
38  * @todo Perhaps eventually these should be split out into a number
39  * of files, as this could get quite big.
40  **/
41
42
43 /**
44  * Many of the RPC functions need the domain sid.  This function gets
45  *  it at the start of every run 
46  *
47  * @param cli A cli_state already connected to the remote machine
48  *
49  * @return The Domain SID of the remote machine.
50  **/
51
52 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
53                                    DOM_SID **domain_sid, char **domain_name)
54 {
55         struct rpc_pipe_client *lsa_pipe;
56         POLICY_HND pol;
57         NTSTATUS result = NT_STATUS_OK;
58         uint32 info_class = 5;
59         
60         lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
61         if (!lsa_pipe) {
62                 d_fprintf(stderr, "Could not initialise lsa pipe\n");
63                 return result;
64         }
65         
66         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False, 
67                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
68                                      &pol);
69         if (!NT_STATUS_IS_OK(result)) {
70                 d_fprintf(stderr, "open_policy failed: %s\n",
71                           nt_errstr(result));
72                 return result;
73         }
74
75         result = rpccli_lsa_query_info_policy(lsa_pipe, mem_ctx, &pol,
76                                               info_class, domain_name,
77                                               domain_sid);
78         if (!NT_STATUS_IS_OK(result)) {
79                 d_fprintf(stderr, "lsaquery failed: %s\n",
80                           nt_errstr(result));
81                 return result;
82         }
83
84         rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
85         cli_rpc_pipe_close(lsa_pipe);
86
87         return NT_STATUS_OK;
88 }
89
90 /**
91  * Run a single RPC command, from start to finish.
92  *
93  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
94  * @param conn_flag a NET_FLAG_ combination.  Passed to 
95  *                   net_make_ipc_connection.
96  * @param argc  Standard main() style argc
97  * @param argc  Standard main() style argv.  Initial components are already
98  *              stripped
99  * @return A shell status integer (0 for success)
100  */
101
102 int run_rpc_command(struct cli_state *cli_arg,
103                         const int pipe_idx,
104                         int conn_flags,
105                         rpc_command_fn fn,
106                         int argc,
107                         const char **argv) 
108 {
109         struct cli_state *cli = NULL;
110         struct rpc_pipe_client *pipe_hnd = NULL;
111         TALLOC_CTX *mem_ctx;
112         NTSTATUS nt_status;
113         DOM_SID *domain_sid;
114         char *domain_name;
115
116         /* make use of cli_state handed over as an argument, if possible */
117         if (!cli_arg) {
118                 cli = net_make_ipc_connection(conn_flags);
119         } else {
120                 cli = cli_arg;
121         }
122
123         if (!cli) {
124                 return -1;
125         }
126
127         /* Create mem_ctx */
128         
129         if (!(mem_ctx = talloc_init("run_rpc_command"))) {
130                 DEBUG(0, ("talloc_init() failed\n"));
131                 cli_shutdown(cli);
132                 return -1;
133         }
134         
135         nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
136                                               &domain_name);
137         if (!NT_STATUS_IS_OK(nt_status)) {
138                 cli_shutdown(cli);
139                 return -1;
140         }
141
142         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
143                 if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) {
144                         /* Always try and create an schannel netlogon pipe. */
145                         pipe_hnd = cli_rpc_pipe_open_schannel(cli, pipe_idx,
146                                                         PIPE_AUTH_LEVEL_PRIVACY,
147                                                         domain_name,
148                                                         &nt_status);
149                         if (!pipe_hnd) {
150                                 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
151                                         nt_errstr(nt_status) ));
152                                 cli_shutdown(cli);
153                                 return -1;
154                         }
155                 } else {
156                         pipe_hnd = cli_rpc_pipe_open_noauth(cli, pipe_idx, &nt_status);
157                         if (!pipe_hnd) {
158                                 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
159                                         cli_get_pipe_name(pipe_idx),
160                                         nt_errstr(nt_status) ));
161                                 cli_shutdown(cli);
162                                 return -1;
163                         }
164                 }
165         }
166         
167         nt_status = fn(domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
168         
169         if (!NT_STATUS_IS_OK(nt_status)) {
170                 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
171         } else {
172                 DEBUG(5, ("rpc command function succedded\n"));
173         }
174                 
175         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
176                 if (pipe_hnd) {
177                         cli_rpc_pipe_close(pipe_hnd);
178                 }
179         }
180
181         /* close the connection only if it was opened here */
182         if (!cli_arg) {
183                 cli_shutdown(cli);
184         }
185         
186         talloc_destroy(mem_ctx);
187         return (!NT_STATUS_IS_OK(nt_status));
188 }
189
190 /** 
191  * Force a change of the trust acccount password.
192  *
193  * All parameters are provided by the run_rpc_command function, except for
194  * argc, argv which are passes through. 
195  *
196  * @param domain_sid The domain sid aquired from the remote server
197  * @param cli A cli_state connected to the server.
198  * @param mem_ctx Talloc context, destoyed on compleation of the function.
199  * @param argc  Standard main() style argc
200  * @param argc  Standard main() style argv.  Initial components are already
201  *              stripped
202  *
203  * @return Normal NTSTATUS return.
204  **/
205
206 static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid,
207                                         const char *domain_name, 
208                                         struct cli_state *cli,
209                                         struct rpc_pipe_client *pipe_hnd,
210                                         TALLOC_CTX *mem_ctx, 
211                                         int argc,
212                                         const char **argv)
213 {
214         
215         return trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup);
216 }
217
218 /** 
219  * Force a change of the trust acccount password.
220  *
221  * @param argc  Standard main() style argc
222  * @param argc  Standard main() style argv.  Initial components are already
223  *              stripped
224  *
225  * @return A shell status integer (0 for success)
226  **/
227
228 int net_rpc_changetrustpw(int argc, const char **argv) 
229 {
230         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
231                                rpc_changetrustpw_internals,
232                                argc, argv);
233 }
234
235 /** 
236  * Join a domain, the old way.
237  *
238  * This uses 'machinename' as the inital password, and changes it. 
239  *
240  * The password should be created with 'server manager' or equiv first.
241  *
242  * All parameters are provided by the run_rpc_command function, except for
243  * argc, argv which are passes through. 
244  *
245  * @param domain_sid The domain sid aquired from the remote server
246  * @param cli A cli_state connected to the server.
247  * @param mem_ctx Talloc context, destoyed on compleation of the function.
248  * @param argc  Standard main() style argc
249  * @param argc  Standard main() style argv.  Initial components are already
250  *              stripped
251  *
252  * @return Normal NTSTATUS return.
253  **/
254
255 static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid,
256                                         const char *domain_name, 
257                                         struct cli_state *cli, 
258                                         struct rpc_pipe_client *pipe_hnd,
259                                         TALLOC_CTX *mem_ctx, 
260                                         int argc,
261                                         const char **argv)
262 {
263         
264         fstring trust_passwd;
265         unsigned char orig_trust_passwd_hash[16];
266         NTSTATUS result;
267         uint32 sec_channel_type;
268
269         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result);
270         if (!pipe_hnd) {
271                 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
272                         "error was %s\n",
273                         cli->desthost,
274                         nt_errstr(result) ));
275                 return result;
276         }
277
278         /* 
279            check what type of join - if the user want's to join as
280            a BDC, the server must agree that we are a BDC.
281         */
282         if (argc >= 0) {
283                 sec_channel_type = get_sec_channel_type(argv[0]);
284         } else {
285                 sec_channel_type = get_sec_channel_type(NULL);
286         }
287         
288         fstrcpy(trust_passwd, global_myname());
289         strlower_m(trust_passwd);
290
291         /*
292          * Machine names can be 15 characters, but the max length on
293          * a password is 14.  --jerry
294          */
295
296         trust_passwd[14] = '\0';
297
298         E_md4hash(trust_passwd, orig_trust_passwd_hash);
299
300         result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup,
301                                               orig_trust_passwd_hash,
302                                               sec_channel_type);
303
304         if (NT_STATUS_IS_OK(result))
305                 printf("Joined domain %s.\n",opt_target_workgroup);
306
307
308         if (!secrets_store_domain_sid(opt_target_workgroup, domain_sid)) {
309                 DEBUG(0, ("error storing domain sid for %s\n", opt_target_workgroup));
310                 result = NT_STATUS_UNSUCCESSFUL;
311         }
312
313         return result;
314 }
315
316 /** 
317  * Join a domain, the old way.
318  *
319  * @param argc  Standard main() style argc
320  * @param argc  Standard main() style argv.  Initial components are already
321  *              stripped
322  *
323  * @return A shell status integer (0 for success)
324  **/
325
326 static int net_rpc_perform_oldjoin(int argc, const char **argv)
327 {
328         return run_rpc_command(NULL, PI_NETLOGON, 
329                                NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
330                                rpc_oldjoin_internals,
331                                argc, argv);
332 }
333
334 /** 
335  * Join a domain, the old way.  This function exists to allow
336  * the message to be displayed when oldjoin was explicitly 
337  * requested, but not when it was implied by "net rpc join"
338  *
339  * @param argc  Standard main() style argc
340  * @param argc  Standard main() style argv.  Initial components are already
341  *              stripped
342  *
343  * @return A shell status integer (0 for success)
344  **/
345
346 static int net_rpc_oldjoin(int argc, const char **argv) 
347 {
348         int rc = net_rpc_perform_oldjoin(argc, argv);
349
350         if (rc) {
351                 d_fprintf(stderr, "Failed to join domain\n");
352         }
353
354         return rc;
355 }
356
357 /** 
358  * Basic usage function for 'net rpc join'
359  * @param argc  Standard main() style argc
360  * @param argc  Standard main() style argv.  Initial components are already
361  *              stripped
362  **/
363
364 static int rpc_join_usage(int argc, const char **argv) 
365 {       
366         d_printf("net rpc join -U <username>[%%password] <type>[options]\n"\
367                  "\t to join a domain with admin username & password\n"\
368                  "\t\t password will be prompted if needed and none is specified\n"\
369                  "\t <type> can be (default MEMBER)\n"\
370                  "\t\t BDC - Join as a BDC\n"\
371                  "\t\t PDC - Join as a PDC\n"\
372                  "\t\t MEMBER - Join as a MEMBER server\n");
373
374         net_common_flags_usage(argc, argv);
375         return -1;
376 }
377
378 /** 
379  * 'net rpc join' entrypoint.
380  * @param argc  Standard main() style argc
381  * @param argc  Standard main() style argv.  Initial components are already
382  *              stripped
383  *
384  * Main 'net_rpc_join()' (where the admain username/password is used) is 
385  * in net_rpc_join.c
386  * Try to just change the password, but if that doesn't work, use/prompt
387  * for a username/password.
388  **/
389
390 int net_rpc_join(int argc, const char **argv) 
391 {
392         if ((net_rpc_perform_oldjoin(argc, argv) == 0))
393                 return 0;
394         
395         return net_rpc_join_newstyle(argc, argv);
396 }
397
398 /** 
399  * display info about a rpc domain
400  *
401  * All parameters are provided by the run_rpc_command function, except for
402  * argc, argv which are passed through. 
403  *
404  * @param domain_sid The domain sid acquired from the remote server
405  * @param cli A cli_state connected to the server.
406  * @param mem_ctx Talloc context, destoyed on completion of the function.
407  * @param argc  Standard main() style argc
408  * @param argv  Standard main() style argv.  Initial components are already
409  *              stripped
410  *
411  * @return Normal NTSTATUS return.
412  **/
413
414 NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
415                         const char *domain_name, 
416                         struct cli_state *cli,
417                         struct rpc_pipe_client *pipe_hnd,
418                         TALLOC_CTX *mem_ctx,
419                         int argc,
420                         const char **argv)
421 {
422         POLICY_HND connect_pol, domain_pol;
423         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
424         SAM_UNK_CTR ctr;
425         fstring sid_str;
426
427         sid_to_string(sid_str, domain_sid);
428
429         /* Get sam policy handle */     
430         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
431                                   &connect_pol);
432         if (!NT_STATUS_IS_OK(result)) {
433                 d_fprintf(stderr, "Could not connect to SAM: %s\n", nt_errstr(result));
434                 goto done;
435         }
436         
437         /* Get domain policy handle */
438         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
439                                       MAXIMUM_ALLOWED_ACCESS,
440                                       domain_sid, &domain_pol);
441         if (!NT_STATUS_IS_OK(result)) {
442                 d_fprintf(stderr, "Could not open domain: %s\n", nt_errstr(result));
443                 goto done;
444         }
445
446         ZERO_STRUCT(ctr);
447         result = rpccli_samr_query_dom_info(pipe_hnd, mem_ctx, &domain_pol,
448                                          2, &ctr);
449         if (NT_STATUS_IS_OK(result)) {
450                 TALLOC_CTX *ctx = talloc_init("rpc_info_internals");
451                 d_printf("Domain Name: %s\n", unistr2_tdup(ctx, &ctr.info.inf2.uni_domain));
452                 d_printf("Domain SID: %s\n", sid_str);
453                 d_printf("Sequence number: %u\n", ctr.info.inf2.seq_num.low);
454                 d_printf("Num users: %u\n", ctr.info.inf2.num_domain_usrs);
455                 d_printf("Num domain groups: %u\n", ctr.info.inf2.num_domain_grps);
456                 d_printf("Num local groups: %u\n", ctr.info.inf2.num_local_grps);
457                 talloc_destroy(ctx);
458         }
459
460  done:
461         return result;
462 }
463
464 /** 
465  * 'net rpc info' entrypoint.
466  * @param argc  Standard main() style argc
467  * @param argc  Standard main() style argv.  Initial components are already
468  *              stripped
469  **/
470
471 int net_rpc_info(int argc, const char **argv) 
472 {
473         return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_PDC, 
474                                rpc_info_internals,
475                                argc, argv);
476 }
477
478 /** 
479  * Fetch domain SID into the local secrets.tdb
480  *
481  * All parameters are provided by the run_rpc_command function, except for
482  * argc, argv which are passes through. 
483  *
484  * @param domain_sid The domain sid acquired from the remote server
485  * @param cli A cli_state connected to the server.
486  * @param mem_ctx Talloc context, destoyed on completion of the function.
487  * @param argc  Standard main() style argc
488  * @param argv  Standard main() style argv.  Initial components are already
489  *              stripped
490  *
491  * @return Normal NTSTATUS return.
492  **/
493
494 static NTSTATUS rpc_getsid_internals(const DOM_SID *domain_sid,
495                         const char *domain_name, 
496                         struct cli_state *cli,
497                         struct rpc_pipe_client *pipe_hnd,
498                         TALLOC_CTX *mem_ctx,
499                         int argc,
500                         const char **argv)
501 {
502         fstring sid_str;
503
504         sid_to_string(sid_str, domain_sid);
505         d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
506                  sid_str, domain_name);
507
508         if (!secrets_store_domain_sid(domain_name, domain_sid)) {
509                 DEBUG(0,("Can't store domain SID\n"));
510                 return NT_STATUS_UNSUCCESSFUL;
511         }
512
513         return NT_STATUS_OK;
514 }
515
516 /** 
517  * 'net rpc getsid' entrypoint.
518  * @param argc  Standard main() style argc
519  * @param argc  Standard main() style argv.  Initial components are already
520  *              stripped
521  **/
522
523 int net_rpc_getsid(int argc, const char **argv) 
524 {
525         return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
526                                rpc_getsid_internals,
527                                argc, argv);
528 }
529
530 /****************************************************************************/
531
532 /**
533  * Basic usage function for 'net rpc user'
534  * @param argc  Standard main() style argc.
535  * @param argv  Standard main() style argv.  Initial components are already
536  *              stripped.
537  **/
538
539 static int rpc_user_usage(int argc, const char **argv)
540 {
541         return net_help_user(argc, argv);
542 }
543
544 /** 
545  * Add a new user to a remote RPC server
546  *
547  * All parameters are provided by the run_rpc_command function, except for
548  * argc, argv which are passes through. 
549  *
550  * @param domain_sid The domain sid acquired from the remote server
551  * @param cli A cli_state connected to the server.
552  * @param mem_ctx Talloc context, destoyed on completion of the function.
553  * @param argc  Standard main() style argc
554  * @param argv  Standard main() style argv.  Initial components are already
555  *              stripped
556  *
557  * @return Normal NTSTATUS return.
558  **/
559
560 static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid,
561                                 const char *domain_name, 
562                                 struct cli_state *cli,
563                                 struct rpc_pipe_client *pipe_hnd,
564                                 TALLOC_CTX *mem_ctx, 
565                                 int argc, const char **argv)
566 {
567         
568         POLICY_HND connect_pol, domain_pol, user_pol;
569         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
570         const char *acct_name;
571         uint32 acb_info;
572         uint32 unknown, user_rid;
573
574         if (argc != 1) {
575                 d_printf("User must be specified\n");
576                 rpc_user_usage(argc, argv);
577                 return NT_STATUS_OK;
578         }
579
580         acct_name = argv[0];
581
582         /* Get sam policy handle */
583         
584         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
585                                   &connect_pol);
586         if (!NT_STATUS_IS_OK(result)) {
587                 goto done;
588         }
589         
590         /* Get domain policy handle */
591         
592         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
593                                       MAXIMUM_ALLOWED_ACCESS,
594                                       domain_sid, &domain_pol);
595         if (!NT_STATUS_IS_OK(result)) {
596                 goto done;
597         }
598
599         /* Create domain user */
600
601         acb_info = ACB_NORMAL;
602         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
603
604         result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
605                                           acct_name, acb_info, unknown,
606                                           &user_pol, &user_rid);
607         if (!NT_STATUS_IS_OK(result)) {
608                 goto done;
609         }
610
611  done:
612         if (!NT_STATUS_IS_OK(result)) {
613                 d_fprintf(stderr, "Failed to add user %s - %s\n", acct_name, 
614                          nt_errstr(result));
615         } else {
616                 d_printf("Added user %s\n", acct_name);
617         }
618         return result;
619 }
620
621 /** 
622  * Add a new user to a remote RPC server
623  *
624  * @param argc  Standard main() style argc
625  * @param argv  Standard main() style argv.  Initial components are already
626  *              stripped
627  *
628  * @return A shell status integer (0 for success)
629  **/
630
631 static int rpc_user_add(int argc, const char **argv) 
632 {
633         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_add_internals,
634                                argc, argv);
635 }
636
637 /** 
638  * Delete a user from a remote RPC server
639  *
640  * All parameters are provided by the run_rpc_command function, except for
641  * argc, argv which are passes through. 
642  *
643  * @param domain_sid The domain sid acquired from the remote server
644  * @param cli A cli_state connected to the server.
645  * @param mem_ctx Talloc context, destoyed on completion of the function.
646  * @param argc  Standard main() style argc
647  * @param argv  Standard main() style argv.  Initial components are already
648  *              stripped
649  *
650  * @return Normal NTSTATUS return.
651  **/
652
653 static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, 
654                                         const char *domain_name, 
655                                         struct cli_state *cli, 
656                                         struct rpc_pipe_client *pipe_hnd,
657                                         TALLOC_CTX *mem_ctx, 
658                                         int argc,
659                                         const char **argv)
660 {
661         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
662         POLICY_HND connect_pol, domain_pol, user_pol;
663
664         if (argc < 1) {
665                 d_printf("User must be specified\n");
666                 rpc_user_usage(argc, argv);
667                 return NT_STATUS_OK;
668         }
669         /* Get sam policy and domain handles */
670
671         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
672                                   &connect_pol);
673
674         if (!NT_STATUS_IS_OK(result)) {
675                 goto done;
676         }
677
678         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
679                                       MAXIMUM_ALLOWED_ACCESS,
680                                       domain_sid, &domain_pol);
681
682         if (!NT_STATUS_IS_OK(result)) {
683                 goto done;
684         }
685
686         /* Get handle on user */
687
688         {
689                 uint32 *user_rids, num_rids, *name_types;
690                 uint32 flags = 0x000003e8; /* Unknown */
691
692                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
693                                                flags, 1, &argv[0],
694                                                &num_rids, &user_rids,
695                                                &name_types);
696
697                 if (!NT_STATUS_IS_OK(result)) {
698                         goto done;
699                 }
700
701                 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
702                                             MAXIMUM_ALLOWED_ACCESS,
703                                             user_rids[0], &user_pol);
704
705                 if (!NT_STATUS_IS_OK(result)) {
706                         goto done;
707                 }
708         }
709
710         /* Delete user */
711
712         result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
713
714         if (!NT_STATUS_IS_OK(result)) {
715                 goto done;
716         }
717
718         /* Display results */
719         if (!NT_STATUS_IS_OK(result)) {
720                 d_fprintf(stderr, "Failed to delete user account - %s\n", nt_errstr(result));
721         } else {
722                 d_printf("Deleted user account\n");
723         }
724
725  done:
726         return result;
727 }
728
729 /** 
730  * Rename a user on a remote RPC server
731  *
732  * All parameters are provided by the run_rpc_command function, except for
733  * argc, argv which are passes through. 
734  *
735  * @param domain_sid The domain sid acquired from the remote server
736  * @param cli A cli_state connected to the server.
737  * @param mem_ctx Talloc context, destoyed on completion of the function.
738  * @param argc  Standard main() style argc
739  * @param argv  Standard main() style argv.  Initial components are already
740  *              stripped
741  *
742  * @return Normal NTSTATUS return.
743  **/
744
745 static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid,
746                                         const char *domain_name, 
747                                         struct cli_state *cli,
748                                         struct rpc_pipe_client *pipe_hnd,
749                                         TALLOC_CTX *mem_ctx, 
750                                         int argc,
751                                         const char **argv)
752 {
753         POLICY_HND connect_pol, domain_pol, user_pol;
754         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
755         uint32 info_level = 7;
756         const char *old_name, *new_name;
757         uint32 *user_rid;
758         uint32 flags = 0x000003e8; /* Unknown */
759         uint32 num_rids, *name_types;
760         uint32 num_names = 1;
761         const char **names;
762         SAM_USERINFO_CTR *user_ctr;
763         SAM_USERINFO_CTR ctr;
764         SAM_USER_INFO_7 info7;
765
766         if (argc != 2) {
767                 d_printf("Old and new username must be specified\n");
768                 rpc_user_usage(argc, argv);
769                 return NT_STATUS_OK;
770         }
771
772         old_name = argv[0];
773         new_name = argv[1];
774
775         ZERO_STRUCT(ctr);
776         ZERO_STRUCT(user_ctr);
777
778         /* Get sam policy handle */
779         
780         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
781                                   &connect_pol);
782         if (!NT_STATUS_IS_OK(result)) {
783                 goto done;
784         }
785         
786         /* Get domain policy handle */
787         
788         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
789                                       MAXIMUM_ALLOWED_ACCESS,
790                                       domain_sid, &domain_pol);
791         if (!NT_STATUS_IS_OK(result)) {
792                 goto done;
793         }
794
795         names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
796         names[0] = old_name;
797         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
798                                        flags, num_names, names,
799                                        &num_rids, &user_rid, &name_types);
800         if (!NT_STATUS_IS_OK(result)) {
801                 goto done;
802         }
803
804         /* Open domain user */
805         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
806                                     MAXIMUM_ALLOWED_ACCESS, user_rid[0], &user_pol);
807
808         if (!NT_STATUS_IS_OK(result)) {
809                 goto done;
810         }
811
812         /* Query user info */
813         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol,
814                                          info_level, &user_ctr);
815
816         if (!NT_STATUS_IS_OK(result)) {
817                 goto done;
818         }
819
820         ctr.switch_value = info_level;
821         ctr.info.id7 = &info7;
822
823         init_sam_user_info7(&info7, new_name);
824
825         /* Set new name */
826         result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol,
827                                        info_level, &cli->user_session_key, &ctr);
828
829         if (!NT_STATUS_IS_OK(result)) {
830                 goto done;
831         }
832
833  done:
834         if (!NT_STATUS_IS_OK(result)) {
835                 d_fprintf(stderr, "Failed to rename user from %s to %s - %s\n", old_name, new_name, 
836                          nt_errstr(result));
837         } else {
838                 d_printf("Renamed user from %s to %s\n", old_name, new_name);
839         }
840         return result;
841 }
842
843 /** 
844  * Rename a user on a remote RPC server
845  *
846  * @param argc  Standard main() style argc
847  * @param argv  Standard main() style argv.  Initial components are already
848  *              stripped
849  *
850  * @return A shell status integer (0 for success)
851  **/
852
853 static int rpc_user_rename(int argc, const char **argv) 
854 {
855         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_rename_internals,
856                                argc, argv);
857 }
858
859 /** 
860  * Delete a user from a remote RPC server
861  *
862  * @param argc  Standard main() style argc
863  * @param argv  Standard main() style argv.  Initial components are already
864  *              stripped
865  *
866  * @return A shell status integer (0 for success)
867  **/
868
869 static int rpc_user_delete(int argc, const char **argv) 
870 {
871         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_del_internals,
872                                argc, argv);
873 }
874
875 /** 
876  * Set a password for a user on a remote RPC server
877  *
878  * All parameters are provided by the run_rpc_command function, except for
879  * argc, argv which are passes through. 
880  *
881  * @param domain_sid The domain sid acquired from the remote server
882  * @param cli A cli_state connected to the server.
883  * @param mem_ctx Talloc context, destoyed on completion of the function.
884  * @param argc  Standard main() style argc
885  * @param argv  Standard main() style argv.  Initial components are already
886  *              stripped
887  *
888  * @return Normal NTSTATUS return.
889  **/
890
891 static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid, 
892                                         const char *domain_name, 
893                                         struct cli_state *cli, 
894                                         struct rpc_pipe_client *pipe_hnd,
895                                         TALLOC_CTX *mem_ctx, 
896                                         int argc,
897                                         const char **argv)
898 {
899         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
900         POLICY_HND connect_pol, domain_pol, user_pol;
901         SAM_USERINFO_CTR ctr;
902         SAM_USER_INFO_24 p24;
903         uchar pwbuf[516];
904         const char *user;
905         const char *new_password;
906         char *prompt = NULL;
907
908         if (argc < 1) {
909                 d_printf("User must be specified\n");
910                 rpc_user_usage(argc, argv);
911                 return NT_STATUS_OK;
912         }
913         
914         user = argv[0];
915
916         if (argv[1]) {
917                 new_password = argv[1];
918         } else {
919                 asprintf(&prompt, "Enter new password for %s:", user);
920                 new_password = getpass(prompt);
921                 SAFE_FREE(prompt);
922         }
923
924         /* Get sam policy and domain handles */
925
926         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
927                                   &connect_pol);
928
929         if (!NT_STATUS_IS_OK(result)) {
930                 goto done;
931         }
932
933         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
934                                       MAXIMUM_ALLOWED_ACCESS,
935                                       domain_sid, &domain_pol);
936
937         if (!NT_STATUS_IS_OK(result)) {
938                 goto done;
939         }
940
941         /* Get handle on user */
942
943         {
944                 uint32 *user_rids, num_rids, *name_types;
945                 uint32 flags = 0x000003e8; /* Unknown */
946
947                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
948                                                flags, 1, &user,
949                                                &num_rids, &user_rids,
950                                                &name_types);
951
952                 if (!NT_STATUS_IS_OK(result)) {
953                         goto done;
954                 }
955
956                 result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
957                                             MAXIMUM_ALLOWED_ACCESS,
958                                             user_rids[0], &user_pol);
959
960                 if (!NT_STATUS_IS_OK(result)) {
961                         goto done;
962                 }
963         }
964
965         /* Set password on account */
966
967         ZERO_STRUCT(ctr);
968         ZERO_STRUCT(p24);
969
970         encode_pw_buffer(pwbuf, new_password, STR_UNICODE);
971
972         init_sam_user_info24(&p24, (char *)pwbuf,24);
973
974         ctr.switch_value = 24;
975         ctr.info.id24 = &p24;
976
977         result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24, 
978                                        &cli->user_session_key, &ctr);
979
980         if (!NT_STATUS_IS_OK(result)) {
981                 goto done;
982         }
983
984         /* Display results */
985
986  done:
987         return result;
988
989 }       
990
991 /** 
992  * Set a user's password on a remote RPC server
993  *
994  * @param argc  Standard main() style argc
995  * @param argv  Standard main() style argv.  Initial components are already
996  *              stripped
997  *
998  * @return A shell status integer (0 for success)
999  **/
1000
1001 static int rpc_user_password(int argc, const char **argv) 
1002 {
1003         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_password_internals,
1004                                argc, argv);
1005 }
1006
1007 /** 
1008  * List user's groups on a remote RPC server
1009  *
1010  * All parameters are provided by the run_rpc_command function, except for
1011  * argc, argv which are passes through. 
1012  *
1013  * @param domain_sid The domain sid acquired from the remote server
1014  * @param cli A cli_state connected to the server.
1015  * @param mem_ctx Talloc context, destoyed on completion of the function.
1016  * @param argc  Standard main() style argc
1017  * @param argv  Standard main() style argv.  Initial components are already
1018  *              stripped
1019  *
1020  * @return Normal NTSTATUS return.
1021  **/
1022
1023 static NTSTATUS rpc_user_info_internals(const DOM_SID *domain_sid,
1024                         const char *domain_name, 
1025                         struct cli_state *cli,
1026                         struct rpc_pipe_client *pipe_hnd,
1027                         TALLOC_CTX *mem_ctx,
1028                         int argc,
1029                         const char **argv)
1030 {
1031         POLICY_HND connect_pol, domain_pol, user_pol;
1032         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1033         uint32 *rids, num_rids, *name_types, num_names;
1034         uint32 flags = 0x000003e8; /* Unknown */
1035         int i;
1036         char **names;
1037         DOM_GID *user_gids;
1038
1039         if (argc < 1) {
1040                 d_printf("User must be specified\n");
1041                 rpc_user_usage(argc, argv);
1042                 return NT_STATUS_OK;
1043         }
1044         /* Get sam policy handle */
1045         
1046         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1047                                   &connect_pol);
1048         if (!NT_STATUS_IS_OK(result)) goto done;
1049         
1050         /* Get domain policy handle */
1051         
1052         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1053                                       MAXIMUM_ALLOWED_ACCESS,
1054                                       domain_sid, &domain_pol);
1055         if (!NT_STATUS_IS_OK(result)) goto done;
1056
1057         /* Get handle on user */
1058
1059         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
1060                                        flags, 1, &argv[0],
1061                                        &num_rids, &rids, &name_types);
1062
1063         if (!NT_STATUS_IS_OK(result)) goto done;
1064
1065         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
1066                                     MAXIMUM_ALLOWED_ACCESS,
1067                                     rids[0], &user_pol);
1068         if (!NT_STATUS_IS_OK(result)) goto done;
1069
1070         result = rpccli_samr_query_usergroups(pipe_hnd, mem_ctx, &user_pol,
1071                                            &num_rids, &user_gids);
1072
1073         if (!NT_STATUS_IS_OK(result)) goto done;
1074
1075         /* Look up rids */
1076
1077         if (num_rids) {
1078                 rids = TALLOC_ARRAY(mem_ctx, uint32, num_rids);
1079
1080                 for (i = 0; i < num_rids; i++)
1081                         rids[i] = user_gids[i].g_rid;
1082
1083                 result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, &domain_pol,
1084                                               num_rids, rids,
1085                                               &num_names, &names, &name_types);
1086
1087                 if (!NT_STATUS_IS_OK(result)) {
1088                         goto done;
1089                 }
1090
1091                 /* Display results */
1092
1093                 for (i = 0; i < num_names; i++)
1094                         printf("%s\n", names[i]);
1095         }
1096  done:
1097         return result;
1098 }
1099
1100 /** 
1101  * List a user's groups from a remote RPC server
1102  *
1103  * @param argc  Standard main() style argc
1104  * @param argv  Standard main() style argv.  Initial components are already
1105  *              stripped
1106  *
1107  * @return A shell status integer (0 for success)
1108  **/
1109
1110 static int rpc_user_info(int argc, const char **argv) 
1111 {
1112         return run_rpc_command(NULL, PI_SAMR, 0, rpc_user_info_internals,
1113                                argc, argv);
1114 }
1115
1116 /** 
1117  * List users on a remote RPC server
1118  *
1119  * All parameters are provided by the run_rpc_command function, except for
1120  * argc, argv which are passes through. 
1121  *
1122  * @param domain_sid The domain sid acquired from the remote server
1123  * @param cli A cli_state connected to the server.
1124  * @param mem_ctx Talloc context, destoyed on completion of the function.
1125  * @param argc  Standard main() style argc
1126  * @param argv  Standard main() style argv.  Initial components are already
1127  *              stripped
1128  *
1129  * @return Normal NTSTATUS return.
1130  **/
1131
1132 static NTSTATUS rpc_user_list_internals(const DOM_SID *domain_sid,
1133                                         const char *domain_name, 
1134                                         struct cli_state *cli,
1135                                         struct rpc_pipe_client *pipe_hnd,
1136                                         TALLOC_CTX *mem_ctx,
1137                                         int argc,
1138                                         const char **argv)
1139 {
1140         POLICY_HND connect_pol, domain_pol;
1141         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1142         uint32 start_idx=0, num_entries, i, loop_count = 0;
1143         SAM_DISPINFO_CTR ctr;
1144         SAM_DISPINFO_1 info1;
1145
1146         /* Get sam policy handle */
1147         
1148         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1149                                   &connect_pol);
1150         if (!NT_STATUS_IS_OK(result)) {
1151                 goto done;
1152         }
1153         
1154         /* Get domain policy handle */
1155         
1156         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1157                                       MAXIMUM_ALLOWED_ACCESS,
1158                                       domain_sid, &domain_pol);
1159         if (!NT_STATUS_IS_OK(result)) {
1160                 goto done;
1161         }
1162
1163         /* Query domain users */
1164         ZERO_STRUCT(ctr);
1165         ZERO_STRUCT(info1);
1166         ctr.sam.info1 = &info1;
1167         if (opt_long_list_entries)
1168                 d_printf("\nUser name             Comment"\
1169                          "\n-----------------------------\n");
1170         do {
1171                 fstring user, desc;
1172                 uint32 max_entries, max_size;
1173
1174                 get_query_dispinfo_params(
1175                         loop_count, &max_entries, &max_size);
1176
1177                 result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol,
1178                                                  &start_idx, 1, &num_entries,
1179                                                  max_entries, max_size, &ctr);
1180                 loop_count++;
1181
1182                 for (i = 0; i < num_entries; i++) {
1183                         unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user)-1);
1184                         if (opt_long_list_entries) 
1185                                 unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1);
1186                         
1187                         if (opt_long_list_entries)
1188                                 printf("%-21.21s %s\n", user, desc);
1189                         else
1190                                 printf("%s\n", user);
1191                 }
1192         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1193
1194  done:
1195         return result;
1196 }
1197
1198 /** 
1199  * 'net rpc user' entrypoint.
1200  * @param argc  Standard main() style argc
1201  * @param argc  Standard main() style argv.  Initial components are already
1202  *              stripped
1203  **/
1204
1205 int net_rpc_user(int argc, const char **argv) 
1206 {
1207         struct functable func[] = {
1208                 {"add", rpc_user_add},
1209                 {"info", rpc_user_info},
1210                 {"delete", rpc_user_delete},
1211                 {"password", rpc_user_password},
1212                 {"rename", rpc_user_rename},
1213                 {NULL, NULL}
1214         };
1215         
1216         if (argc == 0) {
1217                 return run_rpc_command(NULL,PI_SAMR, 0, 
1218                                        rpc_user_list_internals,
1219                                        argc, argv);
1220         }
1221
1222         return net_run_function(argc, argv, func, rpc_user_usage);
1223 }
1224
1225 static NTSTATUS rpc_sh_user_list(TALLOC_CTX *mem_ctx,
1226                                  struct rpc_sh_ctx *ctx,
1227                                  struct rpc_pipe_client *pipe_hnd,
1228                                  int argc, const char **argv)
1229 {
1230         return rpc_user_list_internals(ctx->domain_sid, ctx->domain_name,
1231                                        ctx->cli, pipe_hnd, mem_ctx,
1232                                        argc, argv);
1233 }
1234
1235 static NTSTATUS rpc_sh_user_info(TALLOC_CTX *mem_ctx,
1236                                  struct rpc_sh_ctx *ctx,
1237                                  struct rpc_pipe_client *pipe_hnd,
1238                                  int argc, const char **argv)
1239 {
1240         return rpc_user_info_internals(ctx->domain_sid, ctx->domain_name,
1241                                        ctx->cli, pipe_hnd, mem_ctx,
1242                                        argc, argv);
1243 }
1244
1245 static NTSTATUS rpc_sh_handle_user(TALLOC_CTX *mem_ctx,
1246                                    struct rpc_sh_ctx *ctx,
1247                                    struct rpc_pipe_client *pipe_hnd,
1248                                    int argc, const char **argv,
1249                                    NTSTATUS (*fn)(
1250                                            TALLOC_CTX *mem_ctx,
1251                                            struct rpc_sh_ctx *ctx,
1252                                            struct rpc_pipe_client *pipe_hnd,
1253                                            const POLICY_HND *user_hnd,
1254                                            int argc, const char **argv))
1255                                            
1256 {
1257         POLICY_HND connect_pol, domain_pol, user_pol;
1258         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1259         DOM_SID sid;
1260         uint32 rid;
1261         enum SID_NAME_USE type;
1262
1263         if (argc == 0) {
1264                 d_fprintf(stderr, "usage: %s <username>\n", ctx->whoami);
1265                 return NT_STATUS_INVALID_PARAMETER;
1266         }
1267
1268         ZERO_STRUCT(connect_pol);
1269         ZERO_STRUCT(domain_pol);
1270         ZERO_STRUCT(user_pol);
1271
1272         result = net_rpc_lookup_name(mem_ctx, pipe_hnd->cli, argv[0],
1273                                      NULL, NULL, &sid, &type);
1274         if (!NT_STATUS_IS_OK(result)) {
1275                 d_fprintf(stderr, "Could not lookup %s: %s\n", argv[0],
1276                           nt_errstr(result));
1277                 goto done;
1278         }
1279
1280         if (type != SID_NAME_USER) {
1281                 d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
1282                           sid_type_lookup(type));
1283                 result = NT_STATUS_NO_SUCH_USER;
1284                 goto done;
1285         }
1286
1287         if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1288                 d_fprintf(stderr, "%s is not in our domain\n", argv[0]);
1289                 result = NT_STATUS_NO_SUCH_USER;
1290                 goto done;
1291         }
1292
1293         result = rpccli_samr_connect(pipe_hnd, mem_ctx,
1294                                      MAXIMUM_ALLOWED_ACCESS, &connect_pol);
1295         if (!NT_STATUS_IS_OK(result)) {
1296                 goto done;
1297         }
1298
1299         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1300                                          MAXIMUM_ALLOWED_ACCESS,
1301                                          ctx->domain_sid, &domain_pol);
1302         if (!NT_STATUS_IS_OK(result)) {
1303                 goto done;
1304         }
1305
1306         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
1307                                        MAXIMUM_ALLOWED_ACCESS,
1308                                        rid, &user_pol);
1309         if (!NT_STATUS_IS_OK(result)) {
1310                 goto done;
1311         }
1312
1313         result = fn(mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1314
1315  done:
1316         if (is_valid_policy_hnd(&user_pol)) {
1317                 rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
1318         }
1319         if (is_valid_policy_hnd(&domain_pol)) {
1320                 rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
1321         }
1322         if (is_valid_policy_hnd(&connect_pol)) {
1323                 rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
1324         }
1325         return result;
1326 }
1327
1328 static NTSTATUS rpc_sh_user_show_internals(TALLOC_CTX *mem_ctx,
1329                                            struct rpc_sh_ctx *ctx,
1330                                            struct rpc_pipe_client *pipe_hnd,
1331                                            const POLICY_HND *user_hnd,
1332                                            int argc, const char **argv)
1333 {
1334         NTSTATUS result;
1335         SAM_USERINFO_CTR *ctr;
1336         SAM_USER_INFO_21 *info;
1337
1338         if (argc != 0) {
1339                 d_fprintf(stderr, "usage: %s show <username>\n", ctx->whoami);
1340                 return NT_STATUS_INVALID_PARAMETER;
1341         }
1342
1343         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
1344                                             21, &ctr);
1345         if (!NT_STATUS_IS_OK(result)) {
1346                 return result;
1347         }
1348
1349         info = ctr->info.id21;
1350
1351         d_printf("user rid: %d, group rid: %d\n", info->user_rid,
1352                  info->group_rid);
1353
1354         return result;
1355 }
1356
1357 static NTSTATUS rpc_sh_user_show(TALLOC_CTX *mem_ctx,
1358                                  struct rpc_sh_ctx *ctx,
1359                                  struct rpc_pipe_client *pipe_hnd,
1360                                  int argc, const char **argv)
1361 {
1362         return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
1363                                   rpc_sh_user_show_internals);
1364 }
1365
1366 #define FETCHSTR(name, rec) \
1367 do { if (strequal(ctx->thiscmd, name)) { \
1368         oldval = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_##rec); } \
1369 } while (0);
1370
1371 #define SETSTR(name, rec, flag) \
1372 do { if (strequal(ctx->thiscmd, name)) { \
1373         init_unistr2(&usr->uni_##rec, argv[0], STR_TERMINATE); \
1374         init_uni_hdr(&usr->hdr_##rec, &usr->uni_##rec); \
1375         usr->fields_present |= ACCT_##flag; } \
1376 } while (0);
1377
1378 static NTSTATUS rpc_sh_user_str_edit_internals(TALLOC_CTX *mem_ctx,
1379                                                struct rpc_sh_ctx *ctx,
1380                                                struct rpc_pipe_client *pipe_hnd,
1381                                                const POLICY_HND *user_hnd,
1382                                                int argc, const char **argv)
1383 {
1384         NTSTATUS result;
1385         SAM_USERINFO_CTR *ctr;
1386         SAM_USER_INFO_21 *usr;
1387         const char *username;
1388         const char *oldval = "";
1389
1390         if (argc > 1) {
1391                 d_fprintf(stderr, "usage: %s <username> [new value|NULL]\n",
1392                           ctx->whoami);
1393                 return NT_STATUS_INVALID_PARAMETER;
1394         }
1395
1396         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
1397                                             21, &ctr);
1398         if (!NT_STATUS_IS_OK(result)) {
1399                 return result;
1400         }
1401
1402         usr = ctr->info.id21;
1403
1404         username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
1405
1406         FETCHSTR("fullname", full_name);
1407         FETCHSTR("homedir", home_dir);
1408         FETCHSTR("homedrive", dir_drive);
1409         FETCHSTR("logonscript", logon_script);
1410         FETCHSTR("profilepath", profile_path);
1411         FETCHSTR("description", acct_desc);
1412
1413         if (argc == 0) {
1414                 d_printf("%s's %s: [%s]\n", username, ctx->thiscmd, oldval);
1415                 goto done;
1416         }
1417
1418         ZERO_STRUCTP(usr);
1419
1420         if (strcmp(argv[0], "NULL") == 0) {
1421                 argv[0] = "";
1422         }
1423
1424         SETSTR("fullname", full_name, FULL_NAME);
1425         SETSTR("homedir", home_dir, HOME_DIR);
1426         SETSTR("homedrive", dir_drive, HOME_DRIVE);
1427         SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1428         SETSTR("profilepath", profile_path, PROFILE);
1429         SETSTR("description", acct_desc, DESCRIPTION);
1430
1431         result = rpccli_samr_set_userinfo2(
1432                 pipe_hnd, mem_ctx, user_hnd, 21,
1433                 &pipe_hnd->cli->user_session_key, ctr);
1434
1435         d_printf("Set %s's %s from [%s] to [%s]\n", username,
1436                  ctx->thiscmd, oldval, argv[0]);
1437
1438  done:
1439
1440         return result;
1441 }
1442
1443 #define HANDLEFLG(name, rec) \
1444 do { if (strequal(ctx->thiscmd, name)) { \
1445         oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1446         if (newval) { \
1447                 newflags = oldflags | ACB_##rec; \
1448         } else { \
1449                 newflags = oldflags & ~ACB_##rec; \
1450         } } } while (0);
1451
1452 static NTSTATUS rpc_sh_user_str_edit(TALLOC_CTX *mem_ctx,
1453                                      struct rpc_sh_ctx *ctx,
1454                                      struct rpc_pipe_client *pipe_hnd,
1455                                      int argc, const char **argv)
1456 {
1457         return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
1458                                   rpc_sh_user_str_edit_internals);
1459 }
1460
1461 static NTSTATUS rpc_sh_user_flag_edit_internals(TALLOC_CTX *mem_ctx,
1462                                                 struct rpc_sh_ctx *ctx,
1463                                                 struct rpc_pipe_client *pipe_hnd,
1464                                                 const POLICY_HND *user_hnd,
1465                                                 int argc, const char **argv)
1466 {
1467         NTSTATUS result;
1468         SAM_USERINFO_CTR *ctr;
1469         SAM_USER_INFO_21 *usr;
1470         const char *username;
1471         const char *oldval = "unknown";
1472         uint32 oldflags, newflags;
1473         BOOL newval;
1474
1475         if ((argc > 1) ||
1476             ((argc == 1) && !strequal(argv[0], "yes") &&
1477              !strequal(argv[0], "no"))) {
1478                 d_fprintf(stderr, "usage: %s <username> [yes|no]\n",
1479                           ctx->whoami);
1480                 return NT_STATUS_INVALID_PARAMETER;
1481         }
1482
1483         newval = strequal(argv[0], "yes");
1484
1485         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
1486                                             21, &ctr);
1487         if (!NT_STATUS_IS_OK(result)) {
1488                 return result;
1489         }
1490
1491         usr = ctr->info.id21;
1492
1493         username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
1494         oldflags = usr->acb_info;
1495         newflags = usr->acb_info;
1496
1497         HANDLEFLG("disabled", DISABLED);
1498         HANDLEFLG("pwnotreq", PWNOTREQ);
1499         HANDLEFLG("autolock", AUTOLOCK);
1500         HANDLEFLG("pwnoexp", PWNOEXP);
1501
1502         if (argc == 0) {
1503                 d_printf("%s's %s flag: %s\n", username, ctx->thiscmd, oldval);
1504                 goto done;
1505         }
1506
1507         ZERO_STRUCTP(usr);
1508
1509         usr->acb_info = newflags;
1510         usr->fields_present = ACCT_FLAGS;
1511
1512         result = rpccli_samr_set_userinfo2(
1513                 pipe_hnd, mem_ctx, user_hnd, 21,
1514                 &pipe_hnd->cli->user_session_key, ctr);
1515
1516         if (NT_STATUS_IS_OK(result)) {
1517                 d_printf("Set %s's %s flag from [%s] to [%s]\n", username,
1518                          ctx->thiscmd, oldval, argv[0]);
1519         }
1520
1521  done:
1522
1523         return result;
1524 }
1525
1526 static NTSTATUS rpc_sh_user_flag_edit(TALLOC_CTX *mem_ctx,
1527                                       struct rpc_sh_ctx *ctx,
1528                                       struct rpc_pipe_client *pipe_hnd,
1529                                       int argc, const char **argv)
1530 {
1531         return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
1532                                   rpc_sh_user_flag_edit_internals);
1533 }
1534
1535 struct rpc_sh_cmd *net_rpc_user_edit_cmds(TALLOC_CTX *mem_ctx,
1536                                           struct rpc_sh_ctx *ctx)
1537 {
1538         static struct rpc_sh_cmd cmds[] = {
1539
1540                 { "fullname", NULL, PI_SAMR, rpc_sh_user_str_edit,
1541                   "Show/Set a user's full name" },
1542
1543                 { "homedir", NULL, PI_SAMR, rpc_sh_user_str_edit,
1544                   "Show/Set a user's home directory" },
1545
1546                 { "homedrive", NULL, PI_SAMR, rpc_sh_user_str_edit,
1547                   "Show/Set a user's home drive" },
1548
1549                 { "logonscript", NULL, PI_SAMR, rpc_sh_user_str_edit,
1550                   "Show/Set a user's logon script" },
1551
1552                 { "profilepath", NULL, PI_SAMR, rpc_sh_user_str_edit,
1553                   "Show/Set a user's profile path" },
1554
1555                 { "description", NULL, PI_SAMR, rpc_sh_user_str_edit,
1556                   "Show/Set a user's description" },
1557
1558                 { "disabled", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1559                   "Show/Set whether a user is disabled" },
1560
1561                 { "autolock", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1562                   "Show/Set whether a user locked out" },
1563
1564                 { "pwnotreq", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1565                   "Show/Set whether a user does not need a password" },
1566
1567                 { "pwnoexp", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1568                   "Show/Set whether a user's password does not expire" },
1569
1570                 { NULL, NULL, 0, NULL, NULL }
1571         };
1572
1573         return cmds;
1574 }
1575
1576 struct rpc_sh_cmd *net_rpc_user_cmds(TALLOC_CTX *mem_ctx,
1577                                      struct rpc_sh_ctx *ctx)
1578 {
1579         static struct rpc_sh_cmd cmds[] = {
1580
1581                 { "list", NULL, PI_SAMR, rpc_sh_user_list,
1582                   "List available users" },
1583
1584                 { "info", NULL, PI_SAMR, rpc_sh_user_info,
1585                   "List the domain groups a user is member of" },
1586
1587                 { "show", NULL, PI_SAMR, rpc_sh_user_show,
1588                   "Show info about a user" },
1589
1590                 { "edit", net_rpc_user_edit_cmds, 0, NULL, 
1591                   "Show/Modify a user's fields" },
1592
1593                 { NULL, NULL, 0, NULL, NULL }
1594         };
1595
1596         return cmds;
1597 };
1598
1599 /****************************************************************************/
1600
1601 /**
1602  * Basic usage function for 'net rpc group'
1603  * @param argc  Standard main() style argc.
1604  * @param argv  Standard main() style argv.  Initial components are already
1605  *              stripped.
1606  **/
1607
1608 static int rpc_group_usage(int argc, const char **argv)
1609 {
1610         return net_help_group(argc, argv);
1611 }
1612
1613 /**
1614  * Delete group on a remote RPC server
1615  *
1616  * All parameters are provided by the run_rpc_command function, except for
1617  * argc, argv which are passes through.
1618  *
1619  * @param domain_sid The domain sid acquired from the remote server
1620  * @param cli A cli_state connected to the server.
1621  * @param mem_ctx Talloc context, destoyed on completion of the function.
1622  * @param argc  Standard main() style argc
1623  * @param argv  Standard main() style argv.  Initial components are already
1624  *              stripped
1625  *
1626  * @return Normal NTSTATUS return.
1627  **/
1628                                                                                                              
1629 static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
1630                                         const char *domain_name,
1631                                         struct cli_state *cli,
1632                                         struct rpc_pipe_client *pipe_hnd,
1633                                         TALLOC_CTX *mem_ctx,
1634                                         int argc,
1635                                         const char **argv)
1636 {
1637         POLICY_HND connect_pol, domain_pol, group_pol, user_pol;
1638         BOOL group_is_primary = False;
1639         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1640
1641         uint32 *group_rids, num_rids, *name_types, num_members, 
1642                *group_attrs, group_rid;
1643         uint32 flags = 0x000003e8; /* Unknown */
1644         /* char **names; */
1645         int i;
1646         /* DOM_GID *user_gids; */
1647         SAM_USERINFO_CTR *user_ctr;
1648         fstring temp;
1649
1650         if (argc < 1) {
1651                 d_printf("specify group\n");
1652                 rpc_group_usage(argc,argv);
1653                 return NT_STATUS_OK; /* ok? */
1654         }
1655
1656         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1657                                   &connect_pol);
1658
1659         if (!NT_STATUS_IS_OK(result)) {
1660                 d_fprintf(stderr, "Request samr_connect failed\n");
1661                 goto done;
1662         }
1663         
1664         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1665                                       MAXIMUM_ALLOWED_ACCESS,
1666                                       domain_sid, &domain_pol);
1667         
1668         if (!NT_STATUS_IS_OK(result)) {
1669                 d_fprintf(stderr, "Request open_domain failed\n");
1670                 goto done;
1671         }
1672         
1673         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
1674                                        flags, 1, &argv[0],
1675                                        &num_rids, &group_rids,
1676                                        &name_types);
1677
1678         if (!NT_STATUS_IS_OK(result)) {
1679                 d_fprintf(stderr, "Lookup of '%s' failed\n",argv[0]);
1680                 goto done;
1681         }
1682
1683         switch (name_types[0])
1684         {
1685         case SID_NAME_DOM_GRP:
1686                 result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
1687                                              MAXIMUM_ALLOWED_ACCESS,
1688                                              group_rids[0], &group_pol);
1689                 if (!NT_STATUS_IS_OK(result)) {
1690                         d_fprintf(stderr, "Request open_group failed");
1691                         goto done;
1692                 }
1693                 
1694                 group_rid = group_rids[0];
1695                 
1696                 result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol,
1697                                  &num_members, &group_rids,
1698                                  &group_attrs);
1699                 
1700                 if (!NT_STATUS_IS_OK(result)) {
1701                         d_fprintf(stderr, "Unable to query group members of %s",argv[0]);
1702                         goto done;
1703                 }
1704                 
1705                 if (opt_verbose) {
1706                         d_printf("Domain Group %s (rid: %d) has %d members\n",
1707                                 argv[0],group_rid,num_members);
1708                 }
1709
1710                 /* Check if group is anyone's primary group */
1711                 for (i = 0; i < num_members; i++)
1712                 {
1713                         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
1714                                                     MAXIMUM_ALLOWED_ACCESS,
1715                                                     group_rids[i], &user_pol);
1716         
1717                         if (!NT_STATUS_IS_OK(result)) {
1718                                 d_fprintf(stderr, "Unable to open group member %d\n",group_rids[i]);
1719                                 goto done;
1720                         }
1721         
1722                         ZERO_STRUCT(user_ctr);
1723
1724                         result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol,
1725                                                          21, &user_ctr);
1726         
1727                         if (!NT_STATUS_IS_OK(result)) {
1728                                 d_fprintf(stderr, "Unable to lookup userinfo for group member %d\n",group_rids[i]);
1729                                 goto done;
1730                         }
1731         
1732                         if (user_ctr->info.id21->group_rid == group_rid) {
1733                                 unistr2_to_ascii(temp, &(user_ctr->info.id21)->uni_user_name, 
1734                                                 sizeof(temp)-1);
1735                                 if (opt_verbose) 
1736                                         d_printf("Group is primary group of %s\n",temp);
1737                                 group_is_primary = True;
1738                         }
1739
1740                         rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
1741                 }
1742                 
1743                 if (group_is_primary) {
1744                         d_fprintf(stderr, "Unable to delete group because some "
1745                                  "of it's members have it as primary group\n");
1746                         result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1747                         goto done;
1748                 }
1749      
1750                 /* remove all group members */
1751                 for (i = 0; i < num_members; i++)
1752                 {
1753                         if (opt_verbose) 
1754                                 d_printf("Remove group member %d...",group_rids[i]);
1755                         result = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, &group_pol, group_rids[i]);
1756
1757                         if (NT_STATUS_IS_OK(result)) {
1758                                 if (opt_verbose)
1759                                         d_printf("ok\n");
1760                         } else {
1761                                 if (opt_verbose)
1762                                         d_printf("failed\n");
1763                                 goto done;
1764                         }       
1765                 }
1766
1767                 result = rpccli_samr_delete_dom_group(pipe_hnd, mem_ctx, &group_pol);
1768
1769                 break;
1770         /* removing a local group is easier... */
1771         case SID_NAME_ALIAS:
1772                 result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
1773                                              MAXIMUM_ALLOWED_ACCESS,
1774                                              group_rids[0], &group_pol);
1775
1776                 if (!NT_STATUS_IS_OK(result)) {
1777                         d_fprintf(stderr, "Request open_alias failed\n");
1778                         goto done;
1779                 }
1780                 
1781                 result = rpccli_samr_delete_dom_alias(pipe_hnd, mem_ctx, &group_pol);
1782                 break;
1783         default:
1784                 d_fprintf(stderr, "%s is of type %s. This command is only for deleting local or global groups\n",
1785                         argv[0],sid_type_lookup(name_types[0]));
1786                 result = NT_STATUS_UNSUCCESSFUL;
1787                 goto done;
1788         }
1789          
1790         
1791         if (NT_STATUS_IS_OK(result)) {
1792                 if (opt_verbose)
1793                         d_printf("Deleted %s '%s'\n",sid_type_lookup(name_types[0]),argv[0]);
1794         } else {
1795                 d_fprintf(stderr, "Deleting of %s failed: %s\n",argv[0],
1796                         get_friendly_nt_error_msg(result));
1797         }
1798         
1799  done:
1800         return result;  
1801         
1802 }
1803
1804 static int rpc_group_delete(int argc, const char **argv)
1805 {
1806         return run_rpc_command(NULL, PI_SAMR, 0, rpc_group_delete_internals,
1807                                argc,argv);
1808 }
1809
1810 static NTSTATUS rpc_group_add_internals(const DOM_SID *domain_sid,
1811                                         const char *domain_name, 
1812                                         struct cli_state *cli,
1813                                         struct rpc_pipe_client *pipe_hnd,
1814                                         TALLOC_CTX *mem_ctx,
1815                                         int argc,
1816                                         const char **argv)
1817 {
1818         POLICY_HND connect_pol, domain_pol, group_pol;
1819         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1820         GROUP_INFO_CTR group_info;
1821
1822         if (argc != 1) {
1823                 d_printf("Group name must be specified\n");
1824                 rpc_group_usage(argc, argv);
1825                 return NT_STATUS_OK;
1826         }
1827
1828         /* Get sam policy handle */
1829         
1830         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1831                                   &connect_pol);
1832         if (!NT_STATUS_IS_OK(result)) goto done;
1833         
1834         /* Get domain policy handle */
1835         
1836         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1837                                       MAXIMUM_ALLOWED_ACCESS,
1838                                       domain_sid, &domain_pol);
1839         if (!NT_STATUS_IS_OK(result)) goto done;
1840
1841         /* Create the group */
1842
1843         result = rpccli_samr_create_dom_group(pipe_hnd, mem_ctx, &domain_pol,
1844                                            argv[0], MAXIMUM_ALLOWED_ACCESS,
1845                                            &group_pol);
1846         if (!NT_STATUS_IS_OK(result)) goto done;
1847
1848         if (strlen(opt_comment) == 0) goto done;
1849
1850         /* We've got a comment to set */
1851
1852         group_info.switch_value1 = 4;
1853         init_samr_group_info4(&group_info.group.info4, opt_comment);
1854
1855         result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &group_info);
1856         if (!NT_STATUS_IS_OK(result)) goto done;
1857         
1858  done:
1859         if (NT_STATUS_IS_OK(result))
1860                 DEBUG(5, ("add group succeeded\n"));
1861         else
1862                 d_fprintf(stderr, "add group failed: %s\n", nt_errstr(result));
1863
1864         return result;
1865 }
1866
1867 static NTSTATUS rpc_alias_add_internals(const DOM_SID *domain_sid,
1868                                         const char *domain_name, 
1869                                         struct cli_state *cli,
1870                                         struct rpc_pipe_client *pipe_hnd,
1871                                         TALLOC_CTX *mem_ctx,
1872                                         int argc,
1873                                         const char **argv)
1874 {
1875         POLICY_HND connect_pol, domain_pol, alias_pol;
1876         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1877         ALIAS_INFO_CTR alias_info;
1878
1879         if (argc != 1) {
1880                 d_printf("Alias name must be specified\n");
1881                 rpc_group_usage(argc, argv);
1882                 return NT_STATUS_OK;
1883         }
1884
1885         /* Get sam policy handle */
1886         
1887         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
1888                                   &connect_pol);
1889         if (!NT_STATUS_IS_OK(result)) goto done;
1890         
1891         /* Get domain policy handle */
1892         
1893         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
1894                                       MAXIMUM_ALLOWED_ACCESS,
1895                                       domain_sid, &domain_pol);
1896         if (!NT_STATUS_IS_OK(result)) goto done;
1897
1898         /* Create the group */
1899
1900         result = rpccli_samr_create_dom_alias(pipe_hnd, mem_ctx, &domain_pol,
1901                                            argv[0], &alias_pol);
1902         if (!NT_STATUS_IS_OK(result)) goto done;
1903
1904         if (strlen(opt_comment) == 0) goto done;
1905
1906         /* We've got a comment to set */
1907
1908         alias_info.level = 3;
1909         init_samr_alias_info3(&alias_info.alias.info3, opt_comment);
1910
1911         result = rpccli_samr_set_aliasinfo(pipe_hnd, mem_ctx, &alias_pol, &alias_info);
1912         if (!NT_STATUS_IS_OK(result)) goto done;
1913         
1914  done:
1915         if (NT_STATUS_IS_OK(result))
1916                 DEBUG(5, ("add alias succeeded\n"));
1917         else
1918                 d_fprintf(stderr, "add alias failed: %s\n", nt_errstr(result));
1919
1920         return result;
1921 }
1922
1923 static int rpc_group_add(int argc, const char **argv)
1924 {
1925         if (opt_localgroup)
1926                 return run_rpc_command(NULL, PI_SAMR, 0,
1927                                        rpc_alias_add_internals,
1928                                        argc, argv);
1929
1930         return run_rpc_command(NULL, PI_SAMR, 0,
1931                                rpc_group_add_internals,
1932                                argc, argv);
1933 }
1934
1935 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1936                                 TALLOC_CTX *mem_ctx,
1937                                 const char *name,
1938                                 DOM_SID *sid,
1939                                 enum SID_NAME_USE *type)
1940 {
1941         DOM_SID *sids = NULL;
1942         uint32 *types = NULL;
1943         struct rpc_pipe_client *pipe_hnd;
1944         POLICY_HND lsa_pol;
1945         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1946
1947         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
1948         if (!pipe_hnd) {
1949                 goto done;
1950         }
1951
1952         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, False,
1953                                      SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
1954
1955         if (!NT_STATUS_IS_OK(result)) {
1956                 goto done;
1957         }
1958
1959         result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1960                                       &name, NULL, &sids, &types);
1961
1962         if (NT_STATUS_IS_OK(result)) {
1963                 sid_copy(sid, &sids[0]);
1964                 *type = types[0];
1965         }
1966
1967         rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
1968
1969  done:
1970         if (pipe_hnd) {
1971                 cli_rpc_pipe_close(pipe_hnd);
1972         }
1973
1974         if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
1975
1976                 /* Try as S-1-5-whatever */
1977
1978                 DOM_SID tmp_sid;
1979
1980                 if (string_to_sid(&tmp_sid, name)) {
1981                         sid_copy(sid, &tmp_sid);
1982                         *type = SID_NAME_UNKNOWN;
1983                         result = NT_STATUS_OK;
1984                 }
1985         }
1986
1987         return result;
1988 }
1989
1990 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
1991                                 TALLOC_CTX *mem_ctx,
1992                                 const DOM_SID *group_sid,
1993                                 const char *member)
1994 {
1995         POLICY_HND connect_pol, domain_pol;
1996         NTSTATUS result;
1997         uint32 group_rid;
1998         POLICY_HND group_pol;
1999
2000         uint32 num_rids;
2001         uint32 *rids = NULL;
2002         uint32 *rid_types = NULL;
2003
2004         DOM_SID sid;
2005
2006         sid_copy(&sid, group_sid);
2007
2008         if (!sid_split_rid(&sid, &group_rid)) {
2009                 return NT_STATUS_UNSUCCESSFUL;
2010         }
2011
2012         /* Get sam policy handle */     
2013         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2014                                   &connect_pol);
2015         if (!NT_STATUS_IS_OK(result)) {
2016                 return result;
2017         }
2018         
2019         /* Get domain policy handle */
2020         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2021                                       MAXIMUM_ALLOWED_ACCESS,
2022                                       &sid, &domain_pol);
2023         if (!NT_STATUS_IS_OK(result)) {
2024                 return result;
2025         }
2026
2027         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2028                                        1, &member,
2029                                        &num_rids, &rids, &rid_types);
2030
2031         if (!NT_STATUS_IS_OK(result)) {
2032                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2033                 goto done;
2034         }
2035
2036         result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
2037                                      MAXIMUM_ALLOWED_ACCESS,
2038                                      group_rid, &group_pol);
2039
2040         if (!NT_STATUS_IS_OK(result)) {
2041                 goto done;
2042         }
2043
2044         result = rpccli_samr_add_groupmem(pipe_hnd, mem_ctx, &group_pol, rids[0]);
2045
2046  done:
2047         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
2048         return result;
2049 }
2050
2051 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2052                                 TALLOC_CTX *mem_ctx,
2053                                 const DOM_SID *alias_sid,
2054                                 const char *member)
2055 {
2056         POLICY_HND connect_pol, domain_pol;
2057         NTSTATUS result;
2058         uint32 alias_rid;
2059         POLICY_HND alias_pol;
2060
2061         DOM_SID member_sid;
2062         enum SID_NAME_USE member_type;
2063
2064         DOM_SID sid;
2065
2066         sid_copy(&sid, alias_sid);
2067
2068         if (!sid_split_rid(&sid, &alias_rid)) {
2069                 return NT_STATUS_UNSUCCESSFUL;
2070         }
2071
2072         result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member,
2073                                    &member_sid, &member_type);
2074
2075         if (!NT_STATUS_IS_OK(result)) {
2076                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2077                 return result;
2078         }
2079
2080         /* Get sam policy handle */     
2081         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2082                                   &connect_pol);
2083         if (!NT_STATUS_IS_OK(result)) {
2084                 goto done;
2085         }
2086         
2087         /* Get domain policy handle */
2088         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2089                                       MAXIMUM_ALLOWED_ACCESS,
2090                                       &sid, &domain_pol);
2091         if (!NT_STATUS_IS_OK(result)) {
2092                 goto done;
2093         }
2094
2095         result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
2096                                      MAXIMUM_ALLOWED_ACCESS,
2097                                      alias_rid, &alias_pol);
2098
2099         if (!NT_STATUS_IS_OK(result)) {
2100                 return result;
2101         }
2102
2103         result = rpccli_samr_add_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid);
2104
2105         if (!NT_STATUS_IS_OK(result)) {
2106                 return result;
2107         }
2108
2109  done:
2110         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
2111         return result;
2112 }
2113
2114 static NTSTATUS rpc_group_addmem_internals(const DOM_SID *domain_sid,
2115                                         const char *domain_name, 
2116                                         struct cli_state *cli,
2117                                         struct rpc_pipe_client *pipe_hnd,
2118                                         TALLOC_CTX *mem_ctx,
2119                                         int argc,
2120                                         const char **argv)
2121 {
2122         DOM_SID group_sid;
2123         enum SID_NAME_USE group_type;
2124
2125         if (argc != 2) {
2126                 d_printf("Usage: 'net rpc group addmem <group> <member>\n");
2127                 return NT_STATUS_UNSUCCESSFUL;
2128         }
2129
2130         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2131                                                &group_sid, &group_type))) {
2132                 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2133                 return NT_STATUS_UNSUCCESSFUL;
2134         }
2135
2136         if (group_type == SID_NAME_DOM_GRP) {
2137                 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2138                                                    &group_sid, argv[1]);
2139
2140                 if (!NT_STATUS_IS_OK(result)) {
2141                         d_fprintf(stderr, "Could not add %s to %s: %s\n",
2142                                  argv[1], argv[0], nt_errstr(result));
2143                 }
2144                 return result;
2145         }
2146
2147         if (group_type == SID_NAME_ALIAS) {
2148                 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2149                                                    &group_sid, argv[1]);
2150
2151                 if (!NT_STATUS_IS_OK(result)) {
2152                         d_fprintf(stderr, "Could not add %s to %s: %s\n",
2153                                  argv[1], argv[0], nt_errstr(result));
2154                 }
2155                 return result;
2156         }
2157
2158         d_fprintf(stderr, "Can only add members to global or local groups "
2159                  "which %s is not\n", argv[0]);
2160
2161         return NT_STATUS_UNSUCCESSFUL;
2162 }
2163
2164 static int rpc_group_addmem(int argc, const char **argv)
2165 {
2166         return run_rpc_command(NULL, PI_SAMR, 0,
2167                                rpc_group_addmem_internals,
2168                                argc, argv);
2169 }
2170
2171 static NTSTATUS rpc_del_groupmem(struct rpc_pipe_client *pipe_hnd,
2172                                 TALLOC_CTX *mem_ctx,
2173                                 const DOM_SID *group_sid,
2174                                 const char *member)
2175 {
2176         POLICY_HND connect_pol, domain_pol;
2177         NTSTATUS result;
2178         uint32 group_rid;
2179         POLICY_HND group_pol;
2180
2181         uint32 num_rids;
2182         uint32 *rids = NULL;
2183         uint32 *rid_types = NULL;
2184
2185         DOM_SID sid;
2186
2187         sid_copy(&sid, group_sid);
2188
2189         if (!sid_split_rid(&sid, &group_rid))
2190                 return NT_STATUS_UNSUCCESSFUL;
2191
2192         /* Get sam policy handle */     
2193         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2194                                   &connect_pol);
2195         if (!NT_STATUS_IS_OK(result))
2196                 return result;
2197         
2198         /* Get domain policy handle */
2199         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2200                                       MAXIMUM_ALLOWED_ACCESS,
2201                                       &sid, &domain_pol);
2202         if (!NT_STATUS_IS_OK(result))
2203                 return result;
2204
2205         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2206                                        1, &member,
2207                                        &num_rids, &rids, &rid_types);
2208
2209         if (!NT_STATUS_IS_OK(result)) {
2210                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2211                 goto done;
2212         }
2213
2214         result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
2215                                      MAXIMUM_ALLOWED_ACCESS,
2216                                      group_rid, &group_pol);
2217
2218         if (!NT_STATUS_IS_OK(result))
2219                 goto done;
2220
2221         result = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, &group_pol, rids[0]);
2222
2223  done:
2224         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
2225         return result;
2226 }
2227
2228 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2229                                 TALLOC_CTX *mem_ctx,
2230                                 const DOM_SID *alias_sid,
2231                                 const char *member)
2232 {
2233         POLICY_HND connect_pol, domain_pol;
2234         NTSTATUS result;
2235         uint32 alias_rid;
2236         POLICY_HND alias_pol;
2237
2238         DOM_SID member_sid;
2239         enum SID_NAME_USE member_type;
2240
2241         DOM_SID sid;
2242
2243         sid_copy(&sid, alias_sid);
2244
2245         if (!sid_split_rid(&sid, &alias_rid))
2246                 return NT_STATUS_UNSUCCESSFUL;
2247
2248         result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member,
2249                                    &member_sid, &member_type);
2250
2251         if (!NT_STATUS_IS_OK(result)) {
2252                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2253                 return result;
2254         }
2255
2256         /* Get sam policy handle */     
2257         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2258                                   &connect_pol);
2259         if (!NT_STATUS_IS_OK(result)) {
2260                 goto done;
2261         }
2262         
2263         /* Get domain policy handle */
2264         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2265                                       MAXIMUM_ALLOWED_ACCESS,
2266                                       &sid, &domain_pol);
2267         if (!NT_STATUS_IS_OK(result)) {
2268                 goto done;
2269         }
2270
2271         result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
2272                                      MAXIMUM_ALLOWED_ACCESS,
2273                                      alias_rid, &alias_pol);
2274
2275         if (!NT_STATUS_IS_OK(result))
2276                 return result;
2277
2278         result = rpccli_samr_del_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid);
2279
2280         if (!NT_STATUS_IS_OK(result))
2281                 return result;
2282
2283  done:
2284         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
2285         return result;
2286 }
2287
2288 static NTSTATUS rpc_group_delmem_internals(const DOM_SID *domain_sid,
2289                                         const char *domain_name, 
2290                                         struct cli_state *cli,
2291                                         struct rpc_pipe_client *pipe_hnd,
2292                                         TALLOC_CTX *mem_ctx,
2293                                         int argc,
2294                                         const char **argv)
2295 {
2296         DOM_SID group_sid;
2297         enum SID_NAME_USE group_type;
2298
2299         if (argc != 2) {
2300                 d_printf("Usage: 'net rpc group delmem <group> <member>\n");
2301                 return NT_STATUS_UNSUCCESSFUL;
2302         }
2303
2304         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2305                                                &group_sid, &group_type))) {
2306                 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2307                 return NT_STATUS_UNSUCCESSFUL;
2308         }
2309
2310         if (group_type == SID_NAME_DOM_GRP) {
2311                 NTSTATUS result = rpc_del_groupmem(pipe_hnd, mem_ctx,
2312                                                    &group_sid, argv[1]);
2313
2314                 if (!NT_STATUS_IS_OK(result)) {
2315                         d_fprintf(stderr, "Could not del %s from %s: %s\n",
2316                                  argv[1], argv[0], nt_errstr(result));
2317                 }
2318                 return result;
2319         }
2320
2321         if (group_type == SID_NAME_ALIAS) {
2322                 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx, 
2323                                                    &group_sid, argv[1]);
2324
2325                 if (!NT_STATUS_IS_OK(result)) {
2326                         d_fprintf(stderr, "Could not del %s from %s: %s\n",
2327                                  argv[1], argv[0], nt_errstr(result));
2328                 }
2329                 return result;
2330         }
2331
2332         d_fprintf(stderr, "Can only delete members from global or local groups "
2333                  "which %s is not\n", argv[0]);
2334
2335         return NT_STATUS_UNSUCCESSFUL;
2336 }
2337
2338 static int rpc_group_delmem(int argc, const char **argv)
2339 {
2340         return run_rpc_command(NULL, PI_SAMR, 0,
2341                                rpc_group_delmem_internals,
2342                                argc, argv);
2343 }
2344
2345 /** 
2346  * List groups on a remote RPC server
2347  *
2348  * All parameters are provided by the run_rpc_command function, except for
2349  * argc, argv which are passes through. 
2350  *
2351  * @param domain_sid The domain sid acquired from the remote server
2352  * @param cli A cli_state connected to the server.
2353  * @param mem_ctx Talloc context, destoyed on completion of the function.
2354  * @param argc  Standard main() style argc
2355  * @param argv  Standard main() style argv.  Initial components are already
2356  *              stripped
2357  *
2358  * @return Normal NTSTATUS return.
2359  **/
2360
2361 static NTSTATUS rpc_group_list_internals(const DOM_SID *domain_sid,
2362                                         const char *domain_name, 
2363                                         struct cli_state *cli,
2364                                         struct rpc_pipe_client *pipe_hnd,
2365                                         TALLOC_CTX *mem_ctx,
2366                                         int argc,
2367                                         const char **argv)
2368 {
2369         POLICY_HND connect_pol, domain_pol;
2370         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2371         uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2372         struct acct_info *groups;
2373         BOOL global = False;
2374         BOOL local = False;
2375         BOOL builtin = False;
2376
2377         if (argc == 0) {
2378                 global = True;
2379                 local = True;
2380                 builtin = True;
2381         }
2382
2383         for (i=0; i<argc; i++) {
2384                 if (strequal(argv[i], "global"))
2385                         global = True;
2386
2387                 if (strequal(argv[i], "local"))
2388                         local = True;
2389
2390                 if (strequal(argv[i], "builtin"))
2391                         builtin = True;
2392         }
2393
2394         /* Get sam policy handle */
2395         
2396         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2397                                   &connect_pol);
2398         if (!NT_STATUS_IS_OK(result)) {
2399                 goto done;
2400         }
2401         
2402         /* Get domain policy handle */
2403         
2404         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2405                                       MAXIMUM_ALLOWED_ACCESS,
2406                                       domain_sid, &domain_pol);
2407         if (!NT_STATUS_IS_OK(result)) {
2408                 goto done;
2409         }
2410
2411         /* Query domain groups */
2412         if (opt_long_list_entries)
2413                 d_printf("\nGroup name            Comment"\
2414                          "\n-----------------------------\n");
2415         do {
2416                 SAM_DISPINFO_CTR ctr;
2417                 SAM_DISPINFO_3 info3;
2418                 uint32 max_size;
2419
2420                 ZERO_STRUCT(ctr);
2421                 ZERO_STRUCT(info3);
2422                 ctr.sam.info3 = &info3;
2423
2424                 if (!global) break;
2425
2426                 get_query_dispinfo_params(
2427                         loop_count, &max_entries, &max_size);
2428
2429                 result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol,
2430                                                  &start_idx, 3, &num_entries,
2431                                                  max_entries, max_size, &ctr);
2432
2433                 if (!NT_STATUS_IS_OK(result) &&
2434                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2435                         break;
2436                                                  
2437                 for (i = 0; i < num_entries; i++) {
2438
2439                         fstring group, desc;
2440
2441                         unistr2_to_ascii(group, &(&ctr.sam.info3->str[i])->uni_grp_name, sizeof(group)-1);
2442                         unistr2_to_ascii(desc, &(&ctr.sam.info3->str[i])->uni_grp_desc, sizeof(desc)-1);
2443                         
2444                         if (opt_long_list_entries)
2445                                 printf("%-21.21s %-50.50s\n",
2446                                        group, desc);
2447                         else
2448                                 printf("%s\n", group);
2449                 }
2450         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2451         /* query domain aliases */
2452         start_idx = 0;
2453         do {
2454                 if (!local) break;
2455
2456                 /* The max_size field in cli_samr_enum_als_groups is more like
2457                  * an account_control field with indiviual bits what to
2458                  * retrieve. Set this to 0xffff as NT4 usrmgr.exe does to get
2459                  * everything. I'm too lazy (sorry) to get this through to
2460                  * rpc_parse/ etc.  Volker */
2461
2462                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
2463                                                   &start_idx, 0xffff,
2464                                                   &groups, &num_entries);
2465
2466                 if (!NT_STATUS_IS_OK(result) &&
2467                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2468                         break;
2469                                                  
2470                 for (i = 0; i < num_entries; i++) {
2471
2472                         char *description = NULL;
2473
2474                         if (opt_long_list_entries) {
2475
2476                                 POLICY_HND alias_pol;
2477                                 ALIAS_INFO_CTR ctr;
2478
2479                                 if ((NT_STATUS_IS_OK(rpccli_samr_open_alias(pipe_hnd, mem_ctx,
2480                                                                          &domain_pol,
2481                                                                          0x8,
2482                                                                          groups[i].rid,
2483                                                                          &alias_pol))) &&
2484                                     (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx,
2485                                                                                &alias_pol, 3,
2486                                                                                &ctr))) &&
2487                                     (NT_STATUS_IS_OK(rpccli_samr_close(pipe_hnd, mem_ctx,
2488                                                                     &alias_pol)))) {
2489                                         description = unistr2_tdup(mem_ctx,
2490                                                                    ctr.alias.info3.description.string);
2491                                 }
2492                         }
2493                         
2494                         if (description != NULL) {
2495                                 printf("%-21.21s %-50.50s\n", 
2496                                        groups[i].acct_name,
2497                                        description);
2498                         } else {
2499                                 printf("%s\n", groups[i].acct_name);
2500                         }
2501                 }
2502         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2503         rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
2504         /* Get builtin policy handle */
2505         
2506         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2507                                       MAXIMUM_ALLOWED_ACCESS,
2508                                       &global_sid_Builtin, &domain_pol);
2509         if (!NT_STATUS_IS_OK(result)) {
2510                 goto done;
2511         }
2512         /* query builtin aliases */
2513         start_idx = 0;
2514         do {
2515                 if (!builtin) break;
2516
2517                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
2518                                                   &start_idx, max_entries,
2519                                                   &groups, &num_entries);
2520                                                  
2521                 if (!NT_STATUS_IS_OK(result) &&
2522                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2523                         break;
2524                                                  
2525                 for (i = 0; i < num_entries; i++) {
2526
2527                         char *description = NULL;
2528
2529                         if (opt_long_list_entries) {
2530
2531                                 POLICY_HND alias_pol;
2532                                 ALIAS_INFO_CTR ctr;
2533
2534                                 if ((NT_STATUS_IS_OK(rpccli_samr_open_alias(pipe_hnd, mem_ctx,
2535                                                                          &domain_pol,
2536                                                                          0x8,
2537                                                                          groups[i].rid,
2538                                                                          &alias_pol))) &&
2539                                     (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx,
2540                                                                                &alias_pol, 3,
2541                                                                                &ctr))) &&
2542                                     (NT_STATUS_IS_OK(rpccli_samr_close(pipe_hnd, mem_ctx,
2543                                                                     &alias_pol)))) {
2544                                         description = unistr2_tdup(mem_ctx,
2545                                                                    ctr.alias.info3.description.string);
2546                                 }
2547                         }
2548                         
2549                         if (description != NULL) {
2550                                 printf("%-21.21s %-50.50s\n", 
2551                                        groups[i].acct_name,
2552                                        description);
2553                         } else {
2554                                 printf("%s\n", groups[i].acct_name);
2555                         }
2556                 }
2557         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2558
2559  done:
2560         return result;
2561 }
2562
2563 static int rpc_group_list(int argc, const char **argv)
2564 {
2565         return run_rpc_command(NULL, PI_SAMR, 0,
2566                                rpc_group_list_internals,
2567                                argc, argv);
2568 }
2569
2570 static NTSTATUS rpc_list_group_members(struct rpc_pipe_client *pipe_hnd,
2571                                         TALLOC_CTX *mem_ctx,
2572                                         const char *domain_name,
2573                                         const DOM_SID *domain_sid,
2574                                         POLICY_HND *domain_pol,
2575                                         uint32 rid)
2576 {
2577         NTSTATUS result;
2578         POLICY_HND group_pol;
2579         uint32 num_members, *group_rids, *group_attrs;
2580         uint32 num_names;
2581         char **names;
2582         uint32 *name_types;
2583         int i;
2584
2585         fstring sid_str;
2586         sid_to_string(sid_str, domain_sid);
2587
2588         result = rpccli_samr_open_group(pipe_hnd, mem_ctx, domain_pol,
2589                                      MAXIMUM_ALLOWED_ACCESS,
2590                                      rid, &group_pol);
2591
2592         if (!NT_STATUS_IS_OK(result))
2593                 return result;
2594
2595         result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol,
2596                                          &num_members, &group_rids,
2597                                          &group_attrs);
2598
2599         if (!NT_STATUS_IS_OK(result))
2600                 return result;
2601
2602         while (num_members > 0) {
2603                 int this_time = 512;
2604
2605                 if (num_members < this_time)
2606                         this_time = num_members;
2607
2608                 result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, domain_pol,
2609                                               this_time, group_rids,
2610                                               &num_names, &names, &name_types);
2611
2612                 if (!NT_STATUS_IS_OK(result))
2613                         return result;
2614
2615                 /* We only have users as members, but make the output
2616                    the same as the output of alias members */
2617
2618                 for (i = 0; i < this_time; i++) {
2619
2620                         if (opt_long_list_entries) {
2621                                 printf("%s-%d %s\\%s %d\n", sid_str,
2622                                        group_rids[i], domain_name, names[i],
2623                                        SID_NAME_USER);
2624                         } else {
2625                                 printf("%s\\%s\n", domain_name, names[i]);
2626                         }
2627                 }
2628
2629                 num_members -= this_time;
2630                 group_rids += 512;
2631         }
2632
2633         return NT_STATUS_OK;
2634 }
2635
2636 static NTSTATUS rpc_list_alias_members(struct rpc_pipe_client *pipe_hnd,
2637                                         TALLOC_CTX *mem_ctx,
2638                                         POLICY_HND *domain_pol,
2639                                         uint32 rid)
2640 {
2641         NTSTATUS result;
2642         struct rpc_pipe_client *lsa_pipe;
2643         POLICY_HND alias_pol, lsa_pol;
2644         uint32 num_members;
2645         DOM_SID *alias_sids;
2646         char **domains;
2647         char **names;
2648         uint32 *types;
2649         int i;
2650
2651         result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, domain_pol,
2652                                      MAXIMUM_ALLOWED_ACCESS, rid, &alias_pol);
2653
2654         if (!NT_STATUS_IS_OK(result))
2655                 return result;
2656
2657         result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx, &alias_pol,
2658                                          &num_members, &alias_sids);
2659
2660         if (!NT_STATUS_IS_OK(result)) {
2661                 d_fprintf(stderr, "Couldn't list alias members\n");
2662                 return result;
2663         }
2664
2665         if (num_members == 0) {
2666                 return NT_STATUS_OK;
2667         }
2668
2669         lsa_pipe = cli_rpc_pipe_open_noauth(pipe_hnd->cli, PI_LSARPC, &result);
2670         if (!lsa_pipe) {
2671                 d_fprintf(stderr, "Couldn't open LSA pipe. Error was %s\n",
2672                         nt_errstr(result) );
2673                 return result;
2674         }
2675
2676         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
2677                                      SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
2678
2679         if (!NT_STATUS_IS_OK(result)) {
2680                 d_fprintf(stderr, "Couldn't open LSA policy handle\n");
2681                 cli_rpc_pipe_close(lsa_pipe);
2682                 return result;
2683         }
2684
2685         result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol, num_members,
2686                                      alias_sids, 
2687                                      &domains, &names, &types);
2688
2689         if (!NT_STATUS_IS_OK(result) &&
2690             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2691                 d_fprintf(stderr, "Couldn't lookup SIDs\n");
2692                 cli_rpc_pipe_close(lsa_pipe);
2693                 return result;
2694         }
2695
2696         for (i = 0; i < num_members; i++) {
2697                 fstring sid_str;
2698                 sid_to_string(sid_str, &alias_sids[i]);
2699
2700                 if (opt_long_list_entries) {
2701                         printf("%s %s\\%s %d\n", sid_str, 
2702                                domains[i] ? domains[i] : "*unknown*", 
2703                                names[i] ? names[i] : "*unknown*", types[i]);
2704                 } else {
2705                         if (domains[i])
2706                                 printf("%s\\%s\n", domains[i], names[i]);
2707                         else
2708                                 printf("%s\n", sid_str);
2709                 }
2710         }
2711
2712         cli_rpc_pipe_close(lsa_pipe);
2713         return NT_STATUS_OK;
2714 }
2715  
2716 static NTSTATUS rpc_group_members_internals(const DOM_SID *domain_sid,
2717                                         const char *domain_name, 
2718                                         struct cli_state *cli,
2719                                         struct rpc_pipe_client *pipe_hnd,
2720                                         TALLOC_CTX *mem_ctx,
2721                                         int argc,
2722                                         const char **argv)
2723 {
2724         NTSTATUS result;
2725         POLICY_HND connect_pol, domain_pol;
2726         uint32 num_rids, *rids, *rid_types;
2727
2728         /* Get sam policy handle */
2729         
2730         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2731                                   &connect_pol);
2732
2733         if (!NT_STATUS_IS_OK(result))
2734                 return result;
2735         
2736         /* Get domain policy handle */
2737         
2738         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2739                                       MAXIMUM_ALLOWED_ACCESS,
2740                                       domain_sid, &domain_pol);
2741
2742         if (!NT_STATUS_IS_OK(result))
2743                 return result;
2744
2745         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2746                                        1, argv, &num_rids, &rids, &rid_types);
2747
2748         if (!NT_STATUS_IS_OK(result)) {
2749
2750                 /* Ok, did not find it in the global sam, try with builtin */
2751
2752                 DOM_SID sid_Builtin;
2753
2754                 rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
2755
2756                 string_to_sid(&sid_Builtin, "S-1-5-32");                
2757
2758                 result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2759                                               MAXIMUM_ALLOWED_ACCESS,
2760                                               &sid_Builtin, &domain_pol);
2761
2762                 if (!NT_STATUS_IS_OK(result)) {
2763                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2764                         return result;
2765                 }
2766
2767                 result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2768                                                1, argv, &num_rids,
2769                                                &rids, &rid_types);
2770
2771                 if (!NT_STATUS_IS_OK(result)) {
2772                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2773                         return result;
2774                 }
2775         }
2776
2777         if (num_rids != 1) {
2778                 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2779                 return result;
2780         }
2781
2782         if (rid_types[0] == SID_NAME_DOM_GRP) {
2783                 return rpc_list_group_members(pipe_hnd, mem_ctx, domain_name,
2784                                               domain_sid, &domain_pol,
2785                                               rids[0]);
2786         }
2787
2788         if (rid_types[0] == SID_NAME_ALIAS) {
2789                 return rpc_list_alias_members(pipe_hnd, mem_ctx, &domain_pol,
2790                                               rids[0]);
2791         }
2792
2793         return NT_STATUS_NO_SUCH_GROUP;
2794 }
2795
2796 static int rpc_group_members(int argc, const char **argv)
2797 {
2798         if (argc != 1) {
2799                 return rpc_group_usage(argc, argv);
2800         }
2801
2802         return run_rpc_command(NULL, PI_SAMR, 0,
2803                                rpc_group_members_internals,
2804                                argc, argv);
2805 }
2806
2807 static NTSTATUS rpc_group_rename_internals(const DOM_SID *domain_sid,
2808                                         const char *domain_name, 
2809                                         struct cli_state *cli,
2810                                         struct rpc_pipe_client *pipe_hnd,
2811                                         TALLOC_CTX *mem_ctx,
2812                                         int argc,
2813                                         const char **argv)
2814 {
2815         NTSTATUS result;
2816         POLICY_HND connect_pol, domain_pol, group_pol;
2817         uint32 num_rids, *rids, *rid_types;
2818         GROUP_INFO_CTR ctr;
2819
2820         if (argc != 2) {
2821                 d_printf("Usage: 'net rpc group rename group newname'\n");
2822                 return NT_STATUS_UNSUCCESSFUL;
2823         }
2824
2825         /* Get sam policy handle */
2826         
2827         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
2828                                   &connect_pol);
2829
2830         if (!NT_STATUS_IS_OK(result))
2831                 return result;
2832         
2833         /* Get domain policy handle */
2834         
2835         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
2836                                       MAXIMUM_ALLOWED_ACCESS,
2837                                       domain_sid, &domain_pol);
2838
2839         if (!NT_STATUS_IS_OK(result))
2840                 return result;
2841
2842         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
2843                                        1, argv, &num_rids, &rids, &rid_types);
2844
2845         if (num_rids != 1) {
2846                 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2847                 return result;
2848         }
2849
2850         if (rid_types[0] != SID_NAME_DOM_GRP) {
2851                 d_fprintf(stderr, "Can only rename domain groups\n");
2852                 return NT_STATUS_UNSUCCESSFUL;
2853         }
2854
2855         result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
2856                                      MAXIMUM_ALLOWED_ACCESS,
2857                                      rids[0], &group_pol);
2858
2859         if (!NT_STATUS_IS_OK(result))
2860                 return result;
2861
2862         ZERO_STRUCT(ctr);
2863
2864         ctr.switch_value1 = 2;
2865         init_samr_group_info2(&ctr.group.info2, argv[1]);
2866
2867         result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &ctr);
2868
2869         if (!NT_STATUS_IS_OK(result))
2870                 return result;
2871
2872         return NT_STATUS_NO_SUCH_GROUP;
2873 }
2874
2875 static int rpc_group_rename(int argc, const char **argv)
2876 {
2877         if (argc != 2) {
2878                 return rpc_group_usage(argc, argv);
2879         }
2880
2881         return run_rpc_command(NULL, PI_SAMR, 0,
2882                                rpc_group_rename_internals,
2883                                argc, argv);
2884 }
2885
2886 /** 
2887  * 'net rpc group' entrypoint.
2888  * @param argc  Standard main() style argc
2889  * @param argc  Standard main() style argv.  Initial components are already
2890  *              stripped
2891  **/
2892
2893 int net_rpc_group(int argc, const char **argv) 
2894 {
2895         struct functable func[] = {
2896                 {"add", rpc_group_add},
2897                 {"delete", rpc_group_delete},
2898                 {"addmem", rpc_group_addmem},
2899                 {"delmem", rpc_group_delmem},
2900                 {"list", rpc_group_list},
2901                 {"members", rpc_group_members},
2902                 {"rename", rpc_group_rename},
2903                 {NULL, NULL}
2904         };
2905         
2906         if (argc == 0) {
2907                 return run_rpc_command(NULL, PI_SAMR, 0, 
2908                                        rpc_group_list_internals,
2909                                        argc, argv);
2910         }
2911
2912         return net_run_function(argc, argv, func, rpc_group_usage);
2913 }
2914
2915 /****************************************************************************/
2916
2917 static int rpc_share_usage(int argc, const char **argv)
2918 {
2919         return net_help_share(argc, argv);
2920 }
2921
2922 /** 
2923  * Add a share on a remote RPC server
2924  *
2925  * All parameters are provided by the run_rpc_command function, except for
2926  * argc, argv which are passes through. 
2927  *
2928  * @param domain_sid The domain sid acquired from the remote server
2929  * @param cli A cli_state connected to the server.
2930  * @param mem_ctx Talloc context, destoyed on completion of the function.
2931  * @param argc  Standard main() style argc
2932  * @param argv  Standard main() style argv.  Initial components are already
2933  *              stripped
2934  *
2935  * @return Normal NTSTATUS return.
2936  **/
2937 static NTSTATUS rpc_share_add_internals(const DOM_SID *domain_sid,
2938                                         const char *domain_name, 
2939                                         struct cli_state *cli,
2940                                         struct rpc_pipe_client *pipe_hnd,
2941                                         TALLOC_CTX *mem_ctx,int argc,
2942                                         const char **argv)
2943 {
2944         WERROR result;
2945         char *sharename=talloc_strdup(mem_ctx, argv[0]);
2946         char *path;
2947         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
2948         uint32 num_users=0, perms=0;
2949         char *password=NULL; /* don't allow a share password */
2950         uint32 level = 2;
2951
2952         path = strchr(sharename, '=');
2953         if (!path)
2954                 return NT_STATUS_UNSUCCESSFUL;
2955         *path++ = '\0';
2956
2957         result = rpccli_srvsvc_net_share_add(pipe_hnd, mem_ctx, sharename, type,
2958                                           opt_comment, perms, opt_maxusers,
2959                                           num_users, path, password, 
2960                                           level, NULL);
2961         return werror_to_ntstatus(result);
2962 }
2963
2964 static int rpc_share_add(int argc, const char **argv)
2965 {
2966         if ((argc < 1) || !strchr(argv[0], '=')) {
2967                 DEBUG(1,("Sharename or path not specified on add\n"));
2968                 return rpc_share_usage(argc, argv);
2969         }
2970         return run_rpc_command(NULL, PI_SRVSVC, 0, 
2971                                rpc_share_add_internals,
2972                                argc, argv);
2973 }
2974
2975 /** 
2976  * Delete a share on a remote RPC server
2977  *
2978  * All parameters are provided by the run_rpc_command function, except for
2979  * argc, argv which are passes through. 
2980  *
2981  * @param domain_sid The domain sid acquired from the remote server
2982  * @param cli A cli_state connected to the server.
2983  * @param mem_ctx Talloc context, destoyed on completion of the function.
2984  * @param argc  Standard main() style argc
2985  * @param argv  Standard main() style argv.  Initial components are already
2986  *              stripped
2987  *
2988  * @return Normal NTSTATUS return.
2989  **/
2990 static NTSTATUS rpc_share_del_internals(const DOM_SID *domain_sid,
2991                                         const char *domain_name, 
2992                                         struct cli_state *cli,
2993                                         struct rpc_pipe_client *pipe_hnd,
2994                                         TALLOC_CTX *mem_ctx,
2995                                         int argc,
2996                                         const char **argv)
2997 {
2998         WERROR result;
2999
3000         result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
3001         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3002 }
3003
3004 /** 
3005  * Delete a share on a remote RPC server
3006  *
3007  * @param domain_sid The domain sid acquired from the remote server
3008  * @param argc  Standard main() style argc
3009  * @param argv  Standard main() style argv.  Initial components are already
3010  *              stripped
3011  *
3012  * @return A shell status integer (0 for success)
3013  **/
3014 static int rpc_share_delete(int argc, const char **argv)
3015 {
3016         if (argc < 1) {
3017                 DEBUG(1,("Sharename not specified on delete\n"));
3018                 return rpc_share_usage(argc, argv);
3019         }
3020         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3021                                rpc_share_del_internals,
3022                                argc, argv);
3023 }
3024
3025 /**
3026  * Formatted print of share info
3027  *
3028  * @param info1  pointer to SRV_SHARE_INFO_1 to format
3029  **/
3030  
3031 static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
3032 {
3033         fstring netname = "", remark = "";
3034
3035         rpcstr_pull_unistr2_fstring(netname, &info1->info_1_str.uni_netname);
3036         rpcstr_pull_unistr2_fstring(remark, &info1->info_1_str.uni_remark);
3037
3038         if (opt_long_list_entries) {
3039                 d_printf("%-12s %-8.8s %-50s\n",
3040                          netname, share_type[info1->info_1.type], remark);
3041         } else {
3042                 d_printf("%s\n", netname);
3043         }
3044
3045 }
3046
3047 static WERROR get_share_info(struct rpc_pipe_client *pipe_hnd,
3048                                 TALLOC_CTX *mem_ctx, 
3049                                 uint32 level,
3050                                 int argc,
3051                                 const char **argv, 
3052                                 SRV_SHARE_INFO_CTR *ctr)
3053 {
3054         WERROR result;
3055         SRV_SHARE_INFO info;
3056
3057         /* no specific share requested, enumerate all */
3058         if (argc == 0) {
3059
3060                 ENUM_HND hnd;
3061                 uint32 preferred_len = 0xffffffff;
3062
3063                 init_enum_hnd(&hnd, 0);
3064
3065                 return rpccli_srvsvc_net_share_enum(pipe_hnd, mem_ctx, level, ctr, 
3066                                                  preferred_len, &hnd);
3067         }
3068
3069         /* request just one share */
3070         result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, argv[0], level, &info);
3071
3072         if (!W_ERROR_IS_OK(result))
3073                 goto done;
3074
3075         /* construct ctr */
3076         ZERO_STRUCTP(ctr);
3077
3078         ctr->info_level = ctr->switch_value = level;
3079         ctr->ptr_share_info = ctr->ptr_entries = 1;
3080         ctr->num_entries = ctr->num_entries2 = 1;
3081
3082         switch (level) {
3083         case 1:
3084         {
3085                 char *s;
3086                 SRV_SHARE_INFO_1 *info1;
3087                 
3088                 ctr->share.info1 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_1, 1);
3089                 info1 = ctr->share.info1;
3090                                 
3091                 memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
3092
3093                 /* Copy pointer crap */
3094
3095                 memcpy(&info1->info_1, &info.share.info1.info_1, sizeof(SH_INFO_1));
3096
3097                 /* Duplicate strings */
3098
3099                 s = unistr2_tdup(mem_ctx, &info.share.info1.info_1_str.uni_netname);
3100                 if (s)
3101                         init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
3102
3103                 s = unistr2_tdup(mem_ctx, &info.share.info1.info_1_str.uni_remark);
3104                 if (s)
3105                         init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);
3106         }
3107         case 2:
3108         {
3109                 char *s;
3110                 SRV_SHARE_INFO_2 *info2;
3111                 
3112                 ctr->share.info2 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_2, 1);
3113                 info2 = ctr->share.info2;
3114                                 
3115                 memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
3116
3117                 /* Copy pointer crap */
3118
3119                 memcpy(&info2->info_2, &info.share.info2.info_2, sizeof(SH_INFO_2));
3120
3121                 /* Duplicate strings */
3122
3123                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_netname);
3124                 if (s)
3125                         init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);
3126
3127                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_remark);
3128                 if (s)
3129                         init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);
3130
3131                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_path);
3132                 if (s)
3133                         init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);
3134
3135                 s = unistr2_tdup(mem_ctx, &info.share.info2.info_2_str.uni_passwd);
3136                 if (s)
3137                         init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
3138         }
3139         case 502:
3140         {
3141                 char *s;
3142                 SRV_SHARE_INFO_502 *info502;
3143
3144                 ctr->share.info502 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_502, 1);
3145                 info502 = ctr->share.info502;
3146
3147                 memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502));
3148
3149                 /* Copy pointer crap */
3150
3151                 memcpy(&info502->info_502, &info.share.info502.info_502, sizeof(SH_INFO_502));
3152
3153                 /* Duplicate strings */
3154
3155                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_netname);
3156                 if (s)
3157                         init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE);
3158
3159                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_remark);
3160                 if (s)
3161                         init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE);
3162
3163                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_path);
3164                 if (s)
3165                         init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE);
3166
3167                 s = unistr2_tdup(mem_ctx, &info.share.info502.info_502_str.uni_passwd);
3168                 if (s)
3169                         init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE);
3170
3171                 info502->info_502_str.sd = dup_sec_desc(mem_ctx, info.share.info502.info_502_str.sd);
3172                                 
3173         }
3174
3175         } /* switch */
3176
3177 done:
3178         return result;
3179 }
3180
3181 /** 
3182  * List shares on a remote RPC server
3183  *
3184  * All parameters are provided by the run_rpc_command function, except for
3185  * argc, argv which are passes through. 
3186  *
3187  * @param domain_sid The domain sid acquired from the remote server
3188  * @param cli A cli_state connected to the server.
3189  * @param mem_ctx Talloc context, destoyed on completion of the function.
3190  * @param argc  Standard main() style argc
3191  * @param argv  Standard main() style argv.  Initial components are already
3192  *              stripped
3193  *
3194  * @return Normal NTSTATUS return.
3195  **/
3196
3197 static NTSTATUS rpc_share_list_internals(const DOM_SID *domain_sid,
3198                                         const char *domain_name, 
3199                                         struct cli_state *cli,
3200                                         struct rpc_pipe_client *pipe_hnd,
3201                                         TALLOC_CTX *mem_ctx,
3202                                         int argc,
3203                                         const char **argv)
3204 {
3205         SRV_SHARE_INFO_CTR ctr;
3206         WERROR result;
3207         uint32 i, level = 1;
3208
3209         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr);
3210         if (!W_ERROR_IS_OK(result))
3211                 goto done;
3212
3213         /* Display results */
3214
3215         if (opt_long_list_entries) {
3216                 d_printf(
3217         "\nEnumerating shared resources (exports) on remote server:\n\n"\
3218         "\nShare name   Type     Description\n"\
3219         "----------   ----     -----------\n");
3220         }
3221         for (i = 0; i < ctr.num_entries; i++)
3222                 display_share_info_1(&ctr.share.info1[i]);
3223  done:
3224         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3225 }
3226
3227 /*** 
3228  * 'net rpc share list' entrypoint.
3229  * @param argc  Standard main() style argc
3230  * @param argv  Standard main() style argv.  Initial components are already
3231  *              stripped
3232  **/
3233 static int rpc_share_list(int argc, const char **argv)
3234 {
3235         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_list_internals, argc, argv);
3236 }
3237
3238 static BOOL check_share_availability(struct cli_state *cli, const char *netname)
3239 {
3240         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
3241                 d_printf("skipping   [%s]: not a file share.\n", netname);
3242                 return False;
3243         }
3244
3245         if (!cli_tdis(cli)) 
3246                 return False;
3247
3248         return True;
3249 }
3250
3251 static BOOL check_share_sanity(struct cli_state *cli, fstring netname, uint32 type)
3252 {
3253         /* only support disk shares */
3254         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3255                 printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
3256                 return False;
3257         }
3258
3259         /* skip builtin shares */
3260         /* FIXME: should print$ be added too ? */
3261         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") || 
3262             strequal(netname,"global")) 
3263                 return False;
3264
3265         if (opt_exclude && in_list(netname, opt_exclude, False)) {
3266                 printf("excluding  [%s]\n", netname);
3267                 return False;
3268         }
3269
3270         return check_share_availability(cli, netname);
3271 }
3272
3273 /** 
3274  * Migrate shares from a remote RPC server to the local RPC srever
3275  *
3276  * All parameters are provided by the run_rpc_command function, except for
3277  * argc, argv which are passes through. 
3278  *
3279  * @param domain_sid The domain sid acquired from the remote server
3280  * @param cli A cli_state connected to the server.
3281  * @param mem_ctx Talloc context, destoyed on completion of the function.
3282  * @param argc  Standard main() style argc
3283  * @param argv  Standard main() style argv.  Initial components are already
3284  *              stripped
3285  *
3286  * @return Normal NTSTATUS return.
3287  **/
3288
3289 static NTSTATUS rpc_share_migrate_shares_internals(const DOM_SID *domain_sid,
3290                                                 const char *domain_name, 
3291                                                 struct cli_state *cli,
3292                                                 struct rpc_pipe_client *pipe_hnd,
3293                                                 TALLOC_CTX *mem_ctx, 
3294                                                 int argc,
3295                                                 const char **argv)
3296 {
3297         WERROR result;
3298         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3299         SRV_SHARE_INFO_CTR ctr_src;
3300         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3301         char *password = NULL; /* don't allow a share password */
3302         uint32 i;
3303         struct rpc_pipe_client *srvsvc_pipe = NULL;
3304         struct cli_state *cli_dst = NULL;
3305         uint32 level = 502; /* includes secdesc */
3306
3307         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3308         if (!W_ERROR_IS_OK(result))
3309                 goto done;
3310
3311         /* connect destination PI_SRVSVC */
3312         nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
3313         if (!NT_STATUS_IS_OK(nt_status))
3314                 return nt_status;
3315
3316
3317         for (i = 0; i < ctr_src.num_entries; i++) {
3318
3319                 fstring netname = "", remark = "", path = "";
3320                 /* reset error-code */
3321                 nt_status = NT_STATUS_UNSUCCESSFUL;
3322
3323                 rpcstr_pull_unistr2_fstring(
3324                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3325                 rpcstr_pull_unistr2_fstring(
3326                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
3327                 rpcstr_pull_unistr2_fstring(
3328                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
3329
3330                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3331                         continue;
3332
3333                 /* finally add the share on the dst server */ 
3334
3335                 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n", 
3336                         netname, path, remark);
3337
3338                 result = rpccli_srvsvc_net_share_add(srvsvc_pipe, mem_ctx, netname, type, remark,
3339                                                   ctr_src.share.info502[i].info_502.perms,
3340                                                   ctr_src.share.info502[i].info_502.max_uses,
3341                                                   ctr_src.share.info502[i].info_502.num_uses,
3342                                                   path, password, level, 
3343                                                   NULL);
3344         
3345                 if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
3346                         printf("           [%s] does already exist\n", netname);
3347                         continue;
3348                 }
3349
3350                 if (!W_ERROR_IS_OK(result)) {
3351                         printf("cannot add share: %s\n", dos_errstr(result));
3352                         goto done;
3353                 }
3354
3355         }
3356
3357         nt_status = NT_STATUS_OK;
3358
3359 done:
3360         if (cli_dst) {
3361                 cli_shutdown(cli_dst);
3362         }
3363
3364         return nt_status;
3365
3366 }
3367
3368 /** 
3369  * Migrate shares from a rpc-server to another
3370  *
3371  * @param argc  Standard main() style argc
3372  * @param argv  Standard main() style argv.  Initial components are already
3373  *              stripped
3374  *
3375  * @return A shell status integer (0 for success)
3376  **/
3377 static int rpc_share_migrate_shares(int argc, const char **argv)
3378 {
3379
3380         if (!opt_host) {
3381                 printf("no server to migrate\n");
3382                 return -1;
3383         }
3384
3385         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3386                                rpc_share_migrate_shares_internals,
3387                                argc, argv);
3388 }
3389
3390 /**
3391  * Copy a file/dir 
3392  *
3393  * @param f     file_info
3394  * @param mask  current search mask
3395  * @param state arg-pointer
3396  *
3397  **/
3398 static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state)
3399 {
3400         static NTSTATUS nt_status;
3401         static struct copy_clistate *local_state;
3402         static fstring filename, new_mask;
3403         fstring dir;
3404         char *old_dir;
3405
3406         local_state = (struct copy_clistate *)state;
3407         nt_status = NT_STATUS_UNSUCCESSFUL;
3408
3409         if (strequal(f->name, ".") || strequal(f->name, ".."))
3410                 return;
3411
3412         DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3413
3414         /* DIRECTORY */
3415         if (f->mode & aDIR) {
3416
3417                 DEBUG(3,("got dir: %s\n", f->name));
3418
3419                 fstrcpy(dir, local_state->cwd);
3420                 fstrcat(dir, "\\");
3421                 fstrcat(dir, f->name);
3422
3423                 switch (net_mode_share)
3424                 {
3425                 case NET_MODE_SHARE_MIGRATE:
3426                         /* create that directory */
3427                         nt_status = net_copy_file(local_state->mem_ctx,
3428                                                   local_state->cli_share_src,
3429                                                   local_state->cli_share_dst,
3430                                                   dir, dir,
3431                                                   opt_acls? True : False,
3432                                                   opt_attrs? True : False,
3433                                                   opt_timestamps? True : False,
3434                                                   False);
3435                         break;
3436                 default:
3437                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3438                         return;
3439                 }
3440
3441                 if (!NT_STATUS_IS_OK(nt_status)) 
3442                         printf("could not handle dir %s: %s\n", 
3443                                 dir, nt_errstr(nt_status));
3444
3445                 /* search below that directory */
3446                 fstrcpy(new_mask, dir);
3447                 fstrcat(new_mask, "\\*");
3448
3449                 old_dir = local_state->cwd;
3450                 local_state->cwd = dir;
3451                 if (!sync_files(local_state, new_mask))
3452                         printf("could not handle files\n");
3453                 local_state->cwd = old_dir;
3454
3455                 return;
3456         }
3457
3458
3459         /* FILE */
3460         fstrcpy(filename, local_state->cwd);
3461         fstrcat(filename, "\\");
3462         fstrcat(filename, f->name);
3463
3464         DEBUG(3,("got file: %s\n", filename));
3465
3466         switch (net_mode_share)
3467         {
3468         case NET_MODE_SHARE_MIGRATE:
3469                 nt_status = net_copy_file(local_state->mem_ctx, 
3470                                           local_state->cli_share_src, 
3471                                           local_state->cli_share_dst, 
3472                                           filename, filename, 
3473                                           opt_acls? True : False, 
3474                                           opt_attrs? True : False,
3475                                           opt_timestamps? True: False,
3476                                           True);
3477                 break;
3478         default:
3479                 d_fprintf(stderr, "Unsupported file mode %d\n", net_mode_share);
3480                 return;
3481         }
3482
3483         if (!NT_STATUS_IS_OK(nt_status)) 
3484                 printf("could not handle file %s: %s\n", 
3485                         filename, nt_errstr(nt_status));
3486
3487 }
3488
3489 /**
3490  * sync files, can be called recursivly to list files 
3491  * and then call copy_fn for each file 
3492  *
3493  * @param cp_clistate   pointer to the copy_clistate we work with
3494  * @param mask          the current search mask
3495  *
3496  * @return              Boolean result
3497  **/
3498 BOOL sync_files(struct copy_clistate *cp_clistate, pstring mask)
3499 {
3500
3501         DEBUG(3,("calling cli_list with mask: %s\n", mask));
3502
3503         if (cli_list(cp_clistate->cli_share_src, mask, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3504                 d_fprintf(stderr, "listing %s failed with error: %s\n", 
3505                         mask, cli_errstr(cp_clistate->cli_share_src));
3506                 return False;
3507         }
3508
3509         return True;
3510 }
3511
3512
3513 /**
3514  * Set the top level directory permissions before we do any further copies.
3515  * Should set up ACL inheritance.
3516  **/
3517
3518 BOOL copy_top_level_perms(struct copy_clistate *cp_clistate, 
3519                                 const char *sharename)
3520 {
3521         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3522
3523         switch (net_mode_share) {
3524         case NET_MODE_SHARE_MIGRATE:
3525                 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3526                 nt_status = net_copy_fileattr(cp_clistate->mem_ctx,
3527                                                 cp_clistate->cli_share_src, 
3528                                                 cp_clistate->cli_share_dst,
3529                                                 "\\", "\\",
3530                                                 opt_acls? True : False, 
3531                                                 opt_attrs? True : False,
3532                                                 opt_timestamps? True: False,
3533                                                 False);
3534                 break;
3535         default:
3536                 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3537                 break;
3538         }
3539
3540         if (!NT_STATUS_IS_OK(nt_status))  {
3541                 printf("Could handle directory attributes for top level directory of share %s. Error %s\n", 
3542                         sharename, nt_errstr(nt_status));
3543                 return False;
3544         }
3545
3546         return True;
3547 }
3548
3549 /** 
3550  * Sync all files inside a remote share to another share (over smb)
3551  *
3552  * All parameters are provided by the run_rpc_command function, except for
3553  * argc, argv which are passes through. 
3554  *
3555  * @param domain_sid The domain sid acquired from the remote server
3556  * @param cli A cli_state connected to the server.
3557  * @param mem_ctx Talloc context, destoyed on completion of the function.
3558  * @param argc  Standard main() style argc
3559  * @param argv  Standard main() style argv.  Initial components are already
3560  *              stripped
3561  *
3562  * @return Normal NTSTATUS return.
3563  **/
3564
3565 static NTSTATUS rpc_share_migrate_files_internals(const DOM_SID *domain_sid,
3566                                                 const char *domain_name, 
3567                                                 struct cli_state *cli,
3568                                                 struct rpc_pipe_client *pipe_hnd,
3569                                                 TALLOC_CTX *mem_ctx,
3570                                                 int argc,
3571                                                 const char **argv)
3572 {
3573         WERROR result;
3574         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3575         SRV_SHARE_INFO_CTR ctr_src;
3576         uint32 i;
3577         uint32 level = 502;
3578         struct copy_clistate cp_clistate;
3579         BOOL got_src_share = False;
3580         BOOL got_dst_share = False;
3581         pstring mask = "\\*";
3582         char *dst = NULL;
3583
3584         dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1");
3585
3586         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3587
3588         if (!W_ERROR_IS_OK(result))
3589                 goto done;
3590
3591         for (i = 0; i < ctr_src.num_entries; i++) {
3592
3593                 fstring netname = "";
3594
3595                 rpcstr_pull_unistr2_fstring(
3596                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3597
3598                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3599                         continue;
3600
3601                 /* one might not want to mirror whole discs :) */
3602                 if (strequal(netname, "print$") || netname[1] == '$') {
3603                         d_printf("skipping   [%s]: builtin/hidden share\n", netname);
3604                         continue;
3605                 }
3606
3607                 switch (net_mode_share)
3608                 {
3609                 case NET_MODE_SHARE_MIGRATE:
3610                         printf("syncing");
3611                         break;
3612                 default:
3613                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3614                         break;
3615                 }
3616                 printf("    [%s] files and directories %s ACLs, %s DOS Attributes %s\n", 
3617                         netname, 
3618                         opt_acls ? "including" : "without", 
3619                         opt_attrs ? "including" : "without",
3620                         opt_timestamps ? "(preserving timestamps)" : "");
3621
3622                 cp_clistate.mem_ctx = mem_ctx;
3623                 cp_clistate.cli_share_src = NULL;
3624                 cp_clistate.cli_share_dst = NULL;
3625                 cp_clistate.cwd = NULL;
3626                 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3627
3628                 /* open share source */
3629                 nt_status = connect_to_service(&cp_clistate.cli_share_src,
3630                                                &cli->dest_ip, cli->desthost,
3631                                                netname, "A:");
3632                 if (!NT_STATUS_IS_OK(nt_status))
3633                         goto done;
3634
3635                 got_src_share = True;
3636
3637                 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3638                         /* open share destination */
3639                         nt_status = connect_to_service(&cp_clistate.cli_share_dst,
3640                                                        NULL, dst, netname, "A:");
3641                         if (!NT_STATUS_IS_OK(nt_status))
3642                                 goto done;
3643
3644                         got_dst_share = True;
3645                 }
3646
3647                 if (!copy_top_level_perms(&cp_clistate, netname)) {
3648                         d_fprintf(stderr, "Could not handle the top level directory permissions for the share: %s\n", netname);
3649                         nt_status = NT_STATUS_UNSUCCESSFUL;
3650                         goto done;
3651                 }
3652
3653                 if (!sync_files(&cp_clistate, mask)) {
3654                         d_fprintf(stderr, "could not handle files for share: %s\n", netname);
3655                         nt_status = NT_STATUS_UNSUCCESSFUL;
3656                         goto done;
3657                 }
3658         }
3659
3660         nt_status = NT_STATUS_OK;
3661
3662 done:
3663
3664         if (got_src_share)
3665                 cli_shutdown(cp_clistate.cli_share_src);
3666
3667         if (got_dst_share)
3668                 cli_shutdown(cp_clistate.cli_share_dst);
3669
3670         return nt_status;
3671
3672 }
3673
3674 static int rpc_share_migrate_files(int argc, const char **argv)
3675 {
3676
3677         if (!opt_host) {
3678                 printf("no server to migrate\n");
3679                 return -1;
3680         }
3681
3682         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3683                                rpc_share_migrate_files_internals,
3684                                argc, argv);
3685 }
3686
3687 /** 
3688  * Migrate share-ACLs from a remote RPC server to the local RPC srever
3689  *
3690  * All parameters are provided by the run_rpc_command function, except for
3691  * argc, argv which are passes through. 
3692  *
3693  * @param domain_sid The domain sid acquired from the remote server
3694  * @param cli A cli_state connected to the server.
3695  * @param mem_ctx Talloc context, destoyed on completion of the function.
3696  * @param argc  Standard main() style argc
3697  * @param argv  Standard main() style argv.  Initial components are already
3698  *              stripped
3699  *
3700  * @return Normal NTSTATUS return.
3701  **/
3702
3703 static NTSTATUS rpc_share_migrate_security_internals(const DOM_SID *domain_sid,
3704                                                 const char *domain_name, 
3705                                                 struct cli_state *cli,
3706                                                 struct rpc_pipe_client *pipe_hnd,
3707                                                 TALLOC_CTX *mem_ctx, 
3708                                                 int argc,
3709                                                 const char **argv)
3710 {
3711         WERROR result;
3712         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3713         SRV_SHARE_INFO_CTR ctr_src;
3714         SRV_SHARE_INFO info;
3715         uint32 i;
3716         struct rpc_pipe_client *srvsvc_pipe = NULL;
3717         struct cli_state *cli_dst = NULL;
3718         uint32 level = 502; /* includes secdesc */
3719
3720         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3721
3722         if (!W_ERROR_IS_OK(result))
3723                 goto done;
3724
3725         /* connect destination PI_SRVSVC */
3726         nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
3727         if (!NT_STATUS_IS_OK(nt_status))
3728                 return nt_status;
3729
3730
3731         for (i = 0; i < ctr_src.num_entries; i++) {
3732
3733                 fstring netname = "", remark = "", path = "";
3734                 /* reset error-code */
3735                 nt_status = NT_STATUS_UNSUCCESSFUL;
3736
3737                 rpcstr_pull_unistr2_fstring(
3738                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3739                 rpcstr_pull_unistr2_fstring(
3740                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
3741                 rpcstr_pull_unistr2_fstring(
3742                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
3743
3744                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3745                         continue;
3746
3747                 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n", 
3748                         netname, path, remark);
3749
3750                 if (opt_verbose)
3751                         display_sec_desc(ctr_src.share.info502[i].info_502_str.sd);
3752
3753                 /* init info */
3754                 ZERO_STRUCT(info);
3755
3756                 info.switch_value = level;
3757                 info.ptr_share_ctr = 1;
3758
3759                 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3760                 info.share.info502 = ctr_src.share.info502[i];
3761
3762                 /* finally modify the share on the dst server */
3763                 result = rpccli_srvsvc_net_share_set_info(srvsvc_pipe, mem_ctx, netname, level, &info);
3764         
3765                 if (!W_ERROR_IS_OK(result)) {
3766                         printf("cannot set share-acl: %s\n", dos_errstr(result));
3767                         goto done;
3768                 }
3769
3770         }
3771
3772         nt_status = NT_STATUS_OK;
3773
3774 done:
3775         if (cli_dst) {
3776                 cli_shutdown(cli_dst);
3777         }
3778
3779         return nt_status;
3780
3781 }
3782
3783 /** 
3784  * Migrate share-acls from a rpc-server to another
3785  *
3786  * @param argc  Standard main() style argc
3787  * @param argv  Standard main() style argv.  Initial components are already
3788  *              stripped
3789  *
3790  * @return A shell status integer (0 for success)
3791  **/
3792 static int rpc_share_migrate_security(int argc, const char **argv)
3793 {
3794
3795         if (!opt_host) {
3796                 printf("no server to migrate\n");
3797                 return -1;
3798         }
3799
3800         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3801                                rpc_share_migrate_security_internals,
3802                                argc, argv);
3803 }
3804
3805 /** 
3806  * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3807  * from one server to another
3808  *
3809  * @param argc  Standard main() style argc
3810  * @param argv  Standard main() style argv.  Initial components are already
3811  *              stripped
3812  *
3813  * @return A shell status integer (0 for success)
3814  *
3815  **/
3816 static int rpc_share_migrate_all(int argc, const char **argv)
3817 {
3818         int ret;
3819
3820         if (!opt_host) {
3821                 printf("no server to migrate\n");
3822                 return -1;
3823         }
3824
3825         /* order is important. we don't want to be locked out by the share-acl
3826          * before copying files - gd */
3827         
3828         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
3829         if (ret)
3830                 return ret;
3831
3832         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
3833         if (ret)
3834                 return ret;
3835         
3836         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_security_internals, argc, argv);
3837 }
3838
3839
3840 /** 
3841  * 'net rpc share migrate' entrypoint.
3842  * @param argc  Standard main() style argc
3843  * @param argv  Standard main() style argv.  Initial components are already
3844  *              stripped
3845  **/
3846 static int rpc_share_migrate(int argc, const char **argv)
3847 {
3848
3849         struct functable func[] = {
3850                 {"all",         rpc_share_migrate_all},
3851                 {"files",       rpc_share_migrate_files},
3852                 {"help",        rpc_share_usage},
3853                 {"security",    rpc_share_migrate_security},
3854                 {"shares",      rpc_share_migrate_shares},
3855                 {NULL, NULL}
3856         };
3857
3858         net_mode_share = NET_MODE_SHARE_MIGRATE;
3859
3860         return net_run_function(argc, argv, func, rpc_share_usage);
3861 }
3862
3863 struct full_alias {
3864         DOM_SID sid;
3865         uint32 num_members;
3866         DOM_SID *members;
3867 };
3868
3869 static int num_server_aliases;
3870 static struct full_alias *server_aliases;
3871
3872 /*
3873  * Add an alias to the static list.
3874  */
3875 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
3876 {
3877         if (server_aliases == NULL)
3878                 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
3879
3880         server_aliases[num_server_aliases] = *alias;
3881         num_server_aliases += 1;
3882 }
3883
3884 /*
3885  * For a specific domain on the server, fetch all the aliases
3886  * and their members. Add all of them to the server_aliases.
3887  */
3888
3889 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
3890                                         TALLOC_CTX *mem_ctx,
3891                                         POLICY_HND *connect_pol,
3892                                         const DOM_SID *domain_sid)
3893 {
3894         uint32 start_idx, max_entries, num_entries, i;
3895         struct acct_info *groups;
3896         NTSTATUS result;
3897         POLICY_HND domain_pol;
3898
3899         /* Get domain policy handle */
3900         
3901         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, connect_pol,
3902                                       MAXIMUM_ALLOWED_ACCESS,
3903                                       domain_sid, &domain_pol);
3904         if (!NT_STATUS_IS_OK(result))
3905                 return result;
3906
3907         start_idx = 0;
3908         max_entries = 250;
3909
3910         do {
3911                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
3912                                                   &start_idx, max_entries,
3913                                                   &groups, &num_entries);
3914
3915                 for (i = 0; i < num_entries; i++) {
3916
3917                         POLICY_HND alias_pol;
3918                         struct full_alias alias;
3919                         DOM_SID *members;
3920                         int j;
3921
3922                         result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
3923                                                      MAXIMUM_ALLOWED_ACCESS,
3924                                                      groups[i].rid,
3925                                                      &alias_pol);
3926                         if (!NT_STATUS_IS_OK(result))
3927                                 goto done;
3928
3929                         result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx,
3930                                                          &alias_pol,
3931                                                          &alias.num_members,
3932                                                          &members);
3933                         if (!NT_STATUS_IS_OK(result))
3934                                 goto done;
3935
3936                         result = rpccli_samr_close(pipe_hnd, mem_ctx, &alias_pol);
3937                         if (!NT_STATUS_IS_OK(result))
3938                                 goto done;
3939
3940                         alias.members = NULL;
3941
3942                         if (alias.num_members > 0) {
3943                                 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
3944
3945                                 for (j = 0; j < alias.num_members; j++)
3946                                         sid_copy(&alias.members[j],
3947                                                  &members[j]);
3948                         }
3949
3950                         sid_copy(&alias.sid, domain_sid);
3951                         sid_append_rid(&alias.sid, groups[i].rid);
3952
3953                         push_alias(mem_ctx, &alias);
3954                 }
3955         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3956
3957         result = NT_STATUS_OK;
3958
3959  done:
3960         rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
3961
3962         return result;
3963 }
3964
3965 /*
3966  * Dump server_aliases as names for debugging purposes.
3967  */
3968
3969 static NTSTATUS rpc_aliaslist_dump(const DOM_SID *domain_sid,
3970                                 const char *domain_name,
3971                                 struct cli_state *cli,
3972                                 struct rpc_pipe_client *pipe_hnd,
3973                                 TALLOC_CTX *mem_ctx, 
3974                                 int argc,
3975                                 const char **argv)
3976 {
3977         int i;
3978         NTSTATUS result;
3979         POLICY_HND lsa_pol;
3980
3981         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
3982                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
3983                                      &lsa_pol);
3984         if (!NT_STATUS_IS_OK(result))
3985                 return result;
3986
3987         for (i=0; i<num_server_aliases; i++) {
3988                 char **names;
3989                 char **domains;
3990                 uint32 *types;
3991                 int j;
3992
3993                 struct full_alias *alias = &server_aliases[i];
3994
3995                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
3996                                              &alias->sid,
3997                                              &domains, &names, &types);
3998                 if (!NT_STATUS_IS_OK(result))
3999                         continue;
4000
4001                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4002
4003                 if (alias->num_members == 0) {
4004                         DEBUG(1, ("\n"));
4005                         continue;
4006                 }
4007
4008                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4009                                              alias->num_members,
4010                                              alias->members,
4011                                              &domains, &names, &types);
4012
4013                 if (!NT_STATUS_IS_OK(result) &&
4014                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4015                         continue;
4016
4017                 for (j=0; j<alias->num_members; j++)
4018                         DEBUG(1, ("%s\\%s (%d); ",
4019                                   domains[j] ? domains[j] : "*unknown*", 
4020                                   names[j] ? names[j] : "*unknown*",types[j]));
4021                 DEBUG(1, ("\n"));
4022         }
4023
4024         rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
4025
4026         return NT_STATUS_OK;
4027 }
4028
4029 /*
4030  * Fetch a list of all server aliases and their members into
4031  * server_aliases.
4032  */
4033
4034 static NTSTATUS rpc_aliaslist_internals(const DOM_SID *domain_sid,
4035                                         const char *domain_name,
4036                                         struct cli_state *cli,
4037                                         struct rpc_pipe_client *pipe_hnd,
4038                                         TALLOC_CTX *mem_ctx, 
4039                                         int argc,
4040                                         const char **argv)
4041 {
4042         NTSTATUS result;
4043         POLICY_HND connect_pol;
4044
4045         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
4046                                   &connect_pol);
4047
4048         if (!NT_STATUS_IS_OK(result))
4049                 goto done;
4050         
4051         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4052                                           &global_sid_Builtin);
4053
4054         if (!NT_STATUS_IS_OK(result))
4055                 goto done;
4056         
4057         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4058                                           domain_sid);
4059
4060         rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
4061  done:
4062         return result;
4063 }
4064
4065 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
4066 {
4067         token->num_sids = 4;
4068
4069         token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4);
4070
4071         token->user_sids[0] = *user_sid;
4072         sid_copy(&token->user_sids[1], &global_sid_World);
4073         sid_copy(&token->user_sids[2], &global_sid_Network);
4074         sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
4075 }
4076
4077 static void free_user_token(NT_USER_TOKEN *token)
4078 {
4079         SAFE_FREE(token->user_sids);
4080 }
4081
4082 static BOOL is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
4083 {
4084         int i;
4085
4086         for (i=0; i<token->num_sids; i++) {
4087                 if (sid_compare(sid, &token->user_sids[i]) == 0)
4088                         return True;
4089         }
4090         return False;
4091 }
4092
4093 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
4094 {
4095         if (is_sid_in_token(token, sid))
4096                 return;
4097
4098         token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
4099         if (!token->user_sids) {
4100                 return;
4101         }
4102
4103         sid_copy(&token->user_sids[token->num_sids], sid);
4104
4105         token->num_sids += 1;
4106 }
4107
4108 struct user_token {
4109         fstring name;
4110         NT_USER_TOKEN token;
4111 };
4112
4113 static void dump_user_token(struct user_token *token)
4114 {
4115         int i;
4116
4117         d_printf("%s\n", token->name);
4118
4119         for (i=0; i<token->token.num_sids; i++) {
4120                 d_printf(" %s\n", sid_string_static(&token->token.user_sids[i]));
4121         }
4122 }
4123
4124 static BOOL is_alias_member(DOM_SID *sid, struct full_alias *alias)
4125 {
4126         int i;
4127
4128         for (i=0; i<alias->num_members; i++) {
4129                 if (sid_compare(sid, &alias->members[i]) == 0)
4130                         return True;
4131         }
4132
4133         return False;
4134 }
4135
4136 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
4137 {
4138         int i;
4139
4140         for (i=0; i<num_server_aliases; i++) {
4141                 if (is_alias_member(&sid, &server_aliases[i]))
4142                         add_sid_to_token(token, &server_aliases[i].sid);
4143         }
4144 }
4145
4146 /*
4147  * We got a user token with all the SIDs we can know about without asking the
4148  * server directly. These are the user and domain group sids. All of these can
4149  * be members of aliases. So scan the list of aliases for each of the SIDs and
4150  * add them to the token.
4151  */
4152
4153 static void collect_alias_memberships(NT_USER_TOKEN *token)
4154 {
4155         int num_global_sids = token->num_sids;
4156         int i;
4157
4158         for (i=0; i<num_global_sids; i++) {
4159                 collect_sid_memberships(token, token->user_sids[i]);
4160         }
4161 }
4162
4163 static BOOL get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
4164 {
4165         struct winbindd_request request;
4166         struct winbindd_response response;
4167         fstring full_name;
4168         NSS_STATUS result;
4169
4170         DOM_SID user_sid;
4171
4172         int i;
4173
4174         fstr_sprintf(full_name, "%s%c%s",
4175                      domain, *lp_winbind_separator(), user);
4176
4177         /* First let's find out the user sid */
4178
4179         ZERO_STRUCT(request);
4180         ZERO_STRUCT(response);
4181
4182         fstrcpy(request.data.name.dom_name, domain);
4183         fstrcpy(request.data.name.name, user);
4184
4185         result = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response);
4186
4187         if (result != NSS_STATUS_SUCCESS) {
4188                 DEBUG(1, ("winbind could not find %s\n", full_name));
4189                 return False;
4190         }
4191
4192         if (response.data.sid.type != SID_NAME_USER) {
4193                 DEBUG(1, ("%s is not a user\n", full_name));
4194                 return False;
4195         }
4196
4197         string_to_sid(&user_sid, response.data.sid.sid);
4198
4199         init_user_token(token, &user_sid);
4200
4201         /* And now the groups winbind knows about */
4202
4203         ZERO_STRUCT(response);
4204
4205         fstrcpy(request.data.username, full_name);
4206
4207         result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
4208
4209         if (result != NSS_STATUS_SUCCESS) {
4210                 DEBUG(1, ("winbind could not get groups of %s\n", full_name));
4211                 return False;
4212         }
4213
4214         for (i = 0; i < response.data.num_entries; i++) {
4215                 gid_t gid = ((gid_t *)response.extra_data.data)[i];
4216                 DOM_SID sid;
4217
4218                 struct winbindd_request sidrequest;
4219                 struct winbindd_response sidresponse;
4220
4221                 ZERO_STRUCT(sidrequest);
4222                 ZERO_STRUCT(sidresponse);
4223
4224                 sidrequest.data.gid = gid;
4225
4226                 result = winbindd_request_response(WINBINDD_GID_TO_SID,
4227                                           &sidrequest, &sidresponse);
4228
4229                 if (result != NSS_STATUS_SUCCESS) {
4230                         DEBUG(1, ("winbind could not find SID of gid %d\n",
4231                                   gid));
4232                         return False;
4233                 }
4234
4235                 DEBUG(3, (" %s\n", sidresponse.data.sid.sid));
4236
4237                 string_to_sid(&sid, sidresponse.data.sid.sid);
4238                 add_sid_to_token(token, &sid);
4239         }
4240
4241         SAFE_FREE(response.extra_data.data);
4242
4243         return True;
4244 }
4245         
4246 /**
4247  * Get a list of all user tokens we want to look at
4248  **/
4249
4250 static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens)
4251 {
4252         struct winbindd_request request;
4253         struct winbindd_response response;
4254         const char *extra_data;
4255         fstring name;
4256         int i;
4257         struct user_token *result;
4258
4259         if (lp_winbind_use_default_domain() &&
4260             (opt_target_workgroup == NULL)) {
4261                 d_fprintf(stderr, "winbind use default domain = yes set, "
4262                          "please specify a workgroup\n");
4263                 return False;
4264         }
4265
4266         /* Send request to winbind daemon */
4267
4268         ZERO_STRUCT(request);
4269         ZERO_STRUCT(response);
4270         
4271         if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
4272             NSS_STATUS_SUCCESS)
4273                 return False;
4274
4275         /* Look through extra data */
4276
4277         if (!response.extra_data.data)
4278                 return False;
4279
4280         extra_data = (const char *)response.extra_data.data;
4281         *num_tokens = 0;
4282
4283         while(next_token(&extra_data, name, ",", sizeof(fstring))) {
4284                 *num_tokens += 1;
4285         }
4286
4287         result = SMB_MALLOC_ARRAY(struct user_token, *num_tokens);
4288
4289         if (result == NULL) {
4290                 DEBUG(1, ("Could not malloc sid array\n"));
4291                 return False;
4292         }
4293
4294         extra_data = (const char *)response.extra_data.data;
4295         i=0;
4296
4297         while(next_token(&extra_data, name, ",", sizeof(fstring))) {
4298
4299                 fstring domain, user;
4300                 char *p;
4301
4302                 fstrcpy(result[i].name, name);
4303
4304                 p = strchr(name, *lp_winbind_separator());
4305
4306                 DEBUG(3, ("%s\n", name));
4307
4308                 if (p == NULL) {
4309                         fstrcpy(domain, opt_target_workgroup);
4310                         fstrcpy(user, name);
4311                 } else {
4312                         *p++ = '\0';
4313                         fstrcpy(domain, name);
4314                         strupper_m(domain);
4315                         fstrcpy(user, p);
4316                 }
4317
4318                 get_user_sids(domain, user, &(result[i].token));
4319                 i+=1;
4320         }
4321         
4322         SAFE_FREE(response.extra_data.data);
4323
4324         *user_tokens = result;
4325
4326         return True;
4327 }
4328
4329 static BOOL get_user_tokens_from_file(FILE *f,
4330                                       int *num_tokens,
4331                                       struct user_token **tokens)
4332 {
4333         struct user_token *token = NULL;
4334
4335         while (!feof(f)) {
4336                 fstring line;
4337
4338                 if (fgets(line, sizeof(line)-1, f) == NULL) {
4339                         return True;
4340                 }
4341
4342                 if (line[strlen(line)-1] == '\n')
4343                         line[strlen(line)-1] = '\0';
4344
4345                 if (line[0] == ' ') {
4346                         /* We have a SID */
4347
4348                         DOM_SID sid;
4349                         string_to_sid(&sid, &line[1]);
4350
4351                         if (token == NULL) {
4352                                 DEBUG(0, ("File does not begin with username"));
4353                                 return False;
4354                         }
4355
4356                         add_sid_to_token(&token->token, &sid);
4357                         continue;
4358                 }
4359
4360                 /* And a new user... */
4361
4362                 *num_tokens += 1;
4363                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4364                 if (*tokens == NULL) {
4365                         DEBUG(0, ("Could not realloc tokens\n"));
4366                         return False;
4367                 }
4368
4369                 token = &((*tokens)[*num_tokens-1]);
4370
4371                 fstrcpy(token->name, line);
4372                 token->token.num_sids = 0;
4373                 token->token.user_sids = NULL;
4374                 continue;
4375         }
4376         
4377         return False;
4378 }
4379
4380
4381 /*
4382  * Show the list of all users that have access to a share
4383  */
4384
4385 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4386                         TALLOC_CTX *mem_ctx,
4387                         const char *netname,
4388                         int num_tokens,
4389                         struct user_token *tokens)
4390 {
4391         int fnum;
4392         SEC_DESC *share_sd = NULL;
4393         SEC_DESC *root_sd = NULL;
4394         struct cli_state *cli = pipe_hnd->cli;
4395         int i;
4396         SRV_SHARE_INFO info;
4397         WERROR result;
4398         uint16 cnum;
4399
4400         result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, netname,
4401                                                502, &info);
4402
4403         if (!W_ERROR_IS_OK(result)) {
4404                 DEBUG(1, ("Coult not query secdesc for share %s\n",
4405                           netname));
4406                 return;
4407         }
4408
4409         share_sd = info.share.info502.info_502_str.sd;
4410         if (share_sd == NULL) {
4411                 DEBUG(1, ("Got no secdesc for share %s\n",
4412                           netname));
4413         }
4414
4415         cnum = cli->cnum;
4416
4417         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
4418                 return;
4419         }
4420
4421         fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
4422
4423         if (fnum != -1) {
4424                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4425         }
4426
4427         for (i=0; i<num_tokens; i++) {
4428                 uint32 acc_granted;
4429                 NTSTATUS status;
4430
4431                 if (share_sd != NULL) {
4432                         if (!se_access_check(share_sd, &tokens[i].token,
4433                                              1, &acc_granted, &status)) {
4434                                 DEBUG(1, ("Could not check share_sd for "
4435                                           "user %s\n",
4436                                           tokens[i].name));
4437                                 continue;
4438                         }
4439
4440                         if (!NT_STATUS_IS_OK(status))
4441                                 continue;
4442                 }
4443
4444                 if (root_sd == NULL) {
4445                         d_printf(" %s\n", tokens[i].name);
4446                         continue;
4447                 }
4448
4449                 if (!se_access_check(root_sd, &tokens[i].token,
4450                                      1, &acc_granted, &status)) {
4451                         DEBUG(1, ("Could not check root_sd for user %s\n",
4452                                   tokens[i].name));
4453                         continue;
4454                 }
4455
4456                 if (!NT_STATUS_IS_OK(status))
4457                         continue;
4458
4459                 d_printf(" %s\n", tokens[i].name);
4460         }
4461
4462         if (fnum != -1)
4463                 cli_close(cli, fnum);
4464         cli_tdis(cli);
4465         cli->cnum = cnum;
4466         
4467         return;
4468 }
4469
4470 struct share_list {
4471         int num_shares;
4472         char **shares;
4473 };
4474
4475 static void collect_share(const char *name, uint32 m,
4476                           const char *comment, void *state)
4477 {
4478         struct share_list *share_list = (struct share_list *)state;
4479
4480         if (m != STYPE_DISKTREE)
4481                 return;
4482
4483         share_list->num_shares += 1;
4484         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4485         if (!share_list->shares) {
4486                 share_list->num_shares = 0;
4487                 return;
4488         }
4489         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4490 }
4491
4492 static void rpc_share_userlist_usage(void)
4493 {
4494         return;
4495 }
4496         
4497 /** 
4498  * List shares on a remote RPC server, including the security descriptors
4499  *
4500  * All parameters are provided by the run_rpc_command function, except for
4501  * argc, argv which are passes through. 
4502  *
4503  * @param domain_sid The domain sid acquired from the remote server
4504  * @param cli A cli_state connected to the server.
4505  * @param mem_ctx Talloc context, destoyed on completion of the function.
4506  * @param argc  Standard main() style argc
4507  * @param argv  Standard main() style argv.  Initial components are already
4508  *              stripped
4509  *
4510  * @return Normal NTSTATUS return.
4511  **/
4512
4513 static NTSTATUS rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
4514                                                 const char *domain_name,
4515                                                 struct cli_state *cli,
4516                                                 struct rpc_pipe_client *pipe_hnd,
4517                                                 TALLOC_CTX *mem_ctx,
4518                                                 int argc,
4519                                                 const char **argv)
4520 {
4521         int ret;
4522         BOOL r;
4523         ENUM_HND hnd;
4524         uint32 i;
4525         FILE *f;
4526
4527         struct user_token *tokens = NULL;
4528         int num_tokens = 0;
4529
4530         struct share_list share_list;
4531
4532         if (argc > 1) {
4533                 rpc_share_userlist_usage();
4534                 return NT_STATUS_UNSUCCESSFUL;
4535         }
4536
4537         if (argc == 0) {
4538                 f = stdin;
4539         } else {
4540                 f = fopen(argv[0], "r");
4541         }
4542
4543         if (f == NULL) {
4544                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4545                 return NT_STATUS_UNSUCCESSFUL;
4546         }
4547
4548         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4549
4550         if (f != stdin)
4551                 fclose(f);
4552
4553         if (!r) {
4554                 DEBUG(0, ("Could not read users from file\n"));
4555                 return NT_STATUS_UNSUCCESSFUL;
4556         }
4557
4558         for (i=0; i<num_tokens; i++)
4559                 collect_alias_memberships(&tokens[i].token);
4560
4561         init_enum_hnd(&hnd, 0);
4562
4563         share_list.num_shares = 0;
4564         share_list.shares = NULL;
4565
4566         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4567
4568         if (ret == -1) {
4569                 DEBUG(0, ("Error returning browse list: %s\n",
4570                           cli_errstr(cli)));
4571                 goto done;
4572         }
4573
4574         for (i = 0; i < share_list.num_shares; i++) {
4575                 char *netname = share_list.shares[i];
4576
4577                 if (netname[strlen(netname)-1] == '$')
4578                         continue;
4579
4580                 d_printf("%s\n", netname);
4581
4582                 show_userlist(pipe_hnd, mem_ctx, netname,
4583                               num_tokens, tokens);
4584         }
4585  done:
4586         for (i=0; i<num_tokens; i++) {
4587                 free_user_token(&tokens[i].token);
4588         }
4589         SAFE_FREE(tokens);
4590         SAFE_FREE(share_list.shares);
4591
4592         return NT_STATUS_OK;
4593 }
4594
4595 static int rpc_share_allowedusers(int argc, const char **argv)
4596 {
4597         int result;
4598
4599         result = run_rpc_command(NULL, PI_SAMR, 0,
4600                                  rpc_aliaslist_internals,
4601                                  argc, argv);
4602         if (result != 0)
4603                 return result;
4604
4605         result = run_rpc_command(NULL, PI_LSARPC, 0,
4606                                  rpc_aliaslist_dump,
4607                                  argc, argv);
4608         if (result != 0)
4609                 return result;
4610
4611         return run_rpc_command(NULL, PI_SRVSVC, 0,
4612                                rpc_share_allowedusers_internals,
4613                                argc, argv);
4614 }
4615
4616 int net_usersidlist(int argc, const char **argv)
4617 {
4618         int num_tokens = 0;
4619         struct user_token *tokens = NULL;
4620         int i;
4621
4622         if (argc != 0) {
4623                 net_usersidlist_usage(argc, argv);
4624                 return 0;
4625         }
4626
4627         if (!get_user_tokens(&num_tokens, &tokens)) {
4628                 DEBUG(0, ("Could not get the user/sid list\n"));
4629                 return 0;
4630         }
4631
4632         for (i=0; i<num_tokens; i++) {
4633                 dump_user_token(&tokens[i]);
4634                 free_user_token(&tokens[i].token);
4635         }
4636
4637         SAFE_FREE(tokens);
4638         return 1;
4639 }
4640
4641 int net_usersidlist_usage(int argc, const char **argv)
4642 {
4643         d_printf("net usersidlist\n"
4644                  "\tprints out a list of all users the running winbind knows\n"
4645                  "\tabout, together with all their SIDs. This is used as\n"
4646                  "\tinput to the 'net rpc share allowedusers' command.\n\n");
4647
4648         net_common_flags_usage(argc, argv);
4649         return -1;
4650 }
4651
4652 /** 
4653  * 'net rpc share' entrypoint.
4654  * @param argc  Standard main() style argc
4655  * @param argv  Standard main() style argv.  Initial components are already
4656  *              stripped
4657  **/
4658
4659 int net_rpc_share(int argc, const char **argv) 
4660 {
4661         struct functable func[] = {
4662                 {"add", rpc_share_add},
4663                 {"delete", rpc_share_delete},
4664                 {"allowedusers", rpc_share_allowedusers},
4665                 {"migrate", rpc_share_migrate},
4666                 {"list", rpc_share_list},
4667                 {NULL, NULL}
4668         };
4669
4670         if (argc == 0)
4671                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
4672                                        rpc_share_list_internals,
4673                                        argc, argv);
4674
4675         return net_run_function(argc, argv, func, rpc_share_usage);
4676 }
4677
4678 static NTSTATUS rpc_sh_share_list(TALLOC_CTX *mem_ctx,
4679                                   struct rpc_sh_ctx *ctx,
4680                                   struct rpc_pipe_client *pipe_hnd,
4681                                   int argc, const char **argv)
4682 {
4683         return rpc_share_list_internals(ctx->domain_sid, ctx->domain_name,
4684                                         ctx->cli, pipe_hnd, mem_ctx,
4685                                         argc, argv);
4686 }
4687
4688 static NTSTATUS rpc_sh_share_add(TALLOC_CTX *mem_ctx,
4689                                  struct rpc_sh_ctx *ctx,
4690                                  struct rpc_pipe_client *pipe_hnd,
4691                                  int argc, const char **argv)
4692 {
4693         WERROR result;
4694
4695         if ((argc < 2) || (argc > 3)) {
4696                 d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
4697                           ctx->whoami);
4698                 return NT_STATUS_INVALID_PARAMETER;
4699         }
4700
4701         result = rpccli_srvsvc_net_share_add(
4702                 pipe_hnd, mem_ctx, argv[0], STYPE_DISKTREE,
4703                 (argc == 3) ? argv[2] : "",
4704                 0, 0, 0, argv[1], NULL, 2, NULL);
4705                                              
4706         return werror_to_ntstatus(result);
4707 }
4708
4709 static NTSTATUS rpc_sh_share_delete(TALLOC_CTX *mem_ctx,
4710                                     struct rpc_sh_ctx *ctx,
4711                                     struct rpc_pipe_client *pipe_hnd,
4712                                     int argc, const char **argv)
4713 {
4714         WERROR result;
4715
4716         if (argc != 1) {
4717                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
4718                 return NT_STATUS_INVALID_PARAMETER;
4719         }
4720
4721         result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
4722         return werror_to_ntstatus(result);
4723 }
4724
4725 static NTSTATUS rpc_sh_share_info(TALLOC_CTX *mem_ctx,
4726                                   struct rpc_sh_ctx *ctx,
4727                                   struct rpc_pipe_client *pipe_hnd,
4728                                   int argc, const char **argv)
4729 {
4730         SRV_SHARE_INFO info;
4731         SRV_SHARE_INFO_2 *info2 = &info.share.info2;
4732         WERROR result;
4733
4734         if (argc != 1) {
4735                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
4736                 return NT_STATUS_INVALID_PARAMETER;
4737         }
4738
4739         result = rpccli_srvsvc_net_share_get_info(
4740                 pipe_hnd, mem_ctx, argv[0], 2, &info);
4741         if (!W_ERROR_IS_OK(result)) {
4742                 goto done;
4743         }
4744
4745         d_printf("Name:     %s\n",
4746                  rpcstr_pull_unistr2_talloc(mem_ctx,
4747                                             &info2->info_2_str.uni_netname));
4748         d_printf("Comment:  %s\n",
4749                  rpcstr_pull_unistr2_talloc(mem_ctx,
4750                                             &info2->info_2_str.uni_remark));
4751         
4752         d_printf("Path:     %s\n",
4753                  rpcstr_pull_unistr2_talloc(mem_ctx,
4754                                             &info2->info_2_str.uni_path));
4755         d_printf("Password: %s\n",
4756                  rpcstr_pull_unistr2_talloc(mem_ctx,
4757                                             &info2->info_2_str.uni_passwd));
4758
4759  done:
4760         return werror_to_ntstatus(result);
4761 }
4762
4763 struct rpc_sh_cmd *net_rpc_share_cmds(TALLOC_CTX *mem_ctx,
4764                                       struct rpc_sh_ctx *ctx)
4765 {
4766         static struct rpc_sh_cmd cmds[] = {
4767
4768         { "list", NULL, PI_SRVSVC, rpc_sh_share_list,
4769           "List available shares" },
4770
4771         { "add", NULL, PI_SRVSVC, rpc_sh_share_add,
4772           "Add a share" },
4773
4774         { "delete", NULL, PI_SRVSVC, rpc_sh_share_delete,
4775           "Delete a share" },
4776
4777         { "info", NULL, PI_SRVSVC, rpc_sh_share_info,
4778           "Get information about a share" },
4779
4780         { NULL, NULL, 0, NULL, NULL }
4781         };
4782
4783         return cmds;
4784 };
4785
4786 /****************************************************************************/
4787
4788 static int rpc_file_usage(int argc, const char **argv)
4789 {
4790         return net_help_file(argc, argv);
4791 }
4792
4793 /** 
4794  * Close a file on a remote RPC server
4795  *
4796  * All parameters are provided by the run_rpc_command function, except for
4797  * argc, argv which are passes through. 
4798  *
4799  * @param domain_sid The domain sid acquired from the remote server
4800  * @param cli A cli_state connected to the server.
4801  * @param mem_ctx Talloc context, destoyed on completion of the function.
4802  * @param argc  Standard main() style argc
4803  * @param argv  Standard main() style argv.  Initial components are already
4804  *              stripped
4805  *
4806  * @return Normal NTSTATUS return.
4807  **/
4808 static NTSTATUS rpc_file_close_internals(const DOM_SID *domain_sid,
4809                                         const char *domain_name, 
4810                                         struct cli_state *cli,
4811                                         struct rpc_pipe_client *pipe_hnd,
4812                                         TALLOC_CTX *mem_ctx,
4813                                         int argc,
4814                                         const char **argv)
4815 {
4816         WERROR result;
4817         result = rpccli_srvsvc_net_file_close(pipe_hnd, mem_ctx, atoi(argv[0]));
4818         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
4819 }
4820
4821 /** 
4822  * Close a file on a remote RPC server
4823  *
4824  * @param argc  Standard main() style argc
4825  * @param argv  Standard main() style argv.  Initial components are already
4826  *              stripped
4827  *
4828  * @return A shell status integer (0 for success)
4829  **/
4830 static int rpc_file_close(int argc, const char **argv)
4831 {
4832         if (argc < 1) {
4833                 DEBUG(1, ("No fileid given on close\n"));
4834                 return(rpc_file_usage(argc, argv));
4835         }
4836
4837         return run_rpc_command(NULL, PI_SRVSVC, 0, 
4838                                rpc_file_close_internals,
4839                                argc, argv);
4840 }
4841
4842 /** 
4843  * Formatted print of open file info 
4844  *
4845  * @param info3  FILE_INFO_3 contents
4846  * @param str3   strings for FILE_INFO_3
4847  **/
4848
4849 static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
4850 {
4851         fstring user = "", path = "";
4852
4853         rpcstr_pull_unistr2_fstring(user, &str3->uni_user_name);
4854         rpcstr_pull_unistr2_fstring(path, &str3->uni_path_name);
4855
4856         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
4857                  info3->id, user, info3->perms, info3->num_locks, path);
4858 }
4859
4860 /** 
4861  * List open files on a remote RPC server
4862  *
4863  * All parameters are provided by the run_rpc_command function, except for
4864  * argc, argv which are passes through. 
4865  *
4866  * @param domain_sid The domain sid acquired from the remote server
4867  * @param cli A cli_state connected to the server.
4868  * @param mem_ctx Talloc context, destoyed on completion of the function.
4869  * @param argc  Standard main() style argc
4870  * @param argv  Standard main() style argv.  Initial components are already
4871  *              stripped
4872  *
4873  * @return Normal NTSTATUS return.
4874  **/
4875
4876 static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
4877                                         const char *domain_name, 
4878                                         struct cli_state *cli,
4879                                         struct rpc_pipe_client *pipe_hnd,
4880                                         TALLOC_CTX *mem_ctx,
4881                                         int argc,
4882                                         const char **argv)
4883 {
4884         SRV_FILE_INFO_CTR ctr;
4885         WERROR result;
4886         ENUM_HND hnd;
4887         uint32 preferred_len = 0xffffffff, i;
4888         const char *username=NULL;
4889
4890         init_enum_hnd(&hnd, 0);
4891
4892         /* if argc > 0, must be user command */
4893         if (argc > 0)
4894                 username = smb_xstrdup(argv[0]);
4895                 
4896         result = rpccli_srvsvc_net_file_enum(pipe_hnd,
4897                                         mem_ctx, 3, username, &ctr, preferred_len, &hnd);
4898
4899         if (!W_ERROR_IS_OK(result))
4900                 goto done;
4901
4902         /* Display results */
4903
4904         d_printf(
4905                  "\nEnumerating open files on remote server:\n\n"\
4906                  "\nFileId  Opened by            Perms  Locks  Path"\
4907                  "\n------  ---------            -----  -----  ---- \n");
4908         for (i = 0; i < ctr.num_entries; i++)
4909                 display_file_info_3(&ctr.file.info3[i].info_3, 
4910                                     &ctr.file.info3[i].info_3_str);
4911  done:
4912         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
4913 }
4914
4915 /** 
4916  * List files for a user on a remote RPC server
4917  *
4918  * @param argc  Standard main() style argc
4919  * @param argv  Standard main() style argv.  Initial components are already
4920  *              stripped
4921  *
4922  * @return A shell status integer (0 for success)
4923  **/
4924
4925 static int rpc_file_user(int argc, const char **argv)
4926 {
4927         if (argc < 1) {
4928                 DEBUG(1, ("No username given\n"));
4929                 return(rpc_file_usage(argc, argv));
4930         }
4931
4932         return run_rpc_command(NULL, PI_SRVSVC, 0, 
4933                                rpc_file_list_internals,
4934                                argc, argv);
4935 }
4936
4937 /** 
4938  * 'net rpc file' entrypoint.
4939  * @param argc  Standard main() style argc
4940  * @param argv  Standard main() style argv.  Initial components are already
4941  *              stripped
4942  **/
4943
4944 int net_rpc_file(int argc, const char **argv) 
4945 {
4946         struct functable func[] = {
4947                 {"close", rpc_file_close},
4948                 {"user", rpc_file_user},
4949 #if 0
4950                 {"info", rpc_file_info},
4951 #endif
4952                 {NULL, NULL}
4953         };
4954
4955         if (argc == 0)
4956                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
4957                                        rpc_file_list_internals,
4958                                        argc, argv);
4959
4960         return net_run_function(argc, argv, func, rpc_file_usage);
4961 }
4962
4963 /** 
4964  * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
4965  *
4966  * All parameters are provided by the run_rpc_command function, except for
4967  * argc, argv which are passed through. 
4968  *
4969  * @param domain_sid The domain sid aquired from the remote server
4970  * @param cli A cli_state connected to the server.
4971  * @param mem_ctx Talloc context, destoyed on compleation of the function.
4972  * @param argc  Standard main() style argc
4973  * @param argv  Standard main() style argv.  Initial components are already
4974  *              stripped
4975  *
4976  * @return Normal NTSTATUS return.
4977  **/
4978
4979 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, 
4980                                         const char *domain_name, 
4981                                         struct cli_state *cli, 
4982                                         struct rpc_pipe_client *pipe_hnd,
4983                                         TALLOC_CTX *mem_ctx, 
4984                                         int argc,
4985                                         const char **argv) 
4986 {
4987         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4988         
4989         result = rpccli_shutdown_abort(pipe_hnd, mem_ctx);
4990         
4991         if (NT_STATUS_IS_OK(result)) {
4992                 d_printf("\nShutdown successfully aborted\n");
4993                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
4994         } else
4995                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
4996         
4997         return result;
4998 }
4999
5000 /** 
5001  * ABORT the shutdown of a remote RPC Server,  over winreg pipe
5002  *
5003  * All parameters are provided by the run_rpc_command function, except for
5004  * argc, argv which are passed through. 
5005  *
5006  * @param domain_sid The domain sid aquired from the remote server
5007  * @param cli A cli_state connected to the server.
5008  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5009  * @param argc  Standard main() style argc
5010  * @param argv  Standard main() style argv.  Initial components are already
5011  *              stripped
5012  *
5013  * @return Normal NTSTATUS return.
5014  **/
5015
5016 static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid, 
5017                                                 const char *domain_name, 
5018                                                 struct cli_state *cli, 
5019                                                 struct rpc_pipe_client *pipe_hnd,
5020                                                 TALLOC_CTX *mem_ctx, 
5021                                                 int argc,
5022                                                 const char **argv) 
5023 {
5024         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5025         
5026         result = werror_to_ntstatus(rpccli_reg_abort_shutdown(pipe_hnd, mem_ctx));
5027         
5028         if (NT_STATUS_IS_OK(result)) {
5029                 d_printf("\nShutdown successfully aborted\n");
5030                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5031         } else
5032                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5033         
5034         return result;
5035 }
5036
5037 /** 
5038  * ABORT the Shut down of a remote RPC server
5039  *
5040  * @param argc  Standard main() style argc
5041  * @param argv  Standard main() style argv.  Initial components are already
5042  *              stripped
5043  *
5044  * @return A shell status integer (0 for success)
5045  **/
5046
5047 static int rpc_shutdown_abort(int argc, const char **argv) 
5048 {
5049         int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0, 
5050                                  rpc_shutdown_abort_internals,
5051                                  argc, argv);
5052
5053         if (rc == 0)
5054                 return rc;
5055
5056         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5057
5058         return run_rpc_command(NULL, PI_WINREG, 0, 
5059                                rpc_reg_shutdown_abort_internals,
5060                                argc, argv);
5061 }
5062
5063 /** 
5064  * Shut down a remote RPC Server via initshutdown pipe
5065  *
5066  * All parameters are provided by the run_rpc_command function, except for
5067  * argc, argv which are passes through. 
5068  *
5069  * @param domain_sid The domain sid aquired from the remote server
5070  * @param cli A cli_state connected to the server.
5071  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5072  * @param argc  Standard main() style argc
5073  * @param argc  Standard main() style argv.  Initial components are already
5074  *              stripped
5075  *
5076  * @return Normal NTSTATUS return.
5077  **/
5078
5079 static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid, 
5080                                                 const char *domain_name, 
5081                                                 struct cli_state *cli, 
5082                                                 struct rpc_pipe_client *pipe_hnd,
5083                                                 TALLOC_CTX *mem_ctx, 
5084                                                 int argc,
5085                                                 const char **argv) 
5086 {
5087         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5088         const char *msg = "This machine will be shutdown shortly";
5089         uint32 timeout = 20;
5090
5091         if (opt_comment) {
5092                 msg = opt_comment;
5093         }
5094         if (opt_timeout) {
5095                 timeout = opt_timeout;
5096         }
5097
5098         /* create an entry */
5099         result = rpccli_shutdown_init(pipe_hnd, mem_ctx, msg, timeout, opt_reboot, 
5100                                    opt_force);
5101
5102         if (NT_STATUS_IS_OK(result)) {
5103                 d_printf("\nShutdown of remote machine succeeded\n");
5104                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5105         } else {
5106                 DEBUG(1,("Shutdown of remote machine failed!\n"));
5107         }
5108         return result;
5109 }
5110
5111 /** 
5112  * Shut down a remote RPC Server via winreg pipe
5113  *
5114  * All parameters are provided by the run_rpc_command function, except for
5115  * argc, argv which are passes through. 
5116  *
5117  * @param domain_sid The domain sid aquired from the remote server
5118  * @param cli A cli_state connected to the server.
5119  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5120  * @param argc  Standard main() style argc
5121  * @param argc  Standard main() style argv.  Initial components are already
5122  *              stripped
5123  *
5124  * @return Normal NTSTATUS return.
5125  **/
5126
5127 static NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid, 
5128                                                 const char *domain_name, 
5129                                                 struct cli_state *cli, 
5130                                                 struct rpc_pipe_client *pipe_hnd,
5131                                                 TALLOC_CTX *mem_ctx, 
5132                                                 int argc,
5133                                                 const char **argv) 
5134 {
5135         WERROR result;
5136         const char *msg = "This machine will be shutdown shortly";
5137         uint32 timeout = 20;
5138 #if 0
5139         poptContext pc;
5140         int rc;
5141
5142         struct poptOption long_options[] = {
5143                 {"message",    'm', POPT_ARG_STRING, &msg},
5144                 {"timeout",    't', POPT_ARG_INT,    &timeout},
5145                 {"reboot",     'r', POPT_ARG_NONE,   &reboot},
5146                 {"force",      'f', POPT_ARG_NONE,   &force},
5147                 { 0, 0, 0, 0}
5148         };
5149
5150         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
5151                             POPT_CONTEXT_KEEP_FIRST);
5152
5153         rc = poptGetNextOpt(pc);
5154         
5155         if (rc < -1) {
5156                 /* an error occurred during option processing */
5157                 DEBUG(0, ("%s: %s\n",
5158                           poptBadOption(pc, POPT_BADOPTION_NOALIAS),
5159                           poptStrerror(rc)));
5160                 return NT_STATUS_INVALID_PARAMETER;
5161         }
5162 #endif
5163         if (opt_comment) {
5164                 msg = opt_comment;
5165         }
5166         if (opt_timeout) {
5167                 timeout = opt_timeout;
5168         }
5169
5170         /* create an entry */
5171         result = rpccli_reg_shutdown(pipe_hnd, mem_ctx, msg, timeout, opt_reboot, opt_force);
5172
5173         if (W_ERROR_IS_OK(result)) {
5174                 d_printf("\nShutdown of remote machine succeeded\n");
5175         } else {
5176                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5177                 if (W_ERROR_EQUAL(result,WERR_MACHINE_LOCKED))
5178                         d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5179                 else
5180                         d_fprintf(stderr, "\nresult was: %s\n", dos_errstr(result));
5181         }
5182
5183         return werror_to_ntstatus(result);
5184 }
5185
5186 /** 
5187  * Shut down a remote RPC server
5188  *
5189  * @param argc  Standard main() style argc
5190  * @param argc  Standard main() style argv.  Initial components are already
5191  *              stripped
5192  *
5193  * @return A shell status integer (0 for success)
5194  **/
5195
5196 static int rpc_shutdown(int argc, const char **argv) 
5197 {
5198         int rc = run_rpc_command(NULL, PI_SHUTDOWN, 0, 
5199                                  rpc_init_shutdown_internals,
5200                                  argc, argv);
5201
5202         if (rc) {
5203                 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5204                 rc = run_rpc_command(NULL, PI_WINREG, 0, 
5205                                      rpc_reg_shutdown_internals, argc, argv);
5206         }
5207
5208         return rc;
5209 }
5210
5211 /***************************************************************************
5212   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5213   
5214  ***************************************************************************/
5215
5216 /**
5217  * Add interdomain trust account to the RPC server.
5218  * All parameters (except for argc and argv) are passed by run_rpc_command
5219  * function.
5220  *
5221  * @param domain_sid The domain sid acquired from the server
5222  * @param cli A cli_state connected to the server.
5223  * @param mem_ctx Talloc context, destoyed on completion of the function.
5224  * @param argc  Standard main() style argc
5225  * @param argc  Standard main() style argv.  Initial components are already
5226  *              stripped
5227  *
5228  * @return normal NTSTATUS return code
5229  */
5230
5231 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, 
5232                                                 const char *domain_name, 
5233                                                 struct cli_state *cli,
5234                                                 struct rpc_pipe_client *pipe_hnd,
5235                                                 TALLOC_CTX *mem_ctx, 
5236                                                 int argc,
5237                                                 const char **argv)
5238 {
5239         POLICY_HND connect_pol, domain_pol, user_pol;
5240         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5241         char *acct_name;
5242         uint32 acb_info;
5243         uint32 unknown, user_rid;
5244
5245         if (argc != 2) {
5246                 d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
5247                 return NT_STATUS_INVALID_PARAMETER;
5248         }
5249
5250         /* 
5251          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5252          */
5253          
5254         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5255                 return NT_STATUS_NO_MEMORY;
5256         }
5257
5258         strupper_m(acct_name);
5259
5260         /* Get samr policy handle */
5261         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
5262                                   &connect_pol);
5263         if (!NT_STATUS_IS_OK(result)) {
5264                 goto done;
5265         }
5266         
5267         /* Get domain policy handle */
5268         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
5269                                       MAXIMUM_ALLOWED_ACCESS,
5270                                       domain_sid, &domain_pol);
5271         if (!NT_STATUS_IS_OK(result)) {
5272                 goto done;
5273         }
5274
5275         /* Create trusting domain's account */
5276         acb_info = ACB_NORMAL; 
5277         unknown = 0xe00500b0; /* No idea what this is - a permission mask?
5278                                  mimir: yes, most probably it is */
5279
5280         result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
5281                                           acct_name, acb_info, unknown,
5282                                           &user_pol, &user_rid);
5283         if (!NT_STATUS_IS_OK(result)) {
5284                 goto done;
5285         }
5286
5287         {
5288                 SAM_USERINFO_CTR ctr;
5289                 SAM_USER_INFO_23 p23;
5290                 NTTIME notime;
5291                 char nostr[] = "";
5292                 LOGON_HRS hrs;
5293                 uchar pwbuf[516];
5294
5295                 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
5296
5297                 ZERO_STRUCT(ctr);
5298                 ZERO_STRUCT(p23);
5299                 ZERO_STRUCT(notime);
5300                 hrs.max_len = 1260;
5301                 hrs.offset = 0;
5302                 hrs.len = 21;
5303                 memset(hrs.hours, 0xFF, sizeof(hrs.hours));
5304                 acb_info = ACB_DOMTRUST;
5305
5306                 init_sam_user_info23A(&p23, &notime, &notime, &notime,
5307                                       &notime, &notime, &notime,
5308                                       nostr, nostr, nostr, nostr, nostr,
5309                                       nostr, nostr, nostr, nostr, nostr,
5310                                       0, 0, acb_info, ACCT_FLAGS, 168, &hrs, 
5311                                       0, 0, (char *)pwbuf);
5312                 ctr.switch_value = 23;
5313                 ctr.info.id23 = &p23;
5314                 p23.passmustchange = 0;
5315
5316                 result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 23,
5317                                                &cli->user_session_key, &ctr);
5318
5319                 if (!NT_STATUS_IS_OK(result)) {
5320                         DEBUG(0,("Could not set trust account password: %s\n",
5321                                  nt_errstr(result)));
5322                         goto done;
5323                 }
5324         }
5325
5326  done:
5327         SAFE_FREE(acct_name);
5328         return result;
5329 }
5330
5331 /**
5332  * Create interdomain trust account for a remote domain.
5333  *
5334  * @param argc standard argc
5335  * @param argv standard argv without initial components
5336  *
5337  * @return Integer status (0 means success)
5338  **/
5339
5340 static int rpc_trustdom_add(int argc, const char **argv)
5341 {
5342         if (argc > 0) {
5343                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
5344                                        argc, argv);
5345         } else {
5346                 d_printf("Usage: net rpc trustdom add <domain>\n");
5347                 return -1;
5348         }
5349 }
5350
5351
5352 /**
5353  * Remove interdomain trust account from the RPC server.
5354  * All parameters (except for argc and argv) are passed by run_rpc_command
5355  * function.
5356  *
5357  * @param domain_sid The domain sid acquired from the server
5358  * @param cli A cli_state connected to the server.
5359  * @param mem_ctx Talloc context, destoyed on completion of the function.
5360  * @param argc  Standard main() style argc
5361  * @param argc  Standard main() style argv.  Initial components are already
5362  *              stripped
5363  *
5364  * @return normal NTSTATUS return code
5365  */
5366
5367 static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, 
5368                                         const char *domain_name, 
5369                                         struct cli_state *cli,
5370                                         struct rpc_pipe_client *pipe_hnd,
5371                                         TALLOC_CTX *mem_ctx, 
5372                                         int argc,
5373                                         const char **argv)
5374 {
5375         POLICY_HND connect_pol, domain_pol, user_pol;
5376         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5377         char *acct_name;
5378         const char **names;
5379         DOM_SID trust_acct_sid;
5380         uint32 *user_rids, num_rids, *name_types;
5381         uint32 flags = 0x000003e8; /* Unknown */
5382
5383         if (argc != 1) {
5384                 d_printf("Usage: net rpc trustdom del <domain_name>\n");
5385                 return NT_STATUS_INVALID_PARAMETER;
5386         }
5387
5388         /* 
5389          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5390          */
5391         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5392
5393         if (acct_name == NULL)
5394                 return NT_STATUS_NO_MEMORY;
5395
5396         strupper_m(acct_name);
5397
5398         names = TALLOC_ARRAY(mem_ctx, const char *, 1);
5399         names[0] = acct_name;
5400
5401
5402         /* Get samr policy handle */
5403         result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
5404                                   &connect_pol);
5405         if (!NT_STATUS_IS_OK(result)) {
5406                 goto done;
5407         }
5408         
5409         /* Get domain policy handle */
5410         result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
5411                                       MAXIMUM_ALLOWED_ACCESS,
5412                                       domain_sid, &domain_pol);
5413         if (!NT_STATUS_IS_OK(result)) {
5414                 goto done;
5415         }
5416
5417         result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1,
5418                                        names, &num_rids,
5419                                        &user_rids, &name_types);
5420         
5421         if (!NT_STATUS_IS_OK(result)) {
5422                 goto done;
5423         }
5424
5425         result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
5426                                     MAXIMUM_ALLOWED_ACCESS,
5427                                     user_rids[0], &user_pol);
5428
5429         if (!NT_STATUS_IS_OK(result)) {
5430                 goto done;
5431         }
5432
5433         /* append the rid to the domain sid */
5434         sid_copy(&trust_acct_sid, domain_sid);
5435         if (!sid_append_rid(&trust_acct_sid, user_rids[0])) {
5436                 goto done;
5437         }
5438
5439         /* remove the sid */
5440
5441         result = rpccli_samr_remove_sid_foreign_domain(pipe_hnd, mem_ctx, &user_pol,
5442                                                     &trust_acct_sid);
5443
5444         if (!NT_STATUS_IS_OK(result)) {
5445                 goto done;
5446         }
5447
5448         /* Delete user */
5449
5450         result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
5451
5452         if (!NT_STATUS_IS_OK(result)) {
5453                 goto done;
5454         }
5455
5456         if (!NT_STATUS_IS_OK(result)) {
5457           DEBUG(0,("Could not set trust account password: %s\n",
5458                    nt_errstr(result)));
5459           goto done;
5460         }
5461
5462  done:
5463         return result;
5464 }
5465
5466 /**
5467  * Delete interdomain trust account for a remote domain.
5468  *
5469  * @param argc standard argc
5470  * @param argv standard argv without initial components
5471  *
5472  * @return Integer status (0 means success)
5473  **/
5474
5475 static int rpc_trustdom_del(int argc, const char **argv)
5476 {
5477         if (argc > 0) {
5478                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_del_internals,
5479                                        argc, argv);
5480         } else {
5481                 d_printf("Usage: net rpc trustdom del <domain>\n");
5482                 return -1;
5483         }
5484 }
5485  
5486
5487 /**
5488  * Establish trust relationship to a trusting domain.
5489  * Interdomain account must already be created on remote PDC.
5490  *
5491  * @param argc standard argc
5492  * @param argv standard argv without initial components
5493  *
5494  * @return Integer status (0 means success)
5495  **/
5496
5497 static int rpc_trustdom_establish(int argc, const char **argv)
5498 {
5499         struct cli_state *cli = NULL;
5500         struct in_addr server_ip;
5501         struct rpc_pipe_client *pipe_hnd = NULL;
5502         POLICY_HND connect_hnd;
5503         TALLOC_CTX *mem_ctx;
5504         NTSTATUS nt_status;
5505         DOM_SID *domain_sid;
5506         
5507         char* domain_name;
5508         char* domain_name_pol;
5509         char* acct_name;
5510         fstring pdc_name;
5511
5512         /*
5513          * Connect to \\server\ipc$ as 'our domain' account with password
5514          */
5515
5516         if (argc != 1) {
5517                 d_printf("Usage: net rpc trustdom establish <domain_name>\n");
5518                 return -1;
5519         }
5520
5521         domain_name = smb_xstrdup(argv[0]);
5522         strupper_m(domain_name);
5523
5524         /* account name used at first is our domain's name with '$' */
5525         asprintf(&acct_name, "%s$", lp_workgroup());
5526         strupper_m(acct_name);
5527         
5528         /*
5529          * opt_workgroup will be used by connection functions further,
5530          * hence it should be set to remote domain name instead of ours
5531          */
5532         if (opt_workgroup) {
5533                 opt_workgroup = smb_xstrdup(domain_name);
5534         };
5535         
5536         opt_user_name = acct_name;
5537
5538         /* find the domain controller */
5539         if (!net_find_pdc(&server_ip, pdc_name, domain_name)) {
5540                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5541                 return -1;
5542         }
5543
5544         /* connect to ipc$ as username/password */
5545         nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
5546         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5547
5548                 /* Is it trusting domain account for sure ? */
5549                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5550                         nt_errstr(nt_status)));
5551                 return -1;
5552         }
5553
5554         /* store who we connected to */
5555
5556         saf_store( domain_name, pdc_name );
5557         
5558         /*
5559          * Connect to \\server\ipc$ again (this time anonymously)
5560          */
5561         
5562         nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
5563         
5564         if (NT_STATUS_IS_ERR(nt_status)) {
5565                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5566                         domain_name, nt_errstr(nt_status)));
5567         }
5568
5569         /*
5570          * Use NetServerEnum2 to make sure we're talking to a proper server
5571          */
5572          
5573         if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
5574                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
5575                          for domain %s\n", domain_name));
5576         }
5577          
5578         if (!(mem_ctx = talloc_init("establishing trust relationship to "
5579                                     "domain %s", domain_name))) {
5580                 DEBUG(0, ("talloc_init() failed\n"));
5581                 cli_shutdown(cli);
5582                 return -1;
5583         }
5584
5585         /*
5586          * Call LsaOpenPolicy and LsaQueryInfo
5587          */
5588          
5589         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
5590         if (!pipe_hnd) {
5591                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5592                 cli_shutdown(cli);
5593                 return -1;
5594         }
5595
5596         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
5597                                          &connect_hnd);
5598         if (NT_STATUS_IS_ERR(nt_status)) {
5599                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5600                         nt_errstr(nt_status)));
5601                 cli_shutdown(cli);
5602                 return -1;
5603         }
5604
5605         /* Querying info level 5 */
5606         
5607         nt_status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &connect_hnd,
5608                                               5 /* info level */,
5609                                               &domain_name_pol, &domain_sid);
5610         if (NT_STATUS_IS_ERR(nt_status)) {
5611                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5612                         nt_errstr(nt_status)));
5613                 cli_shutdown(cli);
5614                 return -1;
5615         }
5616
5617         /* There should be actually query info level 3 (following nt serv behaviour),
5618            but I still don't know if it's _really_ necessary */
5619                         
5620         /*
5621          * Store the password in secrets db
5622          */
5623
5624         if (!secrets_store_trusted_domain_password(domain_name,
5625                                                    opt_password,
5626                                                    domain_sid)) {
5627                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5628                 cli_shutdown(cli);
5629                 return -1;
5630         }
5631         
5632         /*
5633          * Close the pipes and clean up
5634          */
5635          
5636         nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
5637         if (NT_STATUS_IS_ERR(nt_status)) {
5638                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5639                         nt_errstr(nt_status)));
5640                 cli_shutdown(cli);
5641                 return -1;
5642         }
5643
5644         cli_shutdown(cli);
5645          
5646         talloc_destroy(mem_ctx);
5647          
5648         d_printf("Trust to domain %s established\n", domain_name);
5649         return 0;
5650 }
5651
5652 /**
5653  * Revoke trust relationship to the remote domain
5654  *
5655  * @param argc standard argc
5656  * @param argv standard argv without initial components
5657  *
5658  * @return Integer status (0 means success)
5659  **/
5660
5661 static int rpc_trustdom_revoke(int argc, const char **argv)
5662 {
5663         char* domain_name;
5664
5665         if (argc < 1) return -1;
5666         
5667         /* generate upper cased domain name */
5668         domain_name = smb_xstrdup(argv[0]);
5669         strupper_m(domain_name);
5670
5671         /* delete password of the trust */
5672         if (!trusted_domain_password_delete(domain_name)) {
5673                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
5674                           domain_name));
5675                 return -1;
5676         };
5677         
5678         return 0;
5679 }
5680
5681 /**
5682  * Usage for 'net rpc trustdom' command
5683  *
5684  * @param argc standard argc
5685  * @param argv standard argv without inital components
5686  *
5687  * @return Integer status returned to shell
5688  **/
5689  
5690 static int rpc_trustdom_usage(int argc, const char **argv)
5691 {
5692         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
5693         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
5694         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
5695         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
5696         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
5697         d_printf("  net rpc trustdom vampire \t vampire interdomain trust relationships from remote server\n");
5698         return -1;
5699 }
5700
5701
5702 static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, 
5703                                         const char *domain_name, 
5704                                         struct cli_state *cli,
5705                                         struct rpc_pipe_client *pipe_hnd,
5706                                         TALLOC_CTX *mem_ctx,
5707                                         int argc,
5708                                         const char **argv)
5709 {
5710         fstring str_sid;
5711         sid_to_string(str_sid, domain_sid);
5712         d_printf("%s\n", str_sid);
5713         return NT_STATUS_OK;
5714 }
5715
5716 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
5717 {
5718         fstring ascii_sid, padding;
5719         int pad_len, col_len = 20;
5720
5721         /* convert sid into ascii string */
5722         sid_to_string(ascii_sid, dom_sid);
5723
5724         /* calculate padding space for d_printf to look nicer */
5725         pad_len = col_len - strlen(trusted_dom_name);
5726         padding[pad_len] = 0;
5727         do padding[--pad_len] = ' '; while (pad_len);
5728                         
5729         d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
5730 }
5731
5732 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
5733                                       TALLOC_CTX *mem_ctx, 
5734                                       POLICY_HND *pol, 
5735                                       DOM_SID dom_sid, 
5736                                       const char *trusted_dom_name)
5737 {
5738         NTSTATUS nt_status;
5739         LSA_TRUSTED_DOMAIN_INFO *info;
5740         char *cleartextpwd = NULL;
5741         DATA_BLOB data;
5742
5743         nt_status = rpccli_lsa_query_trusted_domain_info_by_sid(pipe_hnd, mem_ctx, pol, 4, &dom_sid, &info);
5744         
5745         if (NT_STATUS_IS_ERR(nt_status)) {
5746                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5747                 nt_errstr(nt_status)));
5748                 goto done;
5749         }
5750
5751         data = data_blob(NULL, info->password.password.length);
5752
5753         memcpy(data.data, info->password.password.data, info->password.password.length);
5754         data.length     = info->password.password.length;
5755                                 
5756         cleartextpwd = decrypt_trustdom_secret(pipe_hnd->cli->pwd.password, &data);
5757
5758         if (cleartextpwd == NULL) {
5759                 DEBUG(0,("retrieved NULL password\n"));
5760                 nt_status = NT_STATUS_UNSUCCESSFUL;
5761                 goto done;
5762         }
5763         
5764         if (!secrets_store_trusted_domain_password(trusted_dom_name,
5765                                                    cleartextpwd,
5766                                                    &dom_sid)) {
5767                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5768                 nt_status = NT_STATUS_UNSUCCESSFUL;
5769                 goto done;
5770         }
5771
5772 #ifdef DEBUG_PASSWORD
5773         DEBUG(100,("sucessfully vampired trusted domain [%s], sid: [%s], password: [%s]\n",  
5774                 trusted_dom_name, sid_string_static(&dom_sid), cleartextpwd));
5775 #endif
5776
5777 done:
5778         SAFE_FREE(cleartextpwd);
5779         data_blob_free(&data);
5780
5781         return nt_status;
5782 }
5783
5784 static int rpc_trustdom_vampire(int argc, const char **argv)
5785 {
5786         /* common variables */
5787         TALLOC_CTX* mem_ctx;
5788         struct cli_state *cli = NULL;
5789         struct rpc_pipe_client *pipe_hnd = NULL;
5790         NTSTATUS nt_status;
5791         const char *domain_name = NULL;
5792         DOM_SID *queried_dom_sid;
5793         POLICY_HND connect_hnd;
5794
5795         /* trusted domains listing variables */
5796         unsigned int num_domains, enum_ctx = 0;
5797         int i;
5798         DOM_SID *domain_sids;
5799         char **trusted_dom_names;
5800         fstring pdc_name;
5801         char *dummy;
5802
5803         /*
5804          * Listing trusted domains (stored in secrets.tdb, if local)
5805          */
5806
5807         mem_ctx = talloc_init("trust relationships vampire");
5808
5809         /*
5810          * set domain and pdc name to local samba server (default)
5811          * or to remote one given in command line
5812          */
5813
5814         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
5815                 domain_name = opt_workgroup;
5816                 opt_target_workgroup = opt_workgroup;
5817         } else {
5818                 fstrcpy(pdc_name, global_myname());
5819                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5820                 opt_target_workgroup = domain_name;
5821         };
5822
5823         /* open \PIPE\lsarpc and open policy handle */
5824         if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
5825                 DEBUG(0, ("Couldn't connect to domain controller\n"));
5826                 return -1;
5827         };
5828
5829         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
5830         if (!pipe_hnd) {
5831                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
5832                         nt_errstr(nt_status) ));
5833                 cli_shutdown(cli);
5834                 return -1;
5835         };
5836
5837         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
5838                                         &connect_hnd);
5839         if (NT_STATUS_IS_ERR(nt_status)) {
5840                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5841                         nt_errstr(nt_status)));
5842                 cli_shutdown(cli);
5843                 return -1;
5844         };
5845
5846         /* query info level 5 to obtain sid of a domain being queried */
5847         nt_status = rpccli_lsa_query_info_policy(
5848                 pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, 
5849                 &dummy, &queried_dom_sid);
5850
5851         if (NT_STATUS_IS_ERR(nt_status)) {
5852                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5853                         nt_errstr(nt_status)));
5854                 cli_shutdown(cli);
5855                 return -1;
5856         }
5857
5858         /*
5859          * Keep calling LsaEnumTrustdom over opened pipe until
5860          * the end of enumeration is reached
5861          */
5862
5863         d_printf("Vampire trusted domains:\n\n");
5864
5865         do {
5866                 nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
5867                                                    &num_domains,
5868                                                    &trusted_dom_names, &domain_sids);
5869                 
5870                 if (NT_STATUS_IS_ERR(nt_status)) {
5871                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
5872                                 nt_errstr(nt_status)));
5873                         cli_shutdown(cli);
5874                         return -1;
5875                 };
5876                 
5877                 for (i = 0; i < num_domains; i++) {
5878
5879                         print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
5880
5881                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
5882                                                            domain_sids[i], trusted_dom_names[i]);
5883                         if (!NT_STATUS_IS_OK(nt_status)) {
5884                                 cli_shutdown(cli);
5885                                 return -1;
5886                         }
5887                 };
5888
5889                 /*
5890                  * in case of no trusted domains say something rather
5891                  * than just display blank line
5892                  */
5893                 if (!num_domains) d_printf("none\n");
5894
5895         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
5896
5897         /* close this connection before doing next one */
5898         nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
5899         if (NT_STATUS_IS_ERR(nt_status)) {
5900                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
5901                         nt_errstr(nt_status)));
5902                 cli_shutdown(cli);
5903                 return -1;
5904         };
5905
5906         /* close lsarpc pipe and connection to IPC$ */
5907         cli_shutdown(cli);
5908
5909         talloc_destroy(mem_ctx);         
5910         return 0;
5911 }
5912
5913 static int rpc_trustdom_list(int argc, const char **argv)
5914 {
5915         /* common variables */
5916         TALLOC_CTX* mem_ctx;
5917         struct cli_state *cli = NULL, *remote_cli = NULL;
5918         struct rpc_pipe_client *pipe_hnd = NULL;
5919         NTSTATUS nt_status;
5920         const char *domain_name = NULL;
5921         DOM_SID *queried_dom_sid;
5922         fstring padding;
5923         int ascii_dom_name_len;
5924         POLICY_HND connect_hnd;
5925         
5926         /* trusted domains listing variables */
5927         unsigned int num_domains, enum_ctx = 0;
5928         int i, pad_len, col_len = 20;
5929         DOM_SID *domain_sids;
5930         char **trusted_dom_names;
5931         fstring pdc_name;
5932         char *dummy;
5933         
5934         /* trusting domains listing variables */
5935         POLICY_HND domain_hnd;
5936         char **trusting_dom_names;
5937         uint32 *trusting_dom_rids;
5938         
5939         /*
5940          * Listing trusted domains (stored in secrets.tdb, if local)
5941          */
5942
5943         mem_ctx = talloc_init("trust relationships listing");
5944
5945         /*
5946          * set domain and pdc name to local samba server (default)
5947          * or to remote one given in command line
5948          */
5949         
5950         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
5951                 domain_name = opt_workgroup;
5952                 opt_target_workgroup = opt_workgroup;
5953         } else {
5954                 fstrcpy(pdc_name, global_myname());
5955                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5956                 opt_target_workgroup = domain_name;
5957         };
5958
5959         /* open \PIPE\lsarpc and open policy handle */
5960         if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) {
5961                 DEBUG(0, ("Couldn't connect to domain controller\n"));
5962                 return -1;
5963         };
5964
5965         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
5966         if (!pipe_hnd) {
5967                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
5968                         nt_errstr(nt_status) ));
5969                 return -1;
5970         };
5971
5972         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
5973                                         &connect_hnd);
5974         if (NT_STATUS_IS_ERR(nt_status)) {
5975                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5976                         nt_errstr(nt_status)));
5977                 return -1;
5978         };
5979         
5980         /* query info level 5 to obtain sid of a domain being queried */
5981         nt_status = rpccli_lsa_query_info_policy(
5982                 pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, 
5983                 &dummy, &queried_dom_sid);
5984
5985         if (NT_STATUS_IS_ERR(nt_status)) {
5986                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5987                         nt_errstr(nt_status)));
5988                 return -1;
5989         }
5990                 
5991         /*
5992          * Keep calling LsaEnumTrustdom over opened pipe until
5993          * the end of enumeration is reached
5994          */
5995          
5996         d_printf("Trusted domains list:\n\n");
5997
5998         do {
5999                 nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
6000                                                    &num_domains,
6001                                                    &trusted_dom_names, &domain_sids);
6002                 
6003                 if (NT_STATUS_IS_ERR(nt_status)) {
6004                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6005                                 nt_errstr(nt_status)));
6006                         return -1;
6007                 };
6008                 
6009                 for (i = 0; i < num_domains; i++) {
6010                         print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
6011                 };
6012                 
6013                 /*
6014                  * in case of no trusted domains say something rather
6015                  * than just display blank line
6016                  */
6017                 if (!num_domains) d_printf("none\n");
6018
6019         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6020
6021         /* close this connection before doing next one */
6022         nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
6023         if (NT_STATUS_IS_ERR(nt_status)) {
6024                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6025                         nt_errstr(nt_status)));
6026                 return -1;
6027         };
6028         
6029         cli_rpc_pipe_close(pipe_hnd);
6030
6031         /*
6032          * Listing trusting domains (stored in passdb backend, if local)
6033          */
6034         
6035         d_printf("\nTrusting domains list:\n\n");
6036
6037         /*
6038          * Open \PIPE\samr and get needed policy handles
6039          */
6040         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status);
6041         if (!pipe_hnd) {
6042                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6043                 return -1;
6044         };
6045         
6046         /* SamrConnect */
6047         nt_status = rpccli_samr_connect(pipe_hnd, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN,
6048                                                                  &connect_hnd);
6049         if (!NT_STATUS_IS_OK(nt_status)) {
6050                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6051                         nt_errstr(nt_status)));
6052                 return -1;
6053         };
6054         
6055         /* SamrOpenDomain - we have to open domain policy handle in order to be
6056            able to enumerate accounts*/
6057         nt_status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_hnd,
6058                                          SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
6059                                          queried_dom_sid, &domain_hnd);                                                                  
6060         if (!NT_STATUS_IS_OK(nt_status)) {
6061                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6062                         nt_errstr(nt_status)));
6063                 return -1;
6064         };
6065         
6066         /*
6067          * perform actual enumeration
6068          */
6069          
6070         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6071         do {
6072                         
6073                 nt_status = rpccli_samr_enum_dom_users(pipe_hnd, mem_ctx, &domain_hnd,
6074                                                     &enum_ctx, ACB_DOMTRUST, 0xffff,
6075                                                     &trusting_dom_names, &trusting_dom_rids,
6076                                                     &num_domains);
6077                 if (NT_STATUS_IS_ERR(nt_status)) {
6078                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6079                                 nt_errstr(nt_status)));
6080                         return -1;
6081                 };
6082                 
6083                 for (i = 0; i < num_domains; i++) {
6084
6085                         /*
6086                          * get each single domain's sid (do we _really_ need this ?):
6087                          *  1) connect to domain's pdc
6088                          *  2) query the pdc for domain's sid
6089                          */
6090
6091                         /* get rid of '$' tail */
6092                         ascii_dom_name_len = strlen(trusting_dom_names[i]);
6093                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6094                                 trusting_dom_names[i][ascii_dom_name_len - 1] = '\0';
6095                         
6096                         /* calculate padding space for d_printf to look nicer */
6097                         pad_len = col_len - strlen(trusting_dom_names[i]);
6098                         padding[pad_len] = 0;
6099                         do padding[--pad_len] = ' '; while (pad_len);
6100
6101                         /* set opt_* variables to remote domain */
6102                         strupper_m(trusting_dom_names[i]);
6103                         opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]);
6104                         opt_target_workgroup = opt_workgroup;
6105                         
6106                         d_printf("%s%s", trusting_dom_names[i], padding);
6107                         
6108                         /* connect to remote domain controller */
6109                         remote_cli = net_make_ipc_connection(NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS);
6110                         if (remote_cli) {                       
6111                                 /* query for domain's sid */
6112                                 if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
6113                                         d_fprintf(stderr, "couldn't get domain's sid\n");
6114
6115                                 cli_shutdown(remote_cli);
6116                         
6117                         } else {
6118                                 d_fprintf(stderr, "domain controller is not responding\n");
6119                         };
6120                 };
6121                 
6122                 if (!num_domains) d_printf("none\n");
6123                 
6124         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6125
6126         /* close opened samr and domain policy handles */
6127         nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &domain_hnd);
6128         if (!NT_STATUS_IS_OK(nt_status)) {
6129                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6130         };
6131         
6132         nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &connect_hnd);
6133         if (!NT_STATUS_IS_OK(nt_status)) {
6134                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6135         };
6136         
6137         /* close samr pipe and connection to IPC$ */
6138         cli_shutdown(cli);
6139
6140         talloc_destroy(mem_ctx);         
6141         return 0;
6142 }
6143
6144 /**
6145  * Entrypoint for 'net rpc trustdom' code
6146  *
6147  * @param argc standard argc
6148  * @param argv standard argv without initial components
6149  *
6150  * @return Integer status (0 means success)
6151  */
6152
6153 static int rpc_trustdom(int argc, const char **argv)
6154 {
6155         struct functable func[] = {
6156                 {"add", rpc_trustdom_add},
6157                 {"del", rpc_trustdom_del},
6158                 {"establish", rpc_trustdom_establish},
6159                 {"revoke", rpc_trustdom_revoke},
6160                 {"help", rpc_trustdom_usage},
6161                 {"list", rpc_trustdom_list},
6162                 {"vampire", rpc_trustdom_vampire},
6163                 {NULL, NULL}
6164         };
6165
6166         if (argc == 0) {
6167                 rpc_trustdom_usage(argc, argv);
6168                 return -1;
6169         }
6170
6171         return (net_run_function(argc, argv, func, rpc_user_usage));
6172 }
6173
6174 /**
6175  * Check if a server will take rpc commands
6176  * @param flags Type of server to connect to (PDC, DMB, localhost)
6177  *              if the host is not explicitly specified
6178  * @return  BOOL (true means rpc supported)
6179  */
6180 BOOL net_rpc_check(unsigned flags)
6181 {
6182         struct cli_state cli;
6183         BOOL ret = False;
6184         struct in_addr server_ip;
6185         char *server_name = NULL;
6186
6187         /* flags (i.e. server type) may depend on command */
6188         if (!net_find_server(flags, &server_ip, &server_name))
6189                 return False;
6190
6191         ZERO_STRUCT(cli);
6192         if (cli_initialise(&cli) == False)
6193                 return False;
6194
6195         if (!cli_connect(&cli, server_name, &server_ip))
6196                 goto done;
6197         if (!attempt_netbios_session_request(&cli, global_myname(), 
6198                                              server_name, &server_ip))
6199                 goto done;
6200         if (!cli_negprot(&cli))
6201                 goto done;
6202         if (cli.protocol < PROTOCOL_NT1)
6203                 goto done;
6204
6205         ret = True;
6206  done:
6207         cli_shutdown(&cli);
6208         return ret;
6209 }
6210
6211 /* dump sam database via samsync rpc calls */
6212 static int rpc_samdump(int argc, const char **argv) {
6213                 return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
6214                                argc, argv);
6215 }
6216
6217 /* syncronise sam database via samsync rpc calls */
6218 static int rpc_vampire(int argc, const char **argv) {
6219         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
6220                                argc, argv);
6221 }
6222
6223 /** 
6224  * Migrate everything from a print-server
6225  *
6226  * @param argc  Standard main() style argc
6227  * @param argv  Standard main() style argv.  Initial components are already
6228  *              stripped
6229  *
6230  * @return A shell status integer (0 for success)
6231  *
6232  * The order is important !
6233  * To successfully add drivers the print-queues have to exist !
6234  * Applying ACLs should be the last step, because you're easily locked out
6235  *
6236  **/
6237 static int rpc_printer_migrate_all(int argc, const char **argv)
6238 {
6239         int ret;
6240
6241         if (!opt_host) {
6242                 printf("no server to migrate\n");
6243                 return -1;
6244         }
6245
6246         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
6247         if (ret)
6248                 return ret;
6249
6250         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
6251         if (ret)
6252                 return ret;
6253
6254         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
6255         if (ret)
6256                 return ret;
6257
6258         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
6259         if (ret)
6260                 return ret;
6261
6262         return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
6263
6264 }
6265
6266 /** 
6267  * Migrate print-drivers from a print-server
6268  *
6269  * @param argc  Standard main() style argc
6270  * @param argv  Standard main() style argv.  Initial components are already
6271  *              stripped
6272  *
6273  * @return A shell status integer (0 for success)
6274  **/
6275 static int rpc_printer_migrate_drivers(int argc, const char **argv)
6276 {
6277         if (!opt_host) {
6278                 printf("no server to migrate\n");
6279                 return -1;
6280         }
6281
6282         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6283                                rpc_printer_migrate_drivers_internals,
6284                                argc, argv);
6285 }
6286
6287 /** 
6288  * Migrate print-forms from a print-server
6289  *
6290  * @param argc  Standard main() style argc
6291  * @param argv  Standard main() style argv.  Initial components are already
6292  *              stripped
6293  *
6294  * @return A shell status integer (0 for success)
6295  **/
6296 static int rpc_printer_migrate_forms(int argc, const char **argv)
6297 {
6298         if (!opt_host) {
6299                 printf("no server to migrate\n");
6300                 return -1;
6301         }
6302
6303         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6304                                rpc_printer_migrate_forms_internals,
6305                                argc, argv);
6306 }
6307
6308 /** 
6309  * Migrate printers from a print-server
6310  *
6311  * @param argc  Standard main() style argc
6312  * @param argv  Standard main() style argv.  Initial components are already
6313  *              stripped
6314  *
6315  * @return A shell status integer (0 for success)
6316  **/
6317 static int rpc_printer_migrate_printers(int argc, const char **argv)
6318 {
6319         if (!opt_host) {
6320                 printf("no server to migrate\n");
6321                 return -1;
6322         }
6323
6324         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6325                                rpc_printer_migrate_printers_internals,
6326                                argc, argv);
6327 }
6328
6329 /** 
6330  * Migrate printer-ACLs from a print-server
6331  *
6332  * @param argc  Standard main() style argc
6333  * @param argv  Standard main() style argv.  Initial components are already
6334  *              stripped
6335  *
6336  * @return A shell status integer (0 for success)
6337  **/
6338 static int rpc_printer_migrate_security(int argc, const char **argv)
6339 {
6340         if (!opt_host) {
6341                 printf("no server to migrate\n");
6342                 return -1;
6343         }
6344
6345         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6346                                rpc_printer_migrate_security_internals,
6347                                argc, argv);
6348 }
6349
6350 /** 
6351  * Migrate printer-settings from a print-server
6352  *
6353  * @param argc  Standard main() style argc
6354  * @param argv  Standard main() style argv.  Initial components are already
6355  *              stripped
6356  *
6357  * @return A shell status integer (0 for success)
6358  **/
6359 static int rpc_printer_migrate_settings(int argc, const char **argv)
6360 {
6361         if (!opt_host) {
6362                 printf("no server to migrate\n");
6363                 return -1;
6364         }
6365
6366         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6367                                rpc_printer_migrate_settings_internals,
6368                                argc, argv);
6369 }
6370
6371 /** 
6372  * 'net rpc printer' entrypoint.
6373  * @param argc  Standard main() style argc
6374  * @param argv  Standard main() style argv.  Initial components are already
6375  *              stripped
6376  **/
6377
6378 int rpc_printer_migrate(int argc, const char **argv) 
6379 {
6380
6381         /* ouch: when addriver and setdriver are called from within
6382            rpc_printer_migrate_drivers_internals, the printer-queue already
6383            *has* to exist */
6384
6385         struct functable func[] = {
6386                 {"all",         rpc_printer_migrate_all},
6387                 {"drivers",     rpc_printer_migrate_drivers},
6388                 {"forms",       rpc_printer_migrate_forms},
6389                 {"help",        rpc_printer_usage},
6390                 {"printers",    rpc_printer_migrate_printers},
6391                 {"security",    rpc_printer_migrate_security},
6392                 {"settings",    rpc_printer_migrate_settings},
6393                 {NULL, NULL}
6394         };
6395
6396         return net_run_function(argc, argv, func, rpc_printer_usage);
6397 }
6398
6399
6400 /** 
6401  * List printers on a remote RPC server
6402  *
6403  * @param argc  Standard main() style argc
6404  * @param argv  Standard main() style argv.  Initial components are already
6405  *              stripped
6406  *
6407  * @return A shell status integer (0 for success)
6408  **/
6409 static int rpc_printer_list(int argc, const char **argv)
6410 {
6411
6412         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6413                                rpc_printer_list_internals,
6414                                argc, argv);
6415 }
6416
6417 /** 
6418  * List printer-drivers on a remote RPC server
6419  *
6420  * @param argc  Standard main() style argc
6421  * @param argv  Standard main() style argv.  Initial components are already
6422  *              stripped
6423  *
6424  * @return A shell status integer (0 for success)
6425  **/
6426 static int rpc_printer_driver_list(int argc, const char **argv)
6427 {
6428
6429         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6430                                rpc_printer_driver_list_internals,
6431                                argc, argv);
6432 }
6433
6434 /** 
6435  * Publish printer in ADS via MSRPC
6436  *
6437  * @param argc  Standard main() style argc
6438  * @param argv  Standard main() style argv.  Initial components are already
6439  *              stripped
6440  *
6441  * @return A shell status integer (0 for success)
6442  **/
6443 static int rpc_printer_publish_publish(int argc, const char **argv)
6444 {
6445
6446         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6447                                rpc_printer_publish_publish_internals,
6448                                argc, argv);
6449 }
6450
6451 /** 
6452  * Update printer in ADS via MSRPC
6453  *
6454  * @param argc  Standard main() style argc
6455  * @param argv  Standard main() style argv.  Initial components are already
6456  *              stripped
6457  *
6458  * @return A shell status integer (0 for success)
6459  **/
6460 static int rpc_printer_publish_update(int argc, const char **argv)
6461 {
6462
6463         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6464                                rpc_printer_publish_update_internals,
6465                                argc, argv);
6466 }
6467
6468 /** 
6469  * UnPublish printer in ADS via MSRPC
6470  *
6471  * @param argc  Standard main() style argc
6472  * @param argv  Standard main() style argv.  Initial components are already
6473  *              stripped
6474  *
6475  * @return A shell status integer (0 for success)
6476  **/
6477 static int rpc_printer_publish_unpublish(int argc, const char **argv)
6478 {
6479
6480         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6481                                rpc_printer_publish_unpublish_internals,
6482                                argc, argv);
6483 }
6484
6485 /** 
6486  * List published printers via MSRPC
6487  *
6488  * @param argc  Standard main() style argc
6489  * @param argv  Standard main() style argv.  Initial components are already
6490  *              stripped
6491  *
6492  * @return A shell status integer (0 for success)
6493  **/
6494 static int rpc_printer_publish_list(int argc, const char **argv)
6495 {
6496
6497         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6498                                rpc_printer_publish_list_internals,
6499                                argc, argv);
6500 }
6501
6502
6503 /** 
6504  * Publish printer in ADS
6505  *
6506  * @param argc  Standard main() style argc
6507  * @param argv  Standard main() style argv.  Initial components are already
6508  *              stripped
6509  *
6510  * @return A shell status integer (0 for success)
6511  **/
6512 static int rpc_printer_publish(int argc, const char **argv)
6513 {
6514
6515         struct functable func[] = {
6516                 {"publish",     rpc_printer_publish_publish},
6517                 {"update",      rpc_printer_publish_update},
6518                 {"unpublish",   rpc_printer_publish_unpublish},
6519                 {"list",        rpc_printer_publish_list},
6520                 {"help",        rpc_printer_usage},
6521                 {NULL, NULL}
6522         };
6523
6524         if (argc == 0)
6525                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6526                                rpc_printer_publish_list_internals,
6527                                argc, argv);
6528
6529         return net_run_function(argc, argv, func, rpc_printer_usage);
6530
6531 }
6532
6533
6534 /** 
6535  * Display rpc printer help page.
6536  * @param argc  Standard main() style argc
6537  * @param argv  Standard main() style argv.  Initial components are already
6538  *              stripped
6539  **/
6540 int rpc_printer_usage(int argc, const char **argv)
6541 {
6542         return net_help_printer(argc, argv);
6543 }
6544
6545 /** 
6546  * 'net rpc printer' entrypoint.
6547  * @param argc  Standard main() style argc
6548  * @param argv  Standard main() style argv.  Initial components are already
6549  *              stripped
6550  **/
6551 int net_rpc_printer(int argc, const char **argv) 
6552 {
6553         struct functable func[] = {
6554                 {"list", rpc_printer_list},
6555                 {"migrate", rpc_printer_migrate},
6556                 {"driver", rpc_printer_driver_list},
6557                 {"publish", rpc_printer_publish},
6558                 {NULL, NULL}
6559         };
6560
6561         if (argc == 0)
6562                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6563                                rpc_printer_list_internals,
6564                                argc, argv);
6565
6566         return net_run_function(argc, argv, func, rpc_printer_usage);
6567 }
6568
6569 /****************************************************************************/
6570
6571
6572 /** 
6573  * Basic usage function for 'net rpc'
6574  * @param argc  Standard main() style argc
6575  * @param argv  Standard main() style argv.  Initial components are already
6576  *              stripped
6577  **/
6578
6579 int net_rpc_usage(int argc, const char **argv) 
6580 {
6581         d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
6582         d_printf("  net rpc join \t\t\tto join a domain \n");
6583         d_printf("  net rpc oldjoin \t\t\tto join a domain created in server manager\n");
6584         d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
6585         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
6586         d_printf("  net rpc password <username> [<password>] -Uadmin_username%%admin_pass\n");
6587         d_printf("  net rpc group \t\tto list groups\n");
6588         d_printf("  net rpc share \t\tto add, delete, list and migrate shares\n");
6589         d_printf("  net rpc printer \t\tto list and migrate printers\n");
6590         d_printf("  net rpc file \t\t\tto list open files\n");
6591         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
6592         d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
6593         d_printf("  net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
6594         d_printf("  net rpc samdump \t\tdiplay an NT PDC's users, groups and other data\n");
6595         d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
6596         d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
6597         d_printf("  net rpc shutdown \t\tto shutdown a remote server\n");
6598         d_printf("  net rpc rights\t\tto manage privileges assigned to SIDs\n");
6599         d_printf("  net rpc registry\t\tto manage registry hives\n");
6600         d_printf("  net rpc service\t\tto start, stop and query services\n");
6601         d_printf("\n");
6602         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
6603         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
6604         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
6605         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
6606         d_printf("\t-C or --comment=<message>\ttext message to display on impending shutdown\n");
6607         return -1;
6608 }
6609
6610
6611 /**
6612  * Help function for 'net rpc'.  Calls command specific help if requested
6613  * or displays usage of net rpc
6614  * @param argc  Standard main() style argc
6615  * @param argv  Standard main() style argv.  Initial components are already
6616  *              stripped
6617  **/
6618
6619 int net_rpc_help(int argc, const char **argv)
6620 {
6621         struct functable func[] = {
6622                 {"join", rpc_join_usage},
6623                 {"user", rpc_user_usage},
6624                 {"group", rpc_group_usage},
6625                 {"share", rpc_share_usage},
6626                 /*{"changetrustpw", rpc_changetrustpw_usage}, */
6627                 {"trustdom", rpc_trustdom_usage},
6628                 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
6629                 /*{"shutdown", rpc_shutdown_usage}, */
6630                 {"vampire", rpc_vampire_usage},
6631                 {NULL, NULL}
6632         };
6633
6634         if (argc == 0) {
6635                 net_rpc_usage(argc, argv);
6636                 return -1;
6637         }
6638
6639         return (net_run_function(argc, argv, func, rpc_user_usage));
6640 }
6641
6642 /** 
6643  * 'net rpc' entrypoint.
6644  * @param argc  Standard main() style argc
6645  * @param argv  Standard main() style argv.  Initial components are already
6646  *              stripped
6647  **/
6648
6649 int net_rpc(int argc, const char **argv)
6650 {
6651         struct functable func[] = {
6652                 {"audit", net_rpc_audit},
6653                 {"info", net_rpc_info},
6654                 {"join", net_rpc_join},
6655                 {"oldjoin", net_rpc_oldjoin},
6656                 {"testjoin", net_rpc_testjoin},
6657                 {"user", net_rpc_user},
6658                 {"password", rpc_user_password},
6659                 {"group", net_rpc_group},
6660                 {"share", net_rpc_share},
6661                 {"file", net_rpc_file},
6662                 {"printer", net_rpc_printer},
6663                 {"changetrustpw", net_rpc_changetrustpw},
6664                 {"trustdom", rpc_trustdom},
6665                 {"abortshutdown", rpc_shutdown_abort},
6666                 {"shutdown", rpc_shutdown},
6667                 {"samdump", rpc_samdump},
6668                 {"vampire", rpc_vampire},
6669                 {"getsid", net_rpc_getsid},
6670                 {"rights", net_rpc_rights},
6671                 {"service", net_rpc_service},
6672                 {"registry", net_rpc_registry},
6673                 {"shell", net_rpc_shell},
6674                 {"help", net_rpc_help},
6675                 {NULL, NULL}
6676         };
6677         return net_run_function(argc, argv, func, net_rpc_usage);
6678 }