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