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