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