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