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