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