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