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