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