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