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