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