Remove a bogus comment
[samba.git] / source / utils / net_rpc.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
6    Copyright (C) 2004 Guenther Deschner (gd@samba.org)
7    Copyright (C) 2005 Jeremy Allison (jra@samba.org)
8    Copyright (C) 2006 Jelmer Vernooij (jelmer@samba.org)
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22  
23 #include "includes.h"
24 #include "utils/net.h"
25
26 static void init_lsa_String(struct lsa_String *name, const char *s)
27 {
28         name->string = s;
29 }
30
31 static int net_mode_share;
32 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask);
33
34 /**
35  * @file net_rpc.c
36  *
37  * @brief RPC based subcommands for the 'net' utility.
38  *
39  * This file should contain much of the functionality that used to
40  * be found in rpcclient, execpt that the commands should change 
41  * less often, and the fucntionality should be sane (the user is not 
42  * expected to know a rid/sid before they conduct an operation etc.)
43  *
44  * @todo Perhaps eventually these should be split out into a number
45  * of files, as this could get quite big.
46  **/
47
48
49 /**
50  * Many of the RPC functions need the domain sid.  This function gets
51  *  it at the start of every run 
52  *
53  * @param cli A cli_state already connected to the remote machine
54  *
55  * @return The Domain SID of the remote machine.
56  **/
57
58 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
59                                    DOM_SID **domain_sid,
60                                    const char **domain_name)
61 {
62         struct rpc_pipe_client *lsa_pipe;
63         POLICY_HND pol;
64         NTSTATUS result = NT_STATUS_OK;
65         union lsa_PolicyInformation *info = NULL;
66
67         lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
68         if (!lsa_pipe) {
69                 d_fprintf(stderr, "Could not initialise lsa pipe\n");
70                 return result;
71         }
72         
73         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False, 
74                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
75                                      &pol);
76         if (!NT_STATUS_IS_OK(result)) {
77                 d_fprintf(stderr, "open_policy failed: %s\n",
78                           nt_errstr(result));
79                 return result;
80         }
81
82         result = rpccli_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx,
83                                             &pol,
84                                             LSA_POLICY_INFO_ACCOUNT_DOMAIN,
85                                             &info);
86         if (!NT_STATUS_IS_OK(result)) {
87                 d_fprintf(stderr, "lsaquery failed: %s\n",
88                           nt_errstr(result));
89                 return result;
90         }
91
92         *domain_name = info->account_domain.name.string;
93         *domain_sid = info->account_domain.sid;
94
95         rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
96         cli_rpc_pipe_close(lsa_pipe);
97
98         return NT_STATUS_OK;
99 }
100
101 /**
102  * Run a single RPC command, from start to finish.
103  *
104  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
105  * @param conn_flag a NET_FLAG_ combination.  Passed to 
106  *                   net_make_ipc_connection.
107  * @param argc  Standard main() style argc
108  * @param argc  Standard main() style argv.  Initial components are already
109  *              stripped
110  * @return A shell status integer (0 for success)
111  */
112
113 int run_rpc_command(struct cli_state *cli_arg,
114                         const int pipe_idx,
115                         int conn_flags,
116                         rpc_command_fn fn,
117                         int argc,
118                         const char **argv) 
119 {
120         struct cli_state *cli = NULL;
121         struct rpc_pipe_client *pipe_hnd = NULL;
122         TALLOC_CTX *mem_ctx;
123         NTSTATUS nt_status;
124         DOM_SID *domain_sid;
125         const char *domain_name;
126
127         /* make use of cli_state handed over as an argument, if possible */
128         if (!cli_arg) {
129                 nt_status = net_make_ipc_connection(conn_flags, &cli);
130                 if (!NT_STATUS_IS_OK(nt_status)) {
131                         DEBUG(1, ("failed to make ipc connection: %s\n",
132                                   nt_errstr(nt_status)));
133                         return -1;
134                 }
135         } else {
136                 cli = cli_arg;
137         }
138
139         if (!cli) {
140                 return -1;
141         }
142
143         /* Create mem_ctx */
144         
145         if (!(mem_ctx = talloc_init("run_rpc_command"))) {
146                 DEBUG(0, ("talloc_init() failed\n"));
147                 cli_shutdown(cli);
148                 return -1;
149         }
150         
151         nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
152                                               &domain_name);
153         if (!NT_STATUS_IS_OK(nt_status)) {
154                 cli_shutdown(cli);
155                 return -1;
156         }
157
158         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
159                 if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) {
160                         /* Always try and create an schannel netlogon pipe. */
161                         pipe_hnd = cli_rpc_pipe_open_schannel(cli, pipe_idx,
162                                                         PIPE_AUTH_LEVEL_PRIVACY,
163                                                         domain_name,
164                                                         &nt_status);
165                         if (!pipe_hnd) {
166                                 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
167                                         nt_errstr(nt_status) ));
168                                 cli_shutdown(cli);
169                                 return -1;
170                         }
171                 } else {
172                         pipe_hnd = cli_rpc_pipe_open_noauth(cli, pipe_idx, &nt_status);
173                         if (!pipe_hnd) {
174                                 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
175                                         cli_get_pipe_name(pipe_idx),
176                                         nt_errstr(nt_status) ));
177                                 cli_shutdown(cli);
178                                 return -1;
179                         }
180                 }
181         }
182         
183         nt_status = fn(domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
184         
185         if (!NT_STATUS_IS_OK(nt_status)) {
186                 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
187         } else {
188                 DEBUG(5, ("rpc command function succedded\n"));
189         }
190                 
191         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
192                 if (pipe_hnd) {
193                         cli_rpc_pipe_close(pipe_hnd);
194                 }
195         }
196
197         /* close the connection only if it was opened here */
198         if (!cli_arg) {
199                 cli_shutdown(cli);
200         }
201         
202         talloc_destroy(mem_ctx);
203         return (!NT_STATUS_IS_OK(nt_status));
204 }
205
206 /** 
207  * Force a change of the trust acccount password.
208  *
209  * All parameters are provided by the run_rpc_command function, except for
210  * argc, argv which are passes through. 
211  *
212  * @param domain_sid The domain sid aquired from the remote server
213  * @param cli A cli_state connected to the server.
214  * @param mem_ctx Talloc context, destoyed on compleation of the function.
215  * @param argc  Standard main() style argc
216  * @param argc  Standard main() style argv.  Initial components are already
217  *              stripped
218  *
219  * @return Normal NTSTATUS return.
220  **/
221
222 static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid,
223                                         const char *domain_name, 
224                                         struct cli_state *cli,
225                                         struct rpc_pipe_client *pipe_hnd,
226                                         TALLOC_CTX *mem_ctx, 
227                                         int argc,
228                                         const char **argv)
229 {
230         
231         return trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup);
232 }
233
234 /** 
235  * Force a change of the trust acccount password.
236  *
237  * @param argc  Standard main() style argc
238  * @param argc  Standard main() style argv.  Initial components are already
239  *              stripped
240  *
241  * @return A shell status integer (0 for success)
242  **/
243
244 int net_rpc_changetrustpw(int argc, const char **argv) 
245 {
246         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
247                                rpc_changetrustpw_internals,
248                                argc, argv);
249 }
250
251 /** 
252  * Join a domain, the old way.
253  *
254  * This uses 'machinename' as the inital password, and changes it. 
255  *
256  * The password should be created with 'server manager' or equiv first.
257  *
258  * All parameters are provided by the run_rpc_command function, except for
259  * argc, argv which are passes through. 
260  *
261  * @param domain_sid The domain sid aquired from the remote server
262  * @param cli A cli_state connected to the server.
263  * @param mem_ctx Talloc context, destoyed on compleation of the function.
264  * @param argc  Standard main() style argc
265  * @param argc  Standard main() style argv.  Initial components are already
266  *              stripped
267  *
268  * @return Normal NTSTATUS return.
269  **/
270
271 static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid,
272                                         const char *domain_name, 
273                                         struct cli_state *cli, 
274                                         struct rpc_pipe_client *pipe_hnd,
275                                         TALLOC_CTX *mem_ctx, 
276                                         int argc,
277                                         const char **argv)
278 {
279         
280         fstring trust_passwd;
281         unsigned char orig_trust_passwd_hash[16];
282         NTSTATUS result;
283         uint32 sec_channel_type;
284
285         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result);
286         if (!pipe_hnd) {
287                 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
288                         "error was %s\n",
289                         cli->desthost,
290                         nt_errstr(result) ));
291                 return result;
292         }
293
294         /* 
295            check what type of join - if the user want's to join as
296            a BDC, the server must agree that we are a BDC.
297         */
298         if (argc >= 0) {
299                 sec_channel_type = get_sec_channel_type(argv[0]);
300         } else {
301                 sec_channel_type = get_sec_channel_type(NULL);
302         }
303         
304         fstrcpy(trust_passwd, global_myname());
305         strlower_m(trust_passwd);
306
307         /*
308          * Machine names can be 15 characters, but the max length on
309          * a password is 14.  --jerry
310          */
311
312         trust_passwd[14] = '\0';
313
314         E_md4hash(trust_passwd, orig_trust_passwd_hash);
315
316         result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup,
317                                               orig_trust_passwd_hash,
318                                               sec_channel_type);
319
320         if (NT_STATUS_IS_OK(result))
321                 printf("Joined domain %s.\n",opt_target_workgroup);
322
323
324         if (!secrets_store_domain_sid(opt_target_workgroup, domain_sid)) {
325                 DEBUG(0, ("error storing domain sid for %s\n", opt_target_workgroup));
326                 result = NT_STATUS_UNSUCCESSFUL;
327         }
328
329         return result;
330 }
331
332 /** 
333  * Join a domain, the old way.
334  *
335  * @param argc  Standard main() style argc
336  * @param argc  Standard main() style argv.  Initial components are already
337  *              stripped
338  *
339  * @return A shell status integer (0 for success)
340  **/
341
342 static int net_rpc_perform_oldjoin(int argc, const char **argv)
343 {
344         return run_rpc_command(NULL, PI_NETLOGON, 
345                                NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
346                                rpc_oldjoin_internals,
347                                argc, argv);
348 }
349
350 /** 
351  * Join a domain, the old way.  This function exists to allow
352  * the message to be displayed when oldjoin was explicitly 
353  * requested, but not when it was implied by "net rpc join"
354  *
355  * @param argc  Standard main() style argc
356  * @param argc  Standard main() style argv.  Initial components are already
357  *              stripped
358  *
359  * @return A shell status integer (0 for success)
360  **/
361
362 static int net_rpc_oldjoin(int argc, const char **argv) 
363 {
364         int rc = net_rpc_perform_oldjoin(argc, argv);
365
366         if (rc) {
367                 d_fprintf(stderr, "Failed to join domain\n");
368         }
369
370         return rc;
371 }
372
373 /** 
374  * Basic usage function for 'net rpc join'
375  * @param argc  Standard main() style argc
376  * @param argc  Standard main() style argv.  Initial components are already
377  *              stripped
378  **/
379
380 static int rpc_join_usage(int argc, const char **argv) 
381 {       
382         d_printf("net rpc join -U <username>[%%password] <type>[options]\n"\
383                  "\t to join a domain with admin username & password\n"\
384                  "\t\t password will be prompted if needed and none is specified\n"\
385                  "\t <type> can be (default MEMBER)\n"\
386                  "\t\t BDC - Join as a BDC\n"\
387                  "\t\t PDC - Join as a PDC\n"\
388                  "\t\t MEMBER - Join as a MEMBER server\n");
389
390         net_common_flags_usage(argc, argv);
391         return -1;
392 }
393
394 /** 
395  * 'net rpc join' entrypoint.
396  * @param argc  Standard main() style argc
397  * @param argc  Standard main() style argv.  Initial components are already
398  *              stripped
399  *
400  * Main 'net_rpc_join()' (where the 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 acct_info *groups;
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_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
2730                                                   &start_idx, 0xffff,
2731                                                   &groups, &num_entries);
2732
2733                 if (!NT_STATUS_IS_OK(result) &&
2734                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2735                         break;
2736                                                  
2737                 for (i = 0; i < num_entries; i++) {
2738
2739                         const char *description = NULL;
2740
2741                         if (opt_long_list_entries) {
2742
2743                                 POLICY_HND alias_pol;
2744                                 union samr_AliasInfo *info = NULL;
2745
2746                                 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2747                                                                            &domain_pol,
2748                                                                            0x8,
2749                                                                            groups[i].rid,
2750                                                                            &alias_pol))) &&
2751                                     (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2752                                                                                 &alias_pol,
2753                                                                                 3,
2754                                                                                 &info))) &&
2755                                     (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2756                                                                     &alias_pol)))) {
2757                                         description = info->description.string;
2758                                 }
2759                         }
2760                         
2761                         if (description != NULL) {
2762                                 printf("%-21.21s %-50.50s\n", 
2763                                        groups[i].acct_name,
2764                                        description);
2765                         } else {
2766                                 printf("%s\n", groups[i].acct_name);
2767                         }
2768                 }
2769         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2770         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2771         /* Get builtin policy handle */
2772
2773         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2774                                         &connect_pol,
2775                                         MAXIMUM_ALLOWED_ACCESS,
2776                                         CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2777                                         &domain_pol);
2778         if (!NT_STATUS_IS_OK(result)) {
2779                 goto done;
2780         }
2781         /* query builtin aliases */
2782         start_idx = 0;
2783         do {
2784                 if (!builtin) break;
2785
2786                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
2787                                                   &start_idx, max_entries,
2788                                                   &groups, &num_entries);
2789                                                  
2790                 if (!NT_STATUS_IS_OK(result) &&
2791                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2792                         break;
2793                                                  
2794                 for (i = 0; i < num_entries; i++) {
2795
2796                         const char *description = NULL;
2797
2798                         if (opt_long_list_entries) {
2799
2800                                 POLICY_HND alias_pol;
2801                                 union samr_AliasInfo *info = NULL;
2802
2803                                 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2804                                                                            &domain_pol,
2805                                                                            0x8,
2806                                                                            groups[i].rid,
2807                                                                            &alias_pol))) &&
2808                                     (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2809                                                                                 &alias_pol,
2810                                                                                 3,
2811                                                                                 &info))) &&
2812                                     (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2813                                                                     &alias_pol)))) {
2814                                         description = info->description.string;
2815                                 }
2816                         }
2817                         
2818                         if (description != NULL) {
2819                                 printf("%-21.21s %-50.50s\n", 
2820                                        groups[i].acct_name,
2821                                        description);
2822                         } else {
2823                                 printf("%s\n", groups[i].acct_name);
2824                         }
2825                 }
2826         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2827
2828  done:
2829         return result;
2830 }
2831
2832 static int rpc_group_list(int argc, const char **argv)
2833 {
2834         return run_rpc_command(NULL, PI_SAMR, 0,
2835                                rpc_group_list_internals,
2836                                argc, argv);
2837 }
2838
2839 static NTSTATUS rpc_list_group_members(struct rpc_pipe_client *pipe_hnd,
2840                                         TALLOC_CTX *mem_ctx,
2841                                         const char *domain_name,
2842                                         const DOM_SID *domain_sid,
2843                                         POLICY_HND *domain_pol,
2844                                         uint32 rid)
2845 {
2846         NTSTATUS result;
2847         POLICY_HND group_pol;
2848         uint32 num_members, *group_rids;
2849         int i;
2850         struct samr_RidTypeArray *rids = NULL;
2851         struct lsa_Strings names;
2852         struct samr_Ids types;
2853
2854         fstring sid_str;
2855         sid_to_fstring(sid_str, domain_sid);
2856
2857         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2858                                        domain_pol,
2859                                        MAXIMUM_ALLOWED_ACCESS,
2860                                        rid,
2861                                        &group_pol);
2862
2863         if (!NT_STATUS_IS_OK(result))
2864                 return result;
2865
2866         result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
2867                                               &group_pol,
2868                                               &rids);
2869
2870         if (!NT_STATUS_IS_OK(result))
2871                 return result;
2872
2873         num_members = rids->count;
2874         group_rids = rids->rids;
2875
2876         while (num_members > 0) {
2877                 int this_time = 512;
2878
2879                 if (num_members < this_time)
2880                         this_time = num_members;
2881
2882                 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
2883                                                 domain_pol,
2884                                                 this_time,
2885                                                 group_rids,
2886                                                 &names,
2887                                                 &types);
2888
2889                 if (!NT_STATUS_IS_OK(result))
2890                         return result;
2891
2892                 /* We only have users as members, but make the output
2893                    the same as the output of alias members */
2894
2895                 for (i = 0; i < this_time; i++) {
2896
2897                         if (opt_long_list_entries) {
2898                                 printf("%s-%d %s\\%s %d\n", sid_str,
2899                                        group_rids[i], domain_name,
2900                                        names.names[i].string,
2901                                        SID_NAME_USER);
2902                         } else {
2903                                 printf("%s\\%s\n", domain_name,
2904                                         names.names[i].string);
2905                         }
2906                 }
2907
2908                 num_members -= this_time;
2909                 group_rids += 512;
2910         }
2911
2912         return NT_STATUS_OK;
2913 }
2914
2915 static NTSTATUS rpc_list_alias_members(struct rpc_pipe_client *pipe_hnd,
2916                                         TALLOC_CTX *mem_ctx,
2917                                         POLICY_HND *domain_pol,
2918                                         uint32 rid)
2919 {
2920         NTSTATUS result;
2921         struct rpc_pipe_client *lsa_pipe;
2922         POLICY_HND alias_pol, lsa_pol;
2923         uint32 num_members;
2924         DOM_SID *alias_sids;
2925         char **domains;
2926         char **names;
2927         enum lsa_SidType *types;
2928         int i;
2929         struct lsa_SidArray sid_array;
2930
2931         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2932                                        domain_pol,
2933                                        MAXIMUM_ALLOWED_ACCESS,
2934                                        rid,
2935                                        &alias_pol);
2936
2937         if (!NT_STATUS_IS_OK(result))
2938                 return result;
2939
2940         result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
2941                                                &alias_pol,
2942                                                &sid_array);
2943
2944         if (!NT_STATUS_IS_OK(result)) {
2945                 d_fprintf(stderr, "Couldn't list alias members\n");
2946                 return result;
2947         }
2948
2949         num_members = sid_array.num_sids;
2950
2951         if (num_members == 0) {
2952                 return NT_STATUS_OK;
2953         }
2954
2955         lsa_pipe = cli_rpc_pipe_open_noauth(pipe_hnd->cli, PI_LSARPC, &result);
2956         if (!lsa_pipe) {
2957                 d_fprintf(stderr, "Couldn't open LSA pipe. Error was %s\n",
2958                         nt_errstr(result) );
2959                 return result;
2960         }
2961
2962         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
2963                                      SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
2964
2965         if (!NT_STATUS_IS_OK(result)) {
2966                 d_fprintf(stderr, "Couldn't open LSA policy handle\n");
2967                 cli_rpc_pipe_close(lsa_pipe);
2968                 return result;
2969         }
2970
2971         alias_sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_members);
2972         if (!alias_sids) {
2973                 d_fprintf(stderr, "Out of memory\n");
2974                 cli_rpc_pipe_close(lsa_pipe);
2975                 return NT_STATUS_NO_MEMORY;
2976         }
2977
2978         for (i=0; i<num_members; i++) {
2979                 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2980         }
2981
2982         result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol, num_members,
2983                                      alias_sids, 
2984                                      &domains, &names, &types);
2985
2986         if (!NT_STATUS_IS_OK(result) &&
2987             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2988                 d_fprintf(stderr, "Couldn't lookup SIDs\n");
2989                 cli_rpc_pipe_close(lsa_pipe);
2990                 return result;
2991         }
2992
2993         for (i = 0; i < num_members; i++) {
2994                 fstring sid_str;
2995                 sid_to_fstring(sid_str, &alias_sids[i]);
2996
2997                 if (opt_long_list_entries) {
2998                         printf("%s %s\\%s %d\n", sid_str, 
2999                                domains[i] ? domains[i] : "*unknown*", 
3000                                names[i] ? names[i] : "*unknown*", types[i]);
3001                 } else {
3002                         if (domains[i])
3003                                 printf("%s\\%s\n", domains[i], names[i]);
3004                         else
3005                                 printf("%s\n", sid_str);
3006                 }
3007         }
3008
3009         cli_rpc_pipe_close(lsa_pipe);
3010         return NT_STATUS_OK;
3011 }
3012  
3013 static NTSTATUS rpc_group_members_internals(const DOM_SID *domain_sid,
3014                                         const char *domain_name, 
3015                                         struct cli_state *cli,
3016                                         struct rpc_pipe_client *pipe_hnd,
3017                                         TALLOC_CTX *mem_ctx,
3018                                         int argc,
3019                                         const char **argv)
3020 {
3021         NTSTATUS result;
3022         POLICY_HND connect_pol, domain_pol;
3023         struct samr_Ids rids, rid_types;
3024         struct lsa_String lsa_acct_name;
3025
3026         /* Get sam policy handle */
3027
3028         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
3029                                       pipe_hnd->cli->desthost,
3030                                       MAXIMUM_ALLOWED_ACCESS,
3031                                       &connect_pol);
3032
3033         if (!NT_STATUS_IS_OK(result))
3034                 return result;
3035         
3036         /* Get domain policy handle */
3037
3038         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
3039                                         &connect_pol,
3040                                         MAXIMUM_ALLOWED_ACCESS,
3041                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
3042                                         &domain_pol);
3043
3044         if (!NT_STATUS_IS_OK(result))
3045                 return result;
3046
3047         init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
3048
3049         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
3050                                          &domain_pol,
3051                                          1,
3052                                          &lsa_acct_name,
3053                                          &rids,
3054                                          &rid_types);
3055
3056         if (!NT_STATUS_IS_OK(result)) {
3057
3058                 /* Ok, did not find it in the global sam, try with builtin */
3059
3060                 DOM_SID sid_Builtin;
3061
3062                 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
3063
3064                 string_to_sid(&sid_Builtin, "S-1-5-32");                
3065
3066                 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
3067                                                 &connect_pol,
3068                                                 MAXIMUM_ALLOWED_ACCESS,
3069                                                 &sid_Builtin,
3070                                                 &domain_pol);
3071
3072                 if (!NT_STATUS_IS_OK(result)) {
3073                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
3074                         return result;
3075                 }
3076
3077                 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
3078                                                  &domain_pol,
3079                                                  1,
3080                                                  &lsa_acct_name,
3081                                                  &rids,
3082                                                  &rid_types);
3083
3084                 if (!NT_STATUS_IS_OK(result)) {
3085                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
3086                         return result;
3087                 }
3088         }
3089
3090         if (rids.count != 1) {
3091                 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
3092                 return result;
3093         }
3094
3095         if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
3096                 return rpc_list_group_members(pipe_hnd, mem_ctx, domain_name,
3097                                               domain_sid, &domain_pol,
3098                                               rids.ids[0]);
3099         }
3100
3101         if (rid_types.ids[0] == SID_NAME_ALIAS) {
3102                 return rpc_list_alias_members(pipe_hnd, mem_ctx, &domain_pol,
3103                                               rids.ids[0]);
3104         }
3105
3106         return NT_STATUS_NO_SUCH_GROUP;
3107 }
3108
3109 static int rpc_group_members(int argc, const char **argv)
3110 {
3111         if (argc != 1) {
3112                 return rpc_group_usage(argc, argv);
3113         }
3114
3115         return run_rpc_command(NULL, PI_SAMR, 0,
3116                                rpc_group_members_internals,
3117                                argc, argv);
3118 }
3119
3120 static NTSTATUS rpc_group_rename_internals(const DOM_SID *domain_sid,
3121                                         const char *domain_name, 
3122                                         struct cli_state *cli,
3123                                         struct rpc_pipe_client *pipe_hnd,
3124                                         TALLOC_CTX *mem_ctx,
3125                                         int argc,
3126                                         const char **argv)
3127 {
3128         NTSTATUS result;
3129         POLICY_HND connect_pol, domain_pol, group_pol;
3130         union samr_GroupInfo group_info;
3131         struct samr_Ids rids, rid_types;
3132         struct lsa_String lsa_acct_name;
3133
3134         if (argc != 2) {
3135                 d_printf("Usage: 'net rpc group rename group newname'\n");
3136                 return NT_STATUS_UNSUCCESSFUL;
3137         }
3138
3139         /* Get sam policy handle */
3140
3141         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
3142                                       pipe_hnd->cli->desthost,
3143                                       MAXIMUM_ALLOWED_ACCESS,
3144                                       &connect_pol);
3145
3146         if (!NT_STATUS_IS_OK(result))
3147                 return result;
3148         
3149         /* Get domain policy handle */
3150
3151         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
3152                                         &connect_pol,
3153                                         MAXIMUM_ALLOWED_ACCESS,
3154                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
3155                                         &domain_pol);
3156
3157         if (!NT_STATUS_IS_OK(result))
3158                 return result;
3159
3160         init_lsa_String(&lsa_acct_name, argv[0]);
3161
3162         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
3163                                          &domain_pol,
3164                                          1,
3165                                          &lsa_acct_name,
3166                                          &rids,
3167                                          &rid_types);
3168
3169         if (rids.count != 1) {
3170                 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
3171                 return result;
3172         }
3173
3174         if (rid_types.ids[0] != SID_NAME_DOM_GRP) {
3175                 d_fprintf(stderr, "Can only rename domain groups\n");
3176                 return NT_STATUS_UNSUCCESSFUL;
3177         }
3178
3179         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
3180                                        &domain_pol,
3181                                        MAXIMUM_ALLOWED_ACCESS,
3182                                        rids.ids[0],
3183                                        &group_pol);
3184
3185         if (!NT_STATUS_IS_OK(result))
3186                 return result;
3187
3188         init_lsa_String(&group_info.name, argv[1]);
3189
3190         result = rpccli_samr_SetGroupInfo(pipe_hnd, mem_ctx,
3191                                           &group_pol,
3192                                           2,
3193                                           &group_info);
3194
3195         if (!NT_STATUS_IS_OK(result))
3196                 return result;
3197
3198         return NT_STATUS_NO_SUCH_GROUP;
3199 }
3200
3201 static int rpc_group_rename(int argc, const char **argv)
3202 {
3203         if (argc != 2) {
3204                 return rpc_group_usage(argc, argv);
3205         }
3206
3207         return run_rpc_command(NULL, PI_SAMR, 0,
3208                                rpc_group_rename_internals,
3209                                argc, argv);
3210 }
3211
3212 /** 
3213  * 'net rpc group' entrypoint.
3214  * @param argc  Standard main() style argc
3215  * @param argc  Standard main() style argv.  Initial components are already
3216  *              stripped
3217  **/
3218
3219 int net_rpc_group(int argc, const char **argv) 
3220 {
3221         struct functable func[] = {
3222                 {"add", rpc_group_add},
3223                 {"delete", rpc_group_delete},
3224                 {"addmem", rpc_group_addmem},
3225                 {"delmem", rpc_group_delmem},
3226                 {"list", rpc_group_list},
3227                 {"members", rpc_group_members},
3228                 {"rename", rpc_group_rename},
3229                 {NULL, NULL}
3230         };
3231         
3232         if (argc == 0) {
3233                 return run_rpc_command(NULL, PI_SAMR, 0, 
3234                                        rpc_group_list_internals,
3235                                        argc, argv);
3236         }
3237
3238         return net_run_function(argc, argv, func, rpc_group_usage);
3239 }
3240
3241 /****************************************************************************/
3242
3243 static int rpc_share_usage(int argc, const char **argv)
3244 {
3245         return net_help_share(argc, argv);
3246 }
3247
3248 /** 
3249  * Add a share on a remote RPC server
3250  *
3251  * All parameters are provided by the run_rpc_command function, except for
3252  * argc, argv which are passes through. 
3253  *
3254  * @param domain_sid The domain sid acquired from the remote server
3255  * @param cli A cli_state connected to the server.
3256  * @param mem_ctx Talloc context, destoyed on completion of the function.
3257  * @param argc  Standard main() style argc
3258  * @param argv  Standard main() style argv.  Initial components are already
3259  *              stripped
3260  *
3261  * @return Normal NTSTATUS return.
3262  **/
3263 static NTSTATUS rpc_share_add_internals(const DOM_SID *domain_sid,
3264                                         const char *domain_name, 
3265                                         struct cli_state *cli,
3266                                         struct rpc_pipe_client *pipe_hnd,
3267                                         TALLOC_CTX *mem_ctx,int argc,
3268                                         const char **argv)
3269 {
3270         WERROR result;
3271         char *sharename;
3272         char *path;
3273         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3274         uint32 num_users=0, perms=0;
3275         char *password=NULL; /* don't allow a share password */
3276         uint32 level = 2;
3277
3278         if ((sharename = talloc_strdup(mem_ctx, argv[0])) == NULL) {
3279                 return NT_STATUS_NO_MEMORY;
3280         }
3281
3282         path = strchr(sharename, '=');
3283         if (!path)
3284                 return NT_STATUS_UNSUCCESSFUL;
3285         *path++ = '\0';
3286
3287         result = rpccli_srvsvc_net_share_add(pipe_hnd, mem_ctx, sharename, type,
3288                                           opt_comment, perms, opt_maxusers,
3289                                           num_users, path, password, 
3290                                           level, NULL);
3291         return werror_to_ntstatus(result);
3292 }
3293
3294 static int rpc_share_add(int argc, const char **argv)
3295 {
3296         if ((argc < 1) || !strchr(argv[0], '=')) {
3297                 DEBUG(1,("Sharename or path not specified on add\n"));
3298                 return rpc_share_usage(argc, argv);
3299         }
3300         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3301                                rpc_share_add_internals,
3302                                argc, argv);
3303 }
3304
3305 /** 
3306  * Delete a share on a remote RPC server
3307  *
3308  * All parameters are provided by the run_rpc_command function, except for
3309  * argc, argv which are passes through. 
3310  *
3311  * @param domain_sid The domain sid acquired from the remote server
3312  * @param cli A cli_state connected to the server.
3313  * @param mem_ctx Talloc context, destoyed on completion of the function.
3314  * @param argc  Standard main() style argc
3315  * @param argv  Standard main() style argv.  Initial components are already
3316  *              stripped
3317  *
3318  * @return Normal NTSTATUS return.
3319  **/
3320 static NTSTATUS rpc_share_del_internals(const DOM_SID *domain_sid,
3321                                         const char *domain_name, 
3322                                         struct cli_state *cli,
3323                                         struct rpc_pipe_client *pipe_hnd,
3324                                         TALLOC_CTX *mem_ctx,
3325                                         int argc,
3326                                         const char **argv)
3327 {
3328         WERROR result;
3329
3330         result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
3331         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3332 }
3333
3334 /** 
3335  * Delete a share on a remote RPC server
3336  *
3337  * @param domain_sid The domain sid acquired from the remote server
3338  * @param argc  Standard main() style argc
3339  * @param argv  Standard main() style argv.  Initial components are already
3340  *              stripped
3341  *
3342  * @return A shell status integer (0 for success)
3343  **/
3344 static int rpc_share_delete(int argc, const char **argv)
3345 {
3346         if (argc < 1) {
3347                 DEBUG(1,("Sharename not specified on delete\n"));
3348                 return rpc_share_usage(argc, argv);
3349         }
3350         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3351                                rpc_share_del_internals,
3352                                argc, argv);
3353 }
3354
3355 /**
3356  * Formatted print of share info
3357  *
3358  * @param info1  pointer to SRV_SHARE_INFO_1 to format
3359  **/
3360  
3361 static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
3362 {
3363         fstring netname = "", remark = "";
3364
3365         rpcstr_pull_unistr2_fstring(netname, &info1->info_1_str.uni_netname);
3366         rpcstr_pull_unistr2_fstring(remark, &info1->info_1_str.uni_remark);
3367
3368         if (opt_long_list_entries) {
3369                 d_printf("%-12s %-8.8s %-50s\n",
3370                          netname, share_type[info1->info_1.type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)], remark);
3371         } else {
3372                 d_printf("%s\n", netname);
3373         }
3374
3375 }
3376
3377 static WERROR get_share_info(struct rpc_pipe_client *pipe_hnd,
3378                                 TALLOC_CTX *mem_ctx, 
3379                                 uint32 level,
3380                                 int argc,
3381                                 const char **argv, 
3382                                 SRV_SHARE_INFO_CTR *ctr)
3383 {
3384         WERROR result;
3385         SRV_SHARE_INFO info;
3386
3387         /* no specific share requested, enumerate all */
3388         if (argc == 0) {
3389
3390                 ENUM_HND hnd;
3391                 uint32 preferred_len = 0xffffffff;
3392
3393                 init_enum_hnd(&hnd, 0);
3394
3395                 return rpccli_srvsvc_net_share_enum(pipe_hnd, mem_ctx, level, ctr, 
3396                                                  preferred_len, &hnd);
3397         }
3398
3399         /* request just one share */
3400         result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, argv[0], level, &info);
3401
3402         if (!W_ERROR_IS_OK(result))
3403                 goto done;
3404
3405         /* construct ctr */
3406         ZERO_STRUCTP(ctr);
3407
3408         ctr->info_level = ctr->switch_value = level;
3409         ctr->ptr_share_info = ctr->ptr_entries = 1;
3410         ctr->num_entries = ctr->num_entries2 = 1;
3411
3412         switch (level) {
3413         case 1:
3414         {
3415                 char *s;
3416                 SRV_SHARE_INFO_1 *info1;
3417                 
3418                 ctr->share.info1 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_1, 1);
3419                 if (ctr->share.info1 == NULL) {
3420                         result = WERR_NOMEM;
3421                         goto done;
3422                 }
3423                 info1 = ctr->share.info1;
3424                                 
3425                 memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
3426
3427                 /* Copy pointer crap */
3428
3429                 memcpy(&info1->info_1, &info.share.info1.info_1, sizeof(SH_INFO_1));
3430
3431                 /* Duplicate strings */
3432
3433                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info1.info_1_str.uni_netname);
3434                 if (s)
3435                         init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
3436
3437                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info1.info_1_str.uni_remark);
3438                 if (s)
3439                         init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);
3440         }
3441         case 2:
3442         {
3443                 char *s;
3444                 SRV_SHARE_INFO_2 *info2;
3445                 
3446                 ctr->share.info2 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_2, 1);
3447                 if (ctr->share.info2 == NULL) {
3448                         result = WERR_NOMEM;
3449                         goto done;
3450                 }
3451                 info2 = ctr->share.info2;
3452                                 
3453                 memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
3454
3455                 /* Copy pointer crap */
3456
3457                 memcpy(&info2->info_2, &info.share.info2.info_2, sizeof(SH_INFO_2));
3458
3459                 /* Duplicate strings */
3460
3461                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_netname);
3462                 if (s)
3463                         init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);
3464
3465                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_remark);
3466                 if (s)
3467                         init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);
3468
3469                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_path);
3470                 if (s)
3471                         init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);
3472
3473                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info2.info_2_str.uni_passwd);
3474                 if (s)
3475                         init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
3476         }
3477         case 502:
3478         {
3479                 char *s;
3480                 SRV_SHARE_INFO_502 *info502;
3481
3482                 ctr->share.info502 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_502, 1);
3483                 if (ctr->share.info502 == NULL) {
3484                         result = WERR_NOMEM;
3485                         goto done;
3486                 }
3487                 info502 = ctr->share.info502;
3488
3489                 memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502));
3490
3491                 /* Copy pointer crap */
3492
3493                 memcpy(&info502->info_502, &info.share.info502.info_502, sizeof(SH_INFO_502));
3494
3495                 /* Duplicate strings */
3496
3497                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_netname);
3498                 if (s)
3499                         init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE);
3500
3501                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_remark);
3502                 if (s)
3503                         init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE);
3504
3505                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_path);
3506                 if (s)
3507                         init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE);
3508
3509                 s = unistr2_to_ascii_talloc(mem_ctx, &info.share.info502.info_502_str.uni_passwd);
3510                 if (s)
3511                         init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE);
3512
3513                 info502->info_502_str.sd = dup_sec_desc(mem_ctx, info.share.info502.info_502_str.sd);
3514                                 
3515         }
3516
3517         } /* switch */
3518
3519 done:
3520         return result;
3521 }
3522
3523 /** 
3524  * List shares on a remote RPC server
3525  *
3526  * All parameters are provided by the run_rpc_command function, except for
3527  * argc, argv which are passes through. 
3528  *
3529  * @param domain_sid The domain sid acquired from the remote server
3530  * @param cli A cli_state connected to the server.
3531  * @param mem_ctx Talloc context, destoyed on completion of the function.
3532  * @param argc  Standard main() style argc
3533  * @param argv  Standard main() style argv.  Initial components are already
3534  *              stripped
3535  *
3536  * @return Normal NTSTATUS return.
3537  **/
3538
3539 static NTSTATUS rpc_share_list_internals(const DOM_SID *domain_sid,
3540                                         const char *domain_name, 
3541                                         struct cli_state *cli,
3542                                         struct rpc_pipe_client *pipe_hnd,
3543                                         TALLOC_CTX *mem_ctx,
3544                                         int argc,
3545                                         const char **argv)
3546 {
3547         SRV_SHARE_INFO_CTR ctr;
3548         WERROR result;
3549         uint32 i, level = 1;
3550
3551         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr);
3552         if (!W_ERROR_IS_OK(result))
3553                 goto done;
3554
3555         /* Display results */
3556
3557         if (opt_long_list_entries) {
3558                 d_printf(
3559         "\nEnumerating shared resources (exports) on remote server:\n\n"\
3560         "\nShare name   Type     Description\n"\
3561         "----------   ----     -----------\n");
3562         }
3563         for (i = 0; i < ctr.num_entries; i++)
3564                 display_share_info_1(&ctr.share.info1[i]);
3565  done:
3566         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3567 }
3568
3569 /*** 
3570  * 'net rpc share list' entrypoint.
3571  * @param argc  Standard main() style argc
3572  * @param argv  Standard main() style argv.  Initial components are already
3573  *              stripped
3574  **/
3575 static int rpc_share_list(int argc, const char **argv)
3576 {
3577         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_list_internals, argc, argv);
3578 }
3579
3580 static bool check_share_availability(struct cli_state *cli, const char *netname)
3581 {
3582         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
3583                 d_printf("skipping   [%s]: not a file share.\n", netname);
3584                 return False;
3585         }
3586
3587         if (!cli_tdis(cli)) 
3588                 return False;
3589
3590         return True;
3591 }
3592
3593 static bool check_share_sanity(struct cli_state *cli, fstring netname, uint32 type)
3594 {
3595         /* only support disk shares */
3596         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3597                 printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
3598                 return False;
3599         }
3600
3601         /* skip builtin shares */
3602         /* FIXME: should print$ be added too ? */
3603         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") || 
3604             strequal(netname,"global")) 
3605                 return False;
3606
3607         if (opt_exclude && in_list(netname, opt_exclude, False)) {
3608                 printf("excluding  [%s]\n", netname);
3609                 return False;
3610         }
3611
3612         return check_share_availability(cli, netname);
3613 }
3614
3615 /** 
3616  * Migrate shares from a remote RPC server to the local RPC srever
3617  *
3618  * All parameters are provided by the run_rpc_command function, except for
3619  * argc, argv which are passes through. 
3620  *
3621  * @param domain_sid The domain sid acquired from the remote server
3622  * @param cli A cli_state connected to the server.
3623  * @param mem_ctx Talloc context, destoyed on completion of the function.
3624  * @param argc  Standard main() style argc
3625  * @param argv  Standard main() style argv.  Initial components are already
3626  *              stripped
3627  *
3628  * @return Normal NTSTATUS return.
3629  **/
3630
3631 static NTSTATUS rpc_share_migrate_shares_internals(const DOM_SID *domain_sid,
3632                                                 const char *domain_name, 
3633                                                 struct cli_state *cli,
3634                                                 struct rpc_pipe_client *pipe_hnd,
3635                                                 TALLOC_CTX *mem_ctx, 
3636                                                 int argc,
3637                                                 const char **argv)
3638 {
3639         WERROR result;
3640         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3641         SRV_SHARE_INFO_CTR ctr_src;
3642         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3643         char *password = NULL; /* don't allow a share password */
3644         uint32 i;
3645         struct rpc_pipe_client *srvsvc_pipe = NULL;
3646         struct cli_state *cli_dst = NULL;
3647         uint32 level = 502; /* includes secdesc */
3648
3649         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3650         if (!W_ERROR_IS_OK(result))
3651                 goto done;
3652
3653         /* connect destination PI_SRVSVC */
3654         nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
3655         if (!NT_STATUS_IS_OK(nt_status))
3656                 return nt_status;
3657
3658
3659         for (i = 0; i < ctr_src.num_entries; i++) {
3660
3661                 fstring netname = "", remark = "", path = "";
3662                 /* reset error-code */
3663                 nt_status = NT_STATUS_UNSUCCESSFUL;
3664
3665                 rpcstr_pull_unistr2_fstring(
3666                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3667                 rpcstr_pull_unistr2_fstring(
3668                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
3669                 rpcstr_pull_unistr2_fstring(
3670                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
3671
3672                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3673                         continue;
3674
3675                 /* finally add the share on the dst server */ 
3676
3677                 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n", 
3678                         netname, path, remark);
3679
3680                 result = rpccli_srvsvc_net_share_add(srvsvc_pipe, mem_ctx, netname, type, remark,
3681                                                   ctr_src.share.info502[i].info_502.perms,
3682                                                   ctr_src.share.info502[i].info_502.max_uses,
3683                                                   ctr_src.share.info502[i].info_502.num_uses,
3684                                                   path, password, level, 
3685                                                   NULL);
3686         
3687                 if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
3688                         printf("           [%s] does already exist\n", netname);
3689                         continue;
3690                 }
3691
3692                 if (!W_ERROR_IS_OK(result)) {
3693                         printf("cannot add share: %s\n", dos_errstr(result));
3694                         goto done;
3695                 }
3696
3697         }
3698
3699         nt_status = NT_STATUS_OK;
3700
3701 done:
3702         if (cli_dst) {
3703                 cli_shutdown(cli_dst);
3704         }
3705
3706         return nt_status;
3707
3708 }
3709
3710 /** 
3711  * Migrate shares from a rpc-server to another
3712  *
3713  * @param argc  Standard main() style argc
3714  * @param argv  Standard main() style argv.  Initial components are already
3715  *              stripped
3716  *
3717  * @return A shell status integer (0 for success)
3718  **/
3719 static int rpc_share_migrate_shares(int argc, const char **argv)
3720 {
3721
3722         if (!opt_host) {
3723                 printf("no server to migrate\n");
3724                 return -1;
3725         }
3726
3727         return run_rpc_command(NULL, PI_SRVSVC, 0, 
3728                                rpc_share_migrate_shares_internals,
3729                                argc, argv);
3730 }
3731
3732 /**
3733  * Copy a file/dir 
3734  *
3735  * @param f     file_info
3736  * @param mask  current search mask
3737  * @param state arg-pointer
3738  *
3739  **/
3740 static void copy_fn(const char *mnt, file_info *f, const char *mask, void *state)
3741 {
3742         static NTSTATUS nt_status;
3743         static struct copy_clistate *local_state;
3744         static fstring filename, new_mask;
3745         fstring dir;
3746         char *old_dir;
3747
3748         local_state = (struct copy_clistate *)state;
3749         nt_status = NT_STATUS_UNSUCCESSFUL;
3750
3751         if (strequal(f->name, ".") || strequal(f->name, ".."))
3752                 return;
3753
3754         DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3755
3756         /* DIRECTORY */
3757         if (f->mode & aDIR) {
3758
3759                 DEBUG(3,("got dir: %s\n", f->name));
3760
3761                 fstrcpy(dir, local_state->cwd);
3762                 fstrcat(dir, "\\");
3763                 fstrcat(dir, f->name);
3764
3765                 switch (net_mode_share)
3766                 {
3767                 case NET_MODE_SHARE_MIGRATE:
3768                         /* create that directory */
3769                         nt_status = net_copy_file(local_state->mem_ctx,
3770                                                   local_state->cli_share_src,
3771                                                   local_state->cli_share_dst,
3772                                                   dir, dir,
3773                                                   opt_acls? True : False,
3774                                                   opt_attrs? True : False,
3775                                                   opt_timestamps? True : False,
3776                                                   False);
3777                         break;
3778                 default:
3779                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3780                         return;
3781                 }
3782
3783                 if (!NT_STATUS_IS_OK(nt_status)) 
3784                         printf("could not handle dir %s: %s\n", 
3785                                 dir, nt_errstr(nt_status));
3786
3787                 /* search below that directory */
3788                 fstrcpy(new_mask, dir);
3789                 fstrcat(new_mask, "\\*");
3790
3791                 old_dir = local_state->cwd;
3792                 local_state->cwd = dir;
3793                 if (!sync_files(local_state, new_mask))
3794                         printf("could not handle files\n");
3795                 local_state->cwd = old_dir;
3796
3797                 return;
3798         }
3799
3800
3801         /* FILE */
3802         fstrcpy(filename, local_state->cwd);
3803         fstrcat(filename, "\\");
3804         fstrcat(filename, f->name);
3805
3806         DEBUG(3,("got file: %s\n", filename));
3807
3808         switch (net_mode_share)
3809         {
3810         case NET_MODE_SHARE_MIGRATE:
3811                 nt_status = net_copy_file(local_state->mem_ctx, 
3812                                           local_state->cli_share_src, 
3813                                           local_state->cli_share_dst, 
3814                                           filename, filename, 
3815                                           opt_acls? True : False, 
3816                                           opt_attrs? True : False,
3817                                           opt_timestamps? True: False,
3818                                           True);
3819                 break;
3820         default:
3821                 d_fprintf(stderr, "Unsupported file mode %d\n", net_mode_share);
3822                 return;
3823         }
3824
3825         if (!NT_STATUS_IS_OK(nt_status)) 
3826                 printf("could not handle file %s: %s\n", 
3827                         filename, nt_errstr(nt_status));
3828
3829 }
3830
3831 /**
3832  * sync files, can be called recursivly to list files 
3833  * and then call copy_fn for each file 
3834  *
3835  * @param cp_clistate   pointer to the copy_clistate we work with
3836  * @param mask          the current search mask
3837  *
3838  * @return              Boolean result
3839  **/
3840 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask)
3841 {
3842         struct cli_state *targetcli;
3843         char *targetpath = NULL;
3844
3845         DEBUG(3,("calling cli_list with mask: %s\n", mask));
3846
3847         if ( !cli_resolve_path(talloc_tos(), "", cp_clistate->cli_share_src,
3848                                 mask, &targetcli, &targetpath ) ) {
3849                 d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n", 
3850                         mask, cli_errstr(cp_clistate->cli_share_src));
3851                 return False;
3852         }
3853
3854         if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3855                 d_fprintf(stderr, "listing %s failed with error: %s\n", 
3856                         mask, cli_errstr(targetcli));
3857                 return False;
3858         }
3859
3860         return True;
3861 }
3862
3863
3864 /**
3865  * Set the top level directory permissions before we do any further copies.
3866  * Should set up ACL inheritance.
3867  **/
3868
3869 bool copy_top_level_perms(struct copy_clistate *cp_clistate, 
3870                                 const char *sharename)
3871 {
3872         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3873
3874         switch (net_mode_share) {
3875         case NET_MODE_SHARE_MIGRATE:
3876                 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3877                 nt_status = net_copy_fileattr(cp_clistate->mem_ctx,
3878                                                 cp_clistate->cli_share_src, 
3879                                                 cp_clistate->cli_share_dst,
3880                                                 "\\", "\\",
3881                                                 opt_acls? True : False, 
3882                                                 opt_attrs? True : False,
3883                                                 opt_timestamps? True: False,
3884                                                 False);
3885                 break;
3886         default:
3887                 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3888                 break;
3889         }
3890
3891         if (!NT_STATUS_IS_OK(nt_status))  {
3892                 printf("Could handle directory attributes for top level directory of share %s. Error %s\n", 
3893                         sharename, nt_errstr(nt_status));
3894                 return False;
3895         }
3896
3897         return True;
3898 }
3899
3900 /** 
3901  * Sync all files inside a remote share to another share (over smb)
3902  *
3903  * All parameters are provided by the run_rpc_command function, except for
3904  * argc, argv which are passes through. 
3905  *
3906  * @param domain_sid The domain sid acquired from the remote server
3907  * @param cli A cli_state connected to the server.
3908  * @param mem_ctx Talloc context, destoyed on completion of the function.
3909  * @param argc  Standard main() style argc
3910  * @param argv  Standard main() style argv.  Initial components are already
3911  *              stripped
3912  *
3913  * @return Normal NTSTATUS return.
3914  **/
3915
3916 static NTSTATUS rpc_share_migrate_files_internals(const DOM_SID *domain_sid,
3917                                                 const char *domain_name, 
3918                                                 struct cli_state *cli,
3919                                                 struct rpc_pipe_client *pipe_hnd,
3920                                                 TALLOC_CTX *mem_ctx,
3921                                                 int argc,
3922                                                 const char **argv)
3923 {
3924         WERROR result;
3925         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3926         SRV_SHARE_INFO_CTR ctr_src;
3927         uint32 i;
3928         uint32 level = 502;
3929         struct copy_clistate cp_clistate;
3930         bool got_src_share = False;
3931         bool got_dst_share = False;
3932         const char *mask = "\\*";
3933         char *dst = NULL;
3934
3935         dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1");
3936
3937         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
3938
3939         if (!W_ERROR_IS_OK(result))
3940                 goto done;
3941
3942         for (i = 0; i < ctr_src.num_entries; i++) {
3943
3944                 fstring netname = "";
3945
3946                 rpcstr_pull_unistr2_fstring(
3947                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
3948
3949                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
3950                         continue;
3951
3952                 /* one might not want to mirror whole discs :) */
3953                 if (strequal(netname, "print$") || netname[1] == '$') {
3954                         d_printf("skipping   [%s]: builtin/hidden share\n", netname);
3955                         continue;
3956                 }
3957
3958                 switch (net_mode_share)
3959                 {
3960                 case NET_MODE_SHARE_MIGRATE:
3961                         printf("syncing");
3962                         break;
3963                 default:
3964                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3965                         break;
3966                 }
3967                 printf("    [%s] files and directories %s ACLs, %s DOS Attributes %s\n", 
3968                         netname, 
3969                         opt_acls ? "including" : "without", 
3970                         opt_attrs ? "including" : "without",
3971                         opt_timestamps ? "(preserving timestamps)" : "");
3972
3973                 cp_clistate.mem_ctx = mem_ctx;
3974                 cp_clistate.cli_share_src = NULL;
3975                 cp_clistate.cli_share_dst = NULL;
3976                 cp_clistate.cwd = NULL;
3977                 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3978
3979                 /* open share source */
3980                 nt_status = connect_to_service(&cp_clistate.cli_share_src,
3981                                                &cli->dest_ss, cli->desthost,
3982                                                netname, "A:");
3983                 if (!NT_STATUS_IS_OK(nt_status))
3984                         goto done;
3985
3986                 got_src_share = True;
3987
3988                 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3989                         /* open share destination */
3990                         nt_status = connect_to_service(&cp_clistate.cli_share_dst,
3991                                                        NULL, dst, netname, "A:");
3992                         if (!NT_STATUS_IS_OK(nt_status))
3993                                 goto done;
3994
3995                         got_dst_share = True;
3996                 }
3997
3998                 if (!copy_top_level_perms(&cp_clistate, netname)) {
3999                         d_fprintf(stderr, "Could not handle the top level directory permissions for the share: %s\n", netname);
4000                         nt_status = NT_STATUS_UNSUCCESSFUL;
4001                         goto done;
4002                 }
4003
4004                 if (!sync_files(&cp_clistate, mask)) {
4005                         d_fprintf(stderr, "could not handle files for share: %s\n", netname);
4006                         nt_status = NT_STATUS_UNSUCCESSFUL;
4007                         goto done;
4008                 }
4009         }
4010
4011         nt_status = NT_STATUS_OK;
4012
4013 done:
4014
4015         if (got_src_share)
4016                 cli_shutdown(cp_clistate.cli_share_src);
4017
4018         if (got_dst_share)
4019                 cli_shutdown(cp_clistate.cli_share_dst);
4020
4021         return nt_status;
4022
4023 }
4024
4025 static int rpc_share_migrate_files(int argc, const char **argv)
4026 {
4027
4028         if (!opt_host) {
4029                 printf("no server to migrate\n");
4030                 return -1;
4031         }
4032
4033         return run_rpc_command(NULL, PI_SRVSVC, 0, 
4034                                rpc_share_migrate_files_internals,
4035                                argc, argv);
4036 }
4037
4038 /** 
4039  * Migrate share-ACLs from a remote RPC server to the local RPC srever
4040  *
4041  * All parameters are provided by the run_rpc_command function, except for
4042  * argc, argv which are passes through. 
4043  *
4044  * @param domain_sid The domain sid acquired from the remote server
4045  * @param cli A cli_state connected to the server.
4046  * @param mem_ctx Talloc context, destoyed on completion of the function.
4047  * @param argc  Standard main() style argc
4048  * @param argv  Standard main() style argv.  Initial components are already
4049  *              stripped
4050  *
4051  * @return Normal NTSTATUS return.
4052  **/
4053
4054 static NTSTATUS rpc_share_migrate_security_internals(const DOM_SID *domain_sid,
4055                                                 const char *domain_name, 
4056                                                 struct cli_state *cli,
4057                                                 struct rpc_pipe_client *pipe_hnd,
4058                                                 TALLOC_CTX *mem_ctx, 
4059                                                 int argc,
4060                                                 const char **argv)
4061 {
4062         WERROR result;
4063         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
4064         SRV_SHARE_INFO_CTR ctr_src;
4065         SRV_SHARE_INFO info;
4066         uint32 i;
4067         struct rpc_pipe_client *srvsvc_pipe = NULL;
4068         struct cli_state *cli_dst = NULL;
4069         uint32 level = 502; /* includes secdesc */
4070
4071         result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
4072
4073         if (!W_ERROR_IS_OK(result))
4074                 goto done;
4075
4076         /* connect destination PI_SRVSVC */
4077         nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
4078         if (!NT_STATUS_IS_OK(nt_status))
4079                 return nt_status;
4080
4081
4082         for (i = 0; i < ctr_src.num_entries; i++) {
4083
4084                 fstring netname = "", remark = "", path = "";
4085                 /* reset error-code */
4086                 nt_status = NT_STATUS_UNSUCCESSFUL;
4087
4088                 rpcstr_pull_unistr2_fstring(
4089                         netname, &ctr_src.share.info502[i].info_502_str.uni_netname);
4090                 rpcstr_pull_unistr2_fstring(
4091                         remark, &ctr_src.share.info502[i].info_502_str.uni_remark);
4092                 rpcstr_pull_unistr2_fstring(
4093                         path, &ctr_src.share.info502[i].info_502_str.uni_path);
4094
4095                 if (!check_share_sanity(cli, netname, ctr_src.share.info502[i].info_502.type))
4096                         continue;
4097
4098                 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n", 
4099                         netname, path, remark);
4100
4101                 if (opt_verbose)
4102                         display_sec_desc(ctr_src.share.info502[i].info_502_str.sd);
4103
4104                 /* init info */
4105                 ZERO_STRUCT(info);
4106
4107                 info.switch_value = level;
4108                 info.ptr_share_ctr = 1;
4109
4110                 /* FIXME: shouldn't we be able to just set the security descriptor ? */
4111                 info.share.info502 = ctr_src.share.info502[i];
4112
4113                 /* finally modify the share on the dst server */
4114                 result = rpccli_srvsvc_net_share_set_info(srvsvc_pipe, mem_ctx, netname, level, &info);
4115         
4116                 if (!W_ERROR_IS_OK(result)) {
4117                         printf("cannot set share-acl: %s\n", dos_errstr(result));
4118                         goto done;
4119                 }
4120
4121         }
4122
4123         nt_status = NT_STATUS_OK;
4124
4125 done:
4126         if (cli_dst) {
4127                 cli_shutdown(cli_dst);
4128         }
4129
4130         return nt_status;
4131
4132 }
4133
4134 /** 
4135  * Migrate share-acls from a rpc-server to another
4136  *
4137  * @param argc  Standard main() style argc
4138  * @param argv  Standard main() style argv.  Initial components are already
4139  *              stripped
4140  *
4141  * @return A shell status integer (0 for success)
4142  **/
4143 static int rpc_share_migrate_security(int argc, const char **argv)
4144 {
4145
4146         if (!opt_host) {
4147                 printf("no server to migrate\n");
4148                 return -1;
4149         }
4150
4151         return run_rpc_command(NULL, PI_SRVSVC, 0, 
4152                                rpc_share_migrate_security_internals,
4153                                argc, argv);
4154 }
4155
4156 /** 
4157  * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
4158  * from one server to another
4159  *
4160  * @param argc  Standard main() style argc
4161  * @param argv  Standard main() style argv.  Initial components are already
4162  *              stripped
4163  *
4164  * @return A shell status integer (0 for success)
4165  *
4166  **/
4167 static int rpc_share_migrate_all(int argc, const char **argv)
4168 {
4169         int ret;
4170
4171         if (!opt_host) {
4172                 printf("no server to migrate\n");
4173                 return -1;
4174         }
4175
4176         /* order is important. we don't want to be locked out by the share-acl
4177          * before copying files - gd */
4178         
4179         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv);
4180         if (ret)
4181                 return ret;
4182
4183         ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv);
4184         if (ret)
4185                 return ret;
4186         
4187         return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_security_internals, argc, argv);
4188 }
4189
4190
4191 /** 
4192  * 'net rpc share migrate' entrypoint.
4193  * @param argc  Standard main() style argc
4194  * @param argv  Standard main() style argv.  Initial components are already
4195  *              stripped
4196  **/
4197 static int rpc_share_migrate(int argc, const char **argv)
4198 {
4199
4200         struct functable func[] = {
4201                 {"all",         rpc_share_migrate_all},
4202                 {"files",       rpc_share_migrate_files},
4203                 {"help",        rpc_share_usage},
4204                 {"security",    rpc_share_migrate_security},
4205                 {"shares",      rpc_share_migrate_shares},
4206                 {NULL, NULL}
4207         };
4208
4209         net_mode_share = NET_MODE_SHARE_MIGRATE;
4210
4211         return net_run_function(argc, argv, func, rpc_share_usage);
4212 }
4213
4214 struct full_alias {
4215         DOM_SID sid;
4216         uint32 num_members;
4217         DOM_SID *members;
4218 };
4219
4220 static int num_server_aliases;
4221 static struct full_alias *server_aliases;
4222
4223 /*
4224  * Add an alias to the static list.
4225  */
4226 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
4227 {
4228         if (server_aliases == NULL)
4229                 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
4230
4231         server_aliases[num_server_aliases] = *alias;
4232         num_server_aliases += 1;
4233 }
4234
4235 /*
4236  * For a specific domain on the server, fetch all the aliases
4237  * and their members. Add all of them to the server_aliases.
4238  */
4239
4240 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4241                                         TALLOC_CTX *mem_ctx,
4242                                         POLICY_HND *connect_pol,
4243                                         const DOM_SID *domain_sid)
4244 {
4245         uint32 start_idx, max_entries, num_entries, i;
4246         struct acct_info *groups;
4247         NTSTATUS result;
4248         POLICY_HND domain_pol;
4249
4250         /* Get domain policy handle */
4251
4252         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
4253                                         connect_pol,
4254                                         MAXIMUM_ALLOWED_ACCESS,
4255                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
4256                                         &domain_pol);
4257         if (!NT_STATUS_IS_OK(result))
4258                 return result;
4259
4260         start_idx = 0;
4261         max_entries = 250;
4262
4263         do {
4264                 result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
4265                                                   &start_idx, max_entries,
4266                                                   &groups, &num_entries);
4267
4268                 for (i = 0; i < num_entries; i++) {
4269
4270                         POLICY_HND alias_pol;
4271                         struct full_alias alias;
4272                         struct lsa_SidArray sid_array;
4273                         int j;
4274
4275                         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
4276                                                        &domain_pol,
4277                                                        MAXIMUM_ALLOWED_ACCESS,
4278                                                        groups[i].rid,
4279                                                        &alias_pol);
4280                         if (!NT_STATUS_IS_OK(result))
4281                                 goto done;
4282
4283                         result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
4284                                                                &alias_pol,
4285                                                                &sid_array);
4286                         if (!NT_STATUS_IS_OK(result))
4287                                 goto done;
4288
4289                         alias.num_members = sid_array.num_sids;
4290
4291                         result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
4292                         if (!NT_STATUS_IS_OK(result))
4293                                 goto done;
4294
4295                         alias.members = NULL;
4296
4297                         if (alias.num_members > 0) {
4298                                 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
4299
4300                                 for (j = 0; j < alias.num_members; j++)
4301                                         sid_copy(&alias.members[j],
4302                                                  sid_array.sids[j].sid);
4303                         }
4304
4305                         sid_copy(&alias.sid, domain_sid);
4306                         sid_append_rid(&alias.sid, groups[i].rid);
4307
4308                         push_alias(mem_ctx, &alias);
4309                 }
4310         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4311
4312         result = NT_STATUS_OK;
4313
4314  done:
4315         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
4316
4317         return result;
4318 }
4319
4320 /*
4321  * Dump server_aliases as names for debugging purposes.
4322  */
4323
4324 static NTSTATUS rpc_aliaslist_dump(const DOM_SID *domain_sid,
4325                                 const char *domain_name,
4326                                 struct cli_state *cli,
4327                                 struct rpc_pipe_client *pipe_hnd,
4328                                 TALLOC_CTX *mem_ctx, 
4329                                 int argc,
4330                                 const char **argv)
4331 {
4332         int i;
4333         NTSTATUS result;
4334         POLICY_HND lsa_pol;
4335
4336         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
4337                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
4338                                      &lsa_pol);
4339         if (!NT_STATUS_IS_OK(result))
4340                 return result;
4341
4342         for (i=0; i<num_server_aliases; i++) {
4343                 char **names;
4344                 char **domains;
4345                 enum lsa_SidType *types;
4346                 int j;
4347
4348                 struct full_alias *alias = &server_aliases[i];
4349
4350                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4351                                              &alias->sid,
4352                                              &domains, &names, &types);
4353                 if (!NT_STATUS_IS_OK(result))
4354                         continue;
4355
4356                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4357
4358                 if (alias->num_members == 0) {
4359                         DEBUG(1, ("\n"));
4360                         continue;
4361                 }
4362
4363                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4364                                              alias->num_members,
4365                                              alias->members,
4366                                              &domains, &names, &types);
4367
4368                 if (!NT_STATUS_IS_OK(result) &&
4369                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4370                         continue;
4371
4372                 for (j=0; j<alias->num_members; j++)
4373                         DEBUG(1, ("%s\\%s (%d); ",
4374                                   domains[j] ? domains[j] : "*unknown*", 
4375                                   names[j] ? names[j] : "*unknown*",types[j]));
4376                 DEBUG(1, ("\n"));
4377         }
4378
4379         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
4380
4381         return NT_STATUS_OK;
4382 }
4383
4384 /*
4385  * Fetch a list of all server aliases and their members into
4386  * server_aliases.
4387  */
4388
4389 static NTSTATUS rpc_aliaslist_internals(const DOM_SID *domain_sid,
4390                                         const char *domain_name,
4391                                         struct cli_state *cli,
4392                                         struct rpc_pipe_client *pipe_hnd,
4393                                         TALLOC_CTX *mem_ctx, 
4394                                         int argc,
4395                                         const char **argv)
4396 {
4397         NTSTATUS result;
4398         POLICY_HND connect_pol;
4399
4400         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
4401                                       pipe_hnd->cli->desthost,
4402                                       MAXIMUM_ALLOWED_ACCESS,
4403                                       &connect_pol);
4404
4405         if (!NT_STATUS_IS_OK(result))
4406                 goto done;
4407         
4408         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4409                                           &global_sid_Builtin);
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                                           domain_sid);
4416
4417         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
4418  done:
4419         return result;
4420 }
4421
4422 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
4423 {
4424         token->num_sids = 4;
4425
4426         if (!(token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4))) {
4427                 d_fprintf(stderr, "malloc failed\n");
4428                 token->num_sids = 0;
4429                 return;
4430         }
4431
4432         token->user_sids[0] = *user_sid;
4433         sid_copy(&token->user_sids[1], &global_sid_World);
4434         sid_copy(&token->user_sids[2], &global_sid_Network);
4435         sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
4436 }
4437
4438 static void free_user_token(NT_USER_TOKEN *token)
4439 {
4440         SAFE_FREE(token->user_sids);
4441 }
4442
4443 static bool is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
4444 {
4445         int i;
4446
4447         for (i=0; i<token->num_sids; i++) {
4448                 if (sid_compare(sid, &token->user_sids[i]) == 0)
4449                         return True;
4450         }
4451         return False;
4452 }
4453
4454 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
4455 {
4456         if (is_sid_in_token(token, sid))
4457                 return;
4458
4459         token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
4460         if (!token->user_sids) {
4461                 return;
4462         }
4463
4464         sid_copy(&token->user_sids[token->num_sids], sid);
4465
4466         token->num_sids += 1;
4467 }
4468
4469 struct user_token {
4470         fstring name;
4471         NT_USER_TOKEN token;
4472 };
4473
4474 static void dump_user_token(struct user_token *token)
4475 {
4476         int i;
4477
4478         d_printf("%s\n", token->name);
4479
4480         for (i=0; i<token->token.num_sids; i++) {
4481                 d_printf(" %s\n", sid_string_tos(&token->token.user_sids[i]));
4482         }
4483 }
4484
4485 static bool is_alias_member(DOM_SID *sid, struct full_alias *alias)
4486 {
4487         int i;
4488
4489         for (i=0; i<alias->num_members; i++) {
4490                 if (sid_compare(sid, &alias->members[i]) == 0)
4491                         return True;
4492         }
4493
4494         return False;
4495 }
4496
4497 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
4498 {
4499         int i;
4500
4501         for (i=0; i<num_server_aliases; i++) {
4502                 if (is_alias_member(&sid, &server_aliases[i]))
4503                         add_sid_to_token(token, &server_aliases[i].sid);
4504         }
4505 }
4506
4507 /*
4508  * We got a user token with all the SIDs we can know about without asking the
4509  * server directly. These are the user and domain group sids. All of these can
4510  * be members of aliases. So scan the list of aliases for each of the SIDs and
4511  * add them to the token.
4512  */
4513
4514 static void collect_alias_memberships(NT_USER_TOKEN *token)
4515 {
4516         int num_global_sids = token->num_sids;
4517         int i;
4518
4519         for (i=0; i<num_global_sids; i++) {
4520                 collect_sid_memberships(token, token->user_sids[i]);
4521         }
4522 }
4523
4524 static bool get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
4525 {
4526         struct winbindd_request request;
4527         struct winbindd_response response;
4528         fstring full_name;
4529         NSS_STATUS result;
4530
4531         DOM_SID user_sid;
4532
4533         int i;
4534
4535         fstr_sprintf(full_name, "%s%c%s",
4536                      domain, *lp_winbind_separator(), user);
4537
4538         /* First let's find out the user sid */
4539
4540         ZERO_STRUCT(request);
4541         ZERO_STRUCT(response);
4542
4543         fstrcpy(request.data.name.dom_name, domain);
4544         fstrcpy(request.data.name.name, user);
4545
4546         result = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response);
4547
4548         if (result != NSS_STATUS_SUCCESS) {
4549                 DEBUG(1, ("winbind could not find %s\n", full_name));
4550                 return False;
4551         }
4552
4553         if (response.data.sid.type != SID_NAME_USER) {
4554                 DEBUG(1, ("%s is not a user\n", full_name));
4555                 return False;
4556         }
4557
4558         string_to_sid(&user_sid, response.data.sid.sid);
4559
4560         init_user_token(token, &user_sid);
4561
4562         /* And now the groups winbind knows about */
4563
4564         ZERO_STRUCT(response);
4565
4566         fstrcpy(request.data.username, full_name);
4567
4568         result = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response);
4569
4570         if (result != NSS_STATUS_SUCCESS) {
4571                 DEBUG(1, ("winbind could not get groups of %s\n", full_name));
4572                 return False;
4573         }
4574
4575         for (i = 0; i < response.data.num_entries; i++) {
4576                 gid_t gid = ((gid_t *)response.extra_data.data)[i];
4577                 DOM_SID sid;
4578
4579                 struct winbindd_request sidrequest;
4580                 struct winbindd_response sidresponse;
4581
4582                 ZERO_STRUCT(sidrequest);
4583                 ZERO_STRUCT(sidresponse);
4584
4585                 sidrequest.data.gid = gid;
4586
4587                 result = winbindd_request_response(WINBINDD_GID_TO_SID,
4588                                           &sidrequest, &sidresponse);
4589
4590                 if (result != NSS_STATUS_SUCCESS) {
4591                         DEBUG(1, ("winbind could not find SID of gid %d\n",
4592                                   gid));
4593                         return False;
4594                 }
4595
4596                 DEBUG(3, (" %s\n", sidresponse.data.sid.sid));
4597
4598                 string_to_sid(&sid, sidresponse.data.sid.sid);
4599                 add_sid_to_token(token, &sid);
4600         }
4601
4602         SAFE_FREE(response.extra_data.data);
4603
4604         return True;
4605 }
4606         
4607 /**
4608  * Get a list of all user tokens we want to look at
4609  **/
4610
4611 static bool get_user_tokens(int *num_tokens, struct user_token **user_tokens)
4612 {
4613         struct winbindd_request request;
4614         struct winbindd_response response;
4615         const char *extra_data;
4616         char *name;
4617         int i;
4618         struct user_token *result;
4619         TALLOC_CTX *frame = NULL;
4620
4621         if (lp_winbind_use_default_domain() &&
4622             (opt_target_workgroup == NULL)) {
4623                 d_fprintf(stderr, "winbind use default domain = yes set, "
4624                          "please specify a workgroup\n");
4625                 return False;
4626         }
4627
4628         /* Send request to winbind daemon */
4629
4630         ZERO_STRUCT(request);
4631         ZERO_STRUCT(response);
4632
4633         if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
4634             NSS_STATUS_SUCCESS)
4635                 return False;
4636
4637         /* Look through extra data */
4638
4639         if (!response.extra_data.data)
4640                 return False;
4641
4642         extra_data = (const char *)response.extra_data.data;
4643         *num_tokens = 0;
4644
4645         frame = talloc_stackframe();
4646         while(next_token_talloc(frame, &extra_data, &name, ",")) {
4647                 *num_tokens += 1;
4648         }
4649
4650         result = SMB_MALLOC_ARRAY(struct user_token, *num_tokens);
4651
4652         if (result == NULL) {
4653                 DEBUG(1, ("Could not malloc sid array\n"));
4654                 TALLOC_FREE(frame);
4655                 return False;
4656         }
4657
4658         extra_data = (const char *)response.extra_data.data;
4659         i=0;
4660
4661         while(next_token_talloc(frame, &extra_data, &name, ",")) {
4662                 fstring domain, user;
4663                 char *p;
4664
4665                 fstrcpy(result[i].name, name);
4666
4667                 p = strchr(name, *lp_winbind_separator());
4668
4669                 DEBUG(3, ("%s\n", name));
4670
4671                 if (p == NULL) {
4672                         fstrcpy(domain, opt_target_workgroup);
4673                         fstrcpy(user, name);
4674                 } else {
4675                         *p++ = '\0';
4676                         fstrcpy(domain, name);
4677                         strupper_m(domain);
4678                         fstrcpy(user, p);
4679                 }
4680
4681                 get_user_sids(domain, user, &(result[i].token));
4682                 i+=1;
4683         }
4684         TALLOC_FREE(frame);
4685         SAFE_FREE(response.extra_data.data);
4686
4687         *user_tokens = result;
4688
4689         return True;
4690 }
4691
4692 static bool get_user_tokens_from_file(FILE *f,
4693                                       int *num_tokens,
4694                                       struct user_token **tokens)
4695 {
4696         struct user_token *token = NULL;
4697
4698         while (!feof(f)) {
4699                 fstring line;
4700
4701                 if (fgets(line, sizeof(line)-1, f) == NULL) {
4702                         return True;
4703                 }
4704
4705                 if (line[strlen(line)-1] == '\n')
4706                         line[strlen(line)-1] = '\0';
4707
4708                 if (line[0] == ' ') {
4709                         /* We have a SID */
4710
4711                         DOM_SID sid;
4712                         string_to_sid(&sid, &line[1]);
4713
4714                         if (token == NULL) {
4715                                 DEBUG(0, ("File does not begin with username"));
4716                                 return False;
4717                         }
4718
4719                         add_sid_to_token(&token->token, &sid);
4720                         continue;
4721                 }
4722
4723                 /* And a new user... */
4724
4725                 *num_tokens += 1;
4726                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4727                 if (*tokens == NULL) {
4728                         DEBUG(0, ("Could not realloc tokens\n"));
4729                         return False;
4730                 }
4731
4732                 token = &((*tokens)[*num_tokens-1]);
4733
4734                 fstrcpy(token->name, line);
4735                 token->token.num_sids = 0;
4736                 token->token.user_sids = NULL;
4737                 continue;
4738         }
4739         
4740         return False;
4741 }
4742
4743
4744 /*
4745  * Show the list of all users that have access to a share
4746  */
4747
4748 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4749                         TALLOC_CTX *mem_ctx,
4750                         const char *netname,
4751                         int num_tokens,
4752                         struct user_token *tokens)
4753 {
4754         int fnum;
4755         SEC_DESC *share_sd = NULL;
4756         SEC_DESC *root_sd = NULL;
4757         struct cli_state *cli = pipe_hnd->cli;
4758         int i;
4759         SRV_SHARE_INFO info;
4760         WERROR result;
4761         uint16 cnum;
4762
4763         result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, netname,
4764                                                502, &info);
4765
4766         if (!W_ERROR_IS_OK(result)) {
4767                 DEBUG(1, ("Coult not query secdesc for share %s\n",
4768                           netname));
4769                 return;
4770         }
4771
4772         share_sd = info.share.info502.info_502_str.sd;
4773         if (share_sd == NULL) {
4774                 DEBUG(1, ("Got no secdesc for share %s\n",
4775                           netname));
4776         }
4777
4778         cnum = cli->cnum;
4779
4780         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
4781                 return;
4782         }
4783
4784         fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
4785
4786         if (fnum != -1) {
4787                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4788         }
4789
4790         for (i=0; i<num_tokens; i++) {
4791                 uint32 acc_granted;
4792                 NTSTATUS status;
4793
4794                 if (share_sd != NULL) {
4795                         if (!se_access_check(share_sd, &tokens[i].token,
4796                                              1, &acc_granted, &status)) {
4797                                 DEBUG(1, ("Could not check share_sd for "
4798                                           "user %s\n",
4799                                           tokens[i].name));
4800                                 continue;
4801                         }
4802
4803                         if (!NT_STATUS_IS_OK(status))
4804                                 continue;
4805                 }
4806
4807                 if (root_sd == NULL) {
4808                         d_printf(" %s\n", tokens[i].name);
4809                         continue;
4810                 }
4811
4812                 if (!se_access_check(root_sd, &tokens[i].token,
4813                                      1, &acc_granted, &status)) {
4814                         DEBUG(1, ("Could not check root_sd for user %s\n",
4815                                   tokens[i].name));
4816                         continue;
4817                 }
4818
4819                 if (!NT_STATUS_IS_OK(status))
4820                         continue;
4821
4822                 d_printf(" %s\n", tokens[i].name);
4823         }
4824
4825         if (fnum != -1)
4826                 cli_close(cli, fnum);
4827         cli_tdis(cli);
4828         cli->cnum = cnum;
4829         
4830         return;
4831 }
4832
4833 struct share_list {
4834         int num_shares;
4835         char **shares;
4836 };
4837
4838 static void collect_share(const char *name, uint32 m,
4839                           const char *comment, void *state)
4840 {
4841         struct share_list *share_list = (struct share_list *)state;
4842
4843         if (m != STYPE_DISKTREE)
4844                 return;
4845
4846         share_list->num_shares += 1;
4847         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4848         if (!share_list->shares) {
4849                 share_list->num_shares = 0;
4850                 return;
4851         }
4852         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4853 }
4854
4855 static void rpc_share_userlist_usage(void)
4856 {
4857         return;
4858 }
4859         
4860 /** 
4861  * List shares on a remote RPC server, including the security descriptors
4862  *
4863  * All parameters are provided by the run_rpc_command function, except for
4864  * argc, argv which are passes through. 
4865  *
4866  * @param domain_sid The domain sid acquired from the remote server
4867  * @param cli A cli_state connected to the server.
4868  * @param mem_ctx Talloc context, destoyed on completion of the function.
4869  * @param argc  Standard main() style argc
4870  * @param argv  Standard main() style argv.  Initial components are already
4871  *              stripped
4872  *
4873  * @return Normal NTSTATUS return.
4874  **/
4875
4876 static NTSTATUS rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
4877                                                 const char *domain_name,
4878                                                 struct cli_state *cli,
4879                                                 struct rpc_pipe_client *pipe_hnd,
4880                                                 TALLOC_CTX *mem_ctx,
4881                                                 int argc,
4882                                                 const char **argv)
4883 {
4884         int ret;
4885         bool r;
4886         ENUM_HND hnd;
4887         uint32 i;
4888         FILE *f;
4889
4890         struct user_token *tokens = NULL;
4891         int num_tokens = 0;
4892
4893         struct share_list share_list;
4894
4895         if (argc > 1) {
4896                 rpc_share_userlist_usage();
4897                 return NT_STATUS_UNSUCCESSFUL;
4898         }
4899
4900         if (argc == 0) {
4901                 f = stdin;
4902         } else {
4903                 f = fopen(argv[0], "r");
4904         }
4905
4906         if (f == NULL) {
4907                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4908                 return NT_STATUS_UNSUCCESSFUL;
4909         }
4910
4911         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4912
4913         if (f != stdin)
4914                 fclose(f);
4915
4916         if (!r) {
4917                 DEBUG(0, ("Could not read users from file\n"));
4918                 return NT_STATUS_UNSUCCESSFUL;
4919         }
4920
4921         for (i=0; i<num_tokens; i++)
4922                 collect_alias_memberships(&tokens[i].token);
4923
4924         init_enum_hnd(&hnd, 0);
4925
4926         share_list.num_shares = 0;
4927         share_list.shares = NULL;
4928
4929         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4930
4931         if (ret == -1) {
4932                 DEBUG(0, ("Error returning browse list: %s\n",
4933                           cli_errstr(cli)));
4934                 goto done;
4935         }
4936
4937         for (i = 0; i < share_list.num_shares; i++) {
4938                 char *netname = share_list.shares[i];
4939
4940                 if (netname[strlen(netname)-1] == '$')
4941                         continue;
4942
4943                 d_printf("%s\n", netname);
4944
4945                 show_userlist(pipe_hnd, mem_ctx, netname,
4946                               num_tokens, tokens);
4947         }
4948  done:
4949         for (i=0; i<num_tokens; i++) {
4950                 free_user_token(&tokens[i].token);
4951         }
4952         SAFE_FREE(tokens);
4953         SAFE_FREE(share_list.shares);
4954
4955         return NT_STATUS_OK;
4956 }
4957
4958 static int rpc_share_allowedusers(int argc, const char **argv)
4959 {
4960         int result;
4961
4962         result = run_rpc_command(NULL, PI_SAMR, 0,
4963                                  rpc_aliaslist_internals,
4964                                  argc, argv);
4965         if (result != 0)
4966                 return result;
4967
4968         result = run_rpc_command(NULL, PI_LSARPC, 0,
4969                                  rpc_aliaslist_dump,
4970                                  argc, argv);
4971         if (result != 0)
4972                 return result;
4973
4974         return run_rpc_command(NULL, PI_SRVSVC, 0,
4975                                rpc_share_allowedusers_internals,
4976                                argc, argv);
4977 }
4978
4979 int net_usersidlist(int argc, const char **argv)
4980 {
4981         int num_tokens = 0;
4982         struct user_token *tokens = NULL;
4983         int i;
4984
4985         if (argc != 0) {
4986                 net_usersidlist_usage(argc, argv);
4987                 return 0;
4988         }
4989
4990         if (!get_user_tokens(&num_tokens, &tokens)) {
4991                 DEBUG(0, ("Could not get the user/sid list\n"));
4992                 return 0;
4993         }
4994
4995         for (i=0; i<num_tokens; i++) {
4996                 dump_user_token(&tokens[i]);
4997                 free_user_token(&tokens[i].token);
4998         }
4999
5000         SAFE_FREE(tokens);
5001         return 1;
5002 }
5003
5004 int net_usersidlist_usage(int argc, const char **argv)
5005 {
5006         d_printf("net usersidlist\n"
5007                  "\tprints out a list of all users the running winbind knows\n"
5008                  "\tabout, together with all their SIDs. This is used as\n"
5009                  "\tinput to the 'net rpc share allowedusers' command.\n\n");
5010
5011         net_common_flags_usage(argc, argv);
5012         return -1;
5013 }
5014
5015 /** 
5016  * 'net rpc share' entrypoint.
5017  * @param argc  Standard main() style argc
5018  * @param argv  Standard main() style argv.  Initial components are already
5019  *              stripped
5020  **/
5021
5022 int net_rpc_share(int argc, const char **argv) 
5023 {
5024         struct functable func[] = {
5025                 {"add", rpc_share_add},
5026                 {"delete", rpc_share_delete},
5027                 {"allowedusers", rpc_share_allowedusers},
5028                 {"migrate", rpc_share_migrate},
5029                 {"list", rpc_share_list},
5030                 {NULL, NULL}
5031         };
5032
5033         if (argc == 0)
5034                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
5035                                        rpc_share_list_internals,
5036                                        argc, argv);
5037
5038         return net_run_function(argc, argv, func, rpc_share_usage);
5039 }
5040
5041 static NTSTATUS rpc_sh_share_list(TALLOC_CTX *mem_ctx,
5042                                   struct rpc_sh_ctx *ctx,
5043                                   struct rpc_pipe_client *pipe_hnd,
5044                                   int argc, const char **argv)
5045 {
5046         return rpc_share_list_internals(ctx->domain_sid, ctx->domain_name,
5047                                         ctx->cli, pipe_hnd, mem_ctx,
5048                                         argc, argv);
5049 }
5050
5051 static NTSTATUS rpc_sh_share_add(TALLOC_CTX *mem_ctx,
5052                                  struct rpc_sh_ctx *ctx,
5053                                  struct rpc_pipe_client *pipe_hnd,
5054                                  int argc, const char **argv)
5055 {
5056         WERROR result;
5057
5058         if ((argc < 2) || (argc > 3)) {
5059                 d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
5060                           ctx->whoami);
5061                 return NT_STATUS_INVALID_PARAMETER;
5062         }
5063
5064         result = rpccli_srvsvc_net_share_add(
5065                 pipe_hnd, mem_ctx, argv[0], STYPE_DISKTREE,
5066                 (argc == 3) ? argv[2] : "",
5067                 0, 0, 0, argv[1], NULL, 2, NULL);
5068                                              
5069         return werror_to_ntstatus(result);
5070 }
5071
5072 static NTSTATUS rpc_sh_share_delete(TALLOC_CTX *mem_ctx,
5073                                     struct rpc_sh_ctx *ctx,
5074                                     struct rpc_pipe_client *pipe_hnd,
5075                                     int argc, const char **argv)
5076 {
5077         WERROR result;
5078
5079         if (argc != 1) {
5080                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
5081                 return NT_STATUS_INVALID_PARAMETER;
5082         }
5083
5084         result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
5085         return werror_to_ntstatus(result);
5086 }
5087
5088 static NTSTATUS rpc_sh_share_info(TALLOC_CTX *mem_ctx,
5089                                   struct rpc_sh_ctx *ctx,
5090                                   struct rpc_pipe_client *pipe_hnd,
5091                                   int argc, const char **argv)
5092 {
5093         SRV_SHARE_INFO info;
5094         SRV_SHARE_INFO_2 *info2 = &info.share.info2;
5095         WERROR result;
5096
5097         if (argc != 1) {
5098                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
5099                 return NT_STATUS_INVALID_PARAMETER;
5100         }
5101
5102         result = rpccli_srvsvc_net_share_get_info(
5103                 pipe_hnd, mem_ctx, argv[0], 2, &info);
5104         if (!W_ERROR_IS_OK(result)) {
5105                 goto done;
5106         }
5107
5108         d_printf("Name:     %s\n",
5109                  rpcstr_pull_unistr2_talloc(mem_ctx,
5110                                             &info2->info_2_str.uni_netname));
5111         d_printf("Comment:  %s\n",
5112                  rpcstr_pull_unistr2_talloc(mem_ctx,
5113                                             &info2->info_2_str.uni_remark));
5114         
5115         d_printf("Path:     %s\n",
5116                  rpcstr_pull_unistr2_talloc(mem_ctx,
5117                                             &info2->info_2_str.uni_path));
5118         d_printf("Password: %s\n",
5119                  rpcstr_pull_unistr2_talloc(mem_ctx,
5120                                             &info2->info_2_str.uni_passwd));
5121
5122  done:
5123         return werror_to_ntstatus(result);
5124 }
5125
5126 struct rpc_sh_cmd *net_rpc_share_cmds(TALLOC_CTX *mem_ctx,
5127                                       struct rpc_sh_ctx *ctx)
5128 {
5129         static struct rpc_sh_cmd cmds[] = {
5130
5131         { "list", NULL, PI_SRVSVC, rpc_sh_share_list,
5132           "List available shares" },
5133
5134         { "add", NULL, PI_SRVSVC, rpc_sh_share_add,
5135           "Add a share" },
5136
5137         { "delete", NULL, PI_SRVSVC, rpc_sh_share_delete,
5138           "Delete a share" },
5139
5140         { "info", NULL, PI_SRVSVC, rpc_sh_share_info,
5141           "Get information about a share" },
5142
5143         { NULL, NULL, 0, NULL, NULL }
5144         };
5145
5146         return cmds;
5147 }
5148
5149 /****************************************************************************/
5150
5151 static int rpc_file_usage(int argc, const char **argv)
5152 {
5153         return net_help_file(argc, argv);
5154 }
5155
5156 /** 
5157  * Close a file on a remote RPC server
5158  *
5159  * All parameters are provided by the run_rpc_command function, except for
5160  * argc, argv which are passes through. 
5161  *
5162  * @param domain_sid The domain sid acquired from the remote server
5163  * @param cli A cli_state connected to the server.
5164  * @param mem_ctx Talloc context, destoyed on completion of the function.
5165  * @param argc  Standard main() style argc
5166  * @param argv  Standard main() style argv.  Initial components are already
5167  *              stripped
5168  *
5169  * @return Normal NTSTATUS return.
5170  **/
5171 static NTSTATUS rpc_file_close_internals(const DOM_SID *domain_sid,
5172                                         const char *domain_name, 
5173                                         struct cli_state *cli,
5174                                         struct rpc_pipe_client *pipe_hnd,
5175                                         TALLOC_CTX *mem_ctx,
5176                                         int argc,
5177                                         const char **argv)
5178 {
5179         return rpccli_srvsvc_NetFileClose(pipe_hnd, mem_ctx, 
5180                                             pipe_hnd->cli->desthost, 
5181                                             atoi(argv[0]), NULL);
5182 }
5183
5184 /** 
5185  * Close a file on a remote RPC server
5186  *
5187  * @param argc  Standard main() style argc
5188  * @param argv  Standard main() style argv.  Initial components are already
5189  *              stripped
5190  *
5191  * @return A shell status integer (0 for success)
5192  **/
5193 static int rpc_file_close(int argc, const char **argv)
5194 {
5195         if (argc < 1) {
5196                 DEBUG(1, ("No fileid given on close\n"));
5197                 return(rpc_file_usage(argc, argv));
5198         }
5199
5200         return run_rpc_command(NULL, PI_SRVSVC, 0, 
5201                                rpc_file_close_internals,
5202                                argc, argv);
5203 }
5204
5205 /** 
5206  * Formatted print of open file info 
5207  *
5208  * @param info3  FILE_INFO_3 contents
5209  * @param str3   strings for FILE_INFO_3
5210  **/
5211
5212 static void display_file_info_3( FILE_INFO_3 *info3 )
5213 {
5214         fstring user = "", path = "";
5215
5216         rpcstr_pull_unistr2_fstring(user, info3->user);
5217         rpcstr_pull_unistr2_fstring(path, info3->path);
5218
5219         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5220                  info3->id, user, info3->perms, info3->num_locks, path);
5221 }
5222
5223 /** 
5224  * List open files on a remote RPC server
5225  *
5226  * All parameters are provided by the run_rpc_command function, except for
5227  * argc, argv which are passes through. 
5228  *
5229  * @param domain_sid The domain sid acquired from the remote server
5230  * @param cli A cli_state connected to the server.
5231  * @param mem_ctx Talloc context, destoyed on completion of the function.
5232  * @param argc  Standard main() style argc
5233  * @param argv  Standard main() style argv.  Initial components are already
5234  *              stripped
5235  *
5236  * @return Normal NTSTATUS return.
5237  **/
5238
5239 static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
5240                                         const char *domain_name, 
5241                                         struct cli_state *cli,
5242                                         struct rpc_pipe_client *pipe_hnd,
5243                                         TALLOC_CTX *mem_ctx,
5244                                         int argc,
5245                                         const char **argv)
5246 {
5247         SRV_FILE_INFO_CTR ctr;
5248         WERROR result;
5249         ENUM_HND hnd;
5250         uint32 preferred_len = 0xffffffff, i;
5251         const char *username=NULL;
5252
5253         init_enum_hnd(&hnd, 0);
5254
5255         /* if argc > 0, must be user command */
5256         if (argc > 0)
5257                 username = smb_xstrdup(argv[0]);
5258                 
5259         result = rpccli_srvsvc_net_file_enum(pipe_hnd,
5260                                         mem_ctx, 3, username, &ctr, preferred_len, &hnd);
5261
5262         if (!W_ERROR_IS_OK(result))
5263                 goto done;
5264
5265         /* Display results */
5266
5267         d_printf(
5268                  "\nEnumerating open files on remote server:\n\n"\
5269                  "\nFileId  Opened by            Perms  Locks  Path"\
5270                  "\n------  ---------            -----  -----  ---- \n");
5271         for (i = 0; i < ctr.num_entries; i++)
5272                 display_file_info_3(&ctr.file.info3[i]);
5273  done:
5274         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
5275 }
5276
5277 /** 
5278  * List files for a user on a remote RPC server
5279  *
5280  * @param argc  Standard main() style argc
5281  * @param argv  Standard main() style argv.  Initial components are already
5282  *              stripped
5283  *
5284  * @return A shell status integer (0 for success)
5285  **/
5286
5287 static int rpc_file_user(int argc, const char **argv)
5288 {
5289         if (argc < 1) {
5290                 DEBUG(1, ("No username given\n"));
5291                 return(rpc_file_usage(argc, argv));
5292         }
5293
5294         return run_rpc_command(NULL, PI_SRVSVC, 0, 
5295                                rpc_file_list_internals,
5296                                argc, argv);
5297 }
5298
5299 /** 
5300  * 'net rpc file' entrypoint.
5301  * @param argc  Standard main() style argc
5302  * @param argv  Standard main() style argv.  Initial components are already
5303  *              stripped
5304  **/
5305
5306 int net_rpc_file(int argc, const char **argv) 
5307 {
5308         struct functable func[] = {
5309                 {"close", rpc_file_close},
5310                 {"user", rpc_file_user},
5311 #if 0
5312                 {"info", rpc_file_info},
5313 #endif
5314                 {NULL, NULL}
5315         };
5316
5317         if (argc == 0)
5318                 return run_rpc_command(NULL, PI_SRVSVC, 0, 
5319                                        rpc_file_list_internals,
5320                                        argc, argv);
5321
5322         return net_run_function(argc, argv, func, rpc_file_usage);
5323 }
5324
5325 /** 
5326  * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
5327  *
5328  * All parameters are provided by the run_rpc_command function, except for
5329  * argc, argv which are passed through. 
5330  *
5331  * @param domain_sid The domain sid aquired from the remote server
5332  * @param cli A cli_state connected to the server.
5333  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5334  * @param argc  Standard main() style argc
5335  * @param argv  Standard main() style argv.  Initial components are already
5336  *              stripped
5337  *
5338  * @return Normal NTSTATUS return.
5339  **/
5340
5341 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, 
5342                                         const char *domain_name, 
5343                                         struct cli_state *cli, 
5344                                         struct rpc_pipe_client *pipe_hnd,
5345                                         TALLOC_CTX *mem_ctx, 
5346                                         int argc,
5347                                         const char **argv) 
5348 {
5349         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5350         
5351         result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
5352         
5353         if (NT_STATUS_IS_OK(result)) {
5354                 d_printf("\nShutdown successfully aborted\n");
5355                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5356         } else
5357                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5358         
5359         return result;
5360 }
5361
5362 /** 
5363  * ABORT the shutdown of a remote RPC Server,  over winreg pipe
5364  *
5365  * All parameters are provided by the run_rpc_command function, except for
5366  * argc, argv which are passed through. 
5367  *
5368  * @param domain_sid The domain sid aquired from the remote server
5369  * @param cli A cli_state connected to the server.
5370  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5371  * @param argc  Standard main() style argc
5372  * @param argv  Standard main() style argv.  Initial components are already
5373  *              stripped
5374  *
5375  * @return Normal NTSTATUS return.
5376  **/
5377
5378 static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid, 
5379                                                 const char *domain_name, 
5380                                                 struct cli_state *cli, 
5381                                                 struct rpc_pipe_client *pipe_hnd,
5382                                                 TALLOC_CTX *mem_ctx, 
5383                                                 int argc,
5384                                                 const char **argv) 
5385 {
5386         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5387         
5388         result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
5389         
5390         if (NT_STATUS_IS_OK(result)) {
5391                 d_printf("\nShutdown successfully aborted\n");
5392                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5393         } else
5394                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5395         
5396         return result;
5397 }
5398
5399 /** 
5400  * ABORT the Shut down of a remote RPC server
5401  *
5402  * @param argc  Standard main() style argc
5403  * @param argv  Standard main() style argv.  Initial components are already
5404  *              stripped
5405  *
5406  * @return A shell status integer (0 for success)
5407  **/
5408
5409 static int rpc_shutdown_abort(int argc, const char **argv) 
5410 {
5411         int rc = run_rpc_command(NULL, PI_INITSHUTDOWN, 0, 
5412                                  rpc_shutdown_abort_internals,
5413                                  argc, argv);
5414
5415         if (rc == 0)
5416                 return rc;
5417
5418         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5419
5420         return run_rpc_command(NULL, PI_WINREG, 0, 
5421                                rpc_reg_shutdown_abort_internals,
5422                                argc, argv);
5423 }
5424
5425 /** 
5426  * Shut down a remote RPC Server via initshutdown pipe
5427  *
5428  * All parameters are provided by the run_rpc_command function, except for
5429  * argc, argv which are passes through. 
5430  *
5431  * @param domain_sid The domain sid aquired from the remote server
5432  * @param cli A cli_state connected to the server.
5433  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5434  * @param argc  Standard main() style argc
5435  * @param argc  Standard main() style argv.  Initial components are already
5436  *              stripped
5437  *
5438  * @return Normal NTSTATUS return.
5439  **/
5440
5441 NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid,
5442                                                 const char *domain_name, 
5443                                                 struct cli_state *cli, 
5444                                                 struct rpc_pipe_client *pipe_hnd,
5445                                                 TALLOC_CTX *mem_ctx, 
5446                                                 int argc,
5447                                                 const char **argv) 
5448 {
5449         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5450         const char *msg = "This machine will be shutdown shortly";
5451         uint32 timeout = 20;
5452         struct initshutdown_String msg_string;
5453         struct initshutdown_String_sub s;
5454
5455         if (opt_comment) {
5456                 msg = opt_comment;
5457         }
5458         if (opt_timeout) {
5459                 timeout = opt_timeout;
5460         }
5461
5462         s.name = msg;
5463         msg_string.name = &s;
5464
5465         /* create an entry */
5466         result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5467                         &msg_string, timeout, opt_force, opt_reboot, NULL);
5468
5469         if (NT_STATUS_IS_OK(result)) {
5470                 d_printf("\nShutdown of remote machine succeeded\n");
5471                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5472         } else {
5473                 DEBUG(1,("Shutdown of remote machine failed!\n"));
5474         }
5475         return result;
5476 }
5477
5478 /** 
5479  * Shut down a remote RPC Server via winreg pipe
5480  *
5481  * All parameters are provided by the run_rpc_command function, except for
5482  * argc, argv which are passes through. 
5483  *
5484  * @param domain_sid The domain sid aquired from the remote server
5485  * @param cli A cli_state connected to the server.
5486  * @param mem_ctx Talloc context, destoyed on compleation of the function.
5487  * @param argc  Standard main() style argc
5488  * @param argc  Standard main() style argv.  Initial components are already
5489  *              stripped
5490  *
5491  * @return Normal NTSTATUS return.
5492  **/
5493
5494 NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid,
5495                                                 const char *domain_name, 
5496                                                 struct cli_state *cli, 
5497                                                 struct rpc_pipe_client *pipe_hnd,
5498                                                 TALLOC_CTX *mem_ctx, 
5499                                                 int argc,
5500                                                 const char **argv) 
5501 {
5502         const char *msg = "This machine will be shutdown shortly";
5503         uint32 timeout = 20;
5504         struct initshutdown_String msg_string;
5505         struct initshutdown_String_sub s;
5506         NTSTATUS result;
5507         WERROR werr;
5508
5509         if (opt_comment) {
5510                 msg = opt_comment;
5511         }
5512         s.name = msg;
5513         msg_string.name = &s;
5514
5515         if (opt_timeout) {
5516                 timeout = opt_timeout;
5517         }
5518
5519         /* create an entry */
5520         result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5521                         &msg_string, timeout, opt_force, opt_reboot, &werr);
5522
5523         if (NT_STATUS_IS_OK(result)) {
5524                 d_printf("\nShutdown of remote machine succeeded\n");
5525         } else {
5526                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5527                 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5528                         d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5529                 else
5530                         d_fprintf(stderr, "\nresult was: %s\n", dos_errstr(werr));
5531         }
5532
5533         return result;
5534 }
5535
5536 /** 
5537  * Shut down a remote RPC server
5538  *
5539  * @param argc  Standard main() style argc
5540  * @param argc  Standard main() style argv.  Initial components are already
5541  *              stripped
5542  *
5543  * @return A shell status integer (0 for success)
5544  **/
5545
5546 static int rpc_shutdown(int argc, const char **argv) 
5547 {
5548         int rc = run_rpc_command(NULL, PI_INITSHUTDOWN, 0, 
5549                                  rpc_init_shutdown_internals,
5550                                  argc, argv);
5551
5552         if (rc) {
5553                 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5554                 rc = run_rpc_command(NULL, PI_WINREG, 0, 
5555                                      rpc_reg_shutdown_internals, argc, argv);
5556         }
5557
5558         return rc;
5559 }
5560
5561 /***************************************************************************
5562   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5563   
5564  ***************************************************************************/
5565
5566 /**
5567  * Add interdomain trust account to the RPC server.
5568  * All parameters (except for argc and argv) are passed by run_rpc_command
5569  * function.
5570  *
5571  * @param domain_sid The domain sid acquired from the server
5572  * @param cli A cli_state connected to the server.
5573  * @param mem_ctx Talloc context, destoyed on completion of the function.
5574  * @param argc  Standard main() style argc
5575  * @param argc  Standard main() style argv.  Initial components are already
5576  *              stripped
5577  *
5578  * @return normal NTSTATUS return code
5579  */
5580
5581 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, 
5582                                                 const char *domain_name, 
5583                                                 struct cli_state *cli,
5584                                                 struct rpc_pipe_client *pipe_hnd,
5585                                                 TALLOC_CTX *mem_ctx, 
5586                                                 int argc,
5587                                                 const char **argv)
5588 {
5589         POLICY_HND connect_pol, domain_pol, user_pol;
5590         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5591         char *acct_name;
5592         struct lsa_String lsa_acct_name;
5593         uint32 acb_info;
5594         uint32 acct_flags=0;
5595         uint32 user_rid;
5596         uint32_t access_granted = 0;
5597
5598         if (argc != 2) {
5599                 d_printf("Usage: net rpc trustdom add <domain_name> <pw>\n");
5600                 return NT_STATUS_INVALID_PARAMETER;
5601         }
5602
5603         /* 
5604          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5605          */
5606
5607         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5608                 return NT_STATUS_NO_MEMORY;
5609         }
5610
5611         strupper_m(acct_name);
5612
5613         init_lsa_String(&lsa_acct_name, acct_name);
5614
5615         /* Get samr policy handle */
5616         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5617                                       pipe_hnd->cli->desthost,
5618                                       MAXIMUM_ALLOWED_ACCESS,
5619                                       &connect_pol);
5620         if (!NT_STATUS_IS_OK(result)) {
5621                 goto done;
5622         }
5623
5624         /* Get domain policy handle */
5625         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5626                                         &connect_pol,
5627                                         MAXIMUM_ALLOWED_ACCESS,
5628                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5629                                         &domain_pol);
5630         if (!NT_STATUS_IS_OK(result)) {
5631                 goto done;
5632         }
5633
5634         /* Create trusting domain's account */
5635         acb_info = ACB_NORMAL;
5636         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5637                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5638                      SAMR_USER_ACCESS_SET_PASSWORD |
5639                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
5640                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
5641
5642         result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5643                                          &domain_pol,
5644                                          &lsa_acct_name,
5645                                          acb_info,
5646                                          acct_flags,
5647                                          &user_pol,
5648                                          &access_granted,
5649                                          &user_rid);
5650         if (!NT_STATUS_IS_OK(result)) {
5651                 goto done;
5652         }
5653
5654         {
5655                 SAM_USERINFO_CTR ctr;
5656                 SAM_USER_INFO_23 p23;
5657                 NTTIME notime;
5658                 char nostr[] = "";
5659                 LOGON_HRS hrs;
5660                 uchar pwbuf[516];
5661
5662                 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
5663
5664                 ZERO_STRUCT(ctr);
5665                 ZERO_STRUCT(p23);
5666                 ZERO_STRUCT(notime);
5667                 hrs.max_len = 1260;
5668                 hrs.offset = 0;
5669                 hrs.len = 21;
5670                 memset(hrs.hours, 0xFF, sizeof(hrs.hours));
5671                 acb_info = ACB_DOMTRUST;
5672
5673                 init_sam_user_info23A(&p23, &notime, &notime, &notime,
5674                                       &notime, &notime, &notime,
5675                                       nostr, nostr, nostr, nostr, nostr,
5676                                       nostr, nostr, nostr, nostr, nostr,
5677                                       0, 0, acb_info, SAMR_FIELD_ACCT_FLAGS, 168, &hrs,
5678                                       0, 0, (char *)pwbuf);
5679                 ctr.switch_value = 23;
5680                 ctr.info.id23 = &p23;
5681                 p23.passmustchange = 0;
5682
5683                 result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 23,
5684                                                &cli->user_session_key, &ctr);
5685
5686                 if (!NT_STATUS_IS_OK(result)) {
5687                         DEBUG(0,("Could not set trust account password: %s\n",
5688                                  nt_errstr(result)));
5689                         goto done;
5690                 }
5691         }
5692
5693  done:
5694         SAFE_FREE(acct_name);
5695         return result;
5696 }
5697
5698 /**
5699  * Create interdomain trust account for a remote domain.
5700  *
5701  * @param argc standard argc
5702  * @param argv standard argv without initial components
5703  *
5704  * @return Integer status (0 means success)
5705  **/
5706
5707 static int rpc_trustdom_add(int argc, const char **argv)
5708 {
5709         if (argc > 0) {
5710                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals,
5711                                        argc, argv);
5712         } else {
5713                 d_printf("Usage: net rpc trustdom add <domain>\n");
5714                 return -1;
5715         }
5716 }
5717
5718
5719 /**
5720  * Remove interdomain trust account from the RPC server.
5721  * All parameters (except for argc and argv) are passed by run_rpc_command
5722  * function.
5723  *
5724  * @param domain_sid The domain sid acquired from the server
5725  * @param cli A cli_state connected to the server.
5726  * @param mem_ctx Talloc context, destoyed on completion of the function.
5727  * @param argc  Standard main() style argc
5728  * @param argc  Standard main() style argv.  Initial components are already
5729  *              stripped
5730  *
5731  * @return normal NTSTATUS return code
5732  */
5733
5734 static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, 
5735                                         const char *domain_name, 
5736                                         struct cli_state *cli,
5737                                         struct rpc_pipe_client *pipe_hnd,
5738                                         TALLOC_CTX *mem_ctx, 
5739                                         int argc,
5740                                         const char **argv)
5741 {
5742         POLICY_HND connect_pol, domain_pol, user_pol;
5743         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5744         char *acct_name;
5745         DOM_SID trust_acct_sid;
5746         struct samr_Ids user_rids, name_types;
5747         struct lsa_String lsa_acct_name;
5748
5749         if (argc != 1) {
5750                 d_printf("Usage: net rpc trustdom del <domain_name>\n");
5751                 return NT_STATUS_INVALID_PARAMETER;
5752         }
5753
5754         /* 
5755          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5756          */
5757         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5758
5759         if (acct_name == NULL)
5760                 return NT_STATUS_NO_MEMORY;
5761
5762         strupper_m(acct_name);
5763
5764         /* Get samr policy handle */
5765         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5766                                       pipe_hnd->cli->desthost,
5767                                       MAXIMUM_ALLOWED_ACCESS,
5768                                       &connect_pol);
5769         if (!NT_STATUS_IS_OK(result)) {
5770                 goto done;
5771         }
5772
5773         /* Get domain policy handle */
5774         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5775                                         &connect_pol,
5776                                         MAXIMUM_ALLOWED_ACCESS,
5777                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5778                                         &domain_pol);
5779         if (!NT_STATUS_IS_OK(result)) {
5780                 goto done;
5781         }
5782
5783         init_lsa_String(&lsa_acct_name, acct_name);
5784
5785         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5786                                          &domain_pol,
5787                                          1,
5788                                          &lsa_acct_name,
5789                                          &user_rids,
5790                                          &name_types);
5791
5792         if (!NT_STATUS_IS_OK(result)) {
5793                 goto done;
5794         }
5795
5796         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5797                                       &domain_pol,
5798                                       MAXIMUM_ALLOWED_ACCESS,
5799                                       user_rids.ids[0],
5800                                       &user_pol);
5801
5802         if (!NT_STATUS_IS_OK(result)) {
5803                 goto done;
5804         }
5805
5806         /* append the rid to the domain sid */
5807         sid_copy(&trust_acct_sid, domain_sid);
5808         if (!sid_append_rid(&trust_acct_sid, user_rids.ids[0])) {
5809                 goto done;
5810         }
5811
5812         /* remove the sid */
5813
5814         result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5815                                                            &user_pol,
5816                                                            &trust_acct_sid);
5817         if (!NT_STATUS_IS_OK(result)) {
5818                 goto done;
5819         }
5820
5821         /* Delete user */
5822
5823         result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5824                                         &user_pol);
5825
5826         if (!NT_STATUS_IS_OK(result)) {
5827                 goto done;
5828         }
5829
5830         if (!NT_STATUS_IS_OK(result)) {
5831           DEBUG(0,("Could not set trust account password: %s\n",
5832                    nt_errstr(result)));
5833           goto done;
5834         }
5835
5836  done:
5837         return result;
5838 }
5839
5840 /**
5841  * Delete interdomain trust account for a remote domain.
5842  *
5843  * @param argc standard argc
5844  * @param argv standard argv without initial components
5845  *
5846  * @return Integer status (0 means success)
5847  **/
5848
5849 static int rpc_trustdom_del(int argc, const char **argv)
5850 {
5851         if (argc > 0) {
5852                 return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_del_internals,
5853                                        argc, argv);
5854         } else {
5855                 d_printf("Usage: net rpc trustdom del <domain>\n");
5856                 return -1;
5857         }
5858 }
5859  
5860
5861 /**
5862  * Establish trust relationship to a trusting domain.
5863  * Interdomain account must already be created on remote PDC.
5864  *
5865  * @param argc standard argc
5866  * @param argv standard argv without initial components
5867  *
5868  * @return Integer status (0 means success)
5869  **/
5870
5871 static int rpc_trustdom_establish(int argc, const char **argv)
5872 {
5873         struct cli_state *cli = NULL;
5874         struct sockaddr_storage server_ss;
5875         struct rpc_pipe_client *pipe_hnd = NULL;
5876         POLICY_HND connect_hnd;
5877         TALLOC_CTX *mem_ctx;
5878         NTSTATUS nt_status;
5879         DOM_SID *domain_sid;
5880
5881         char* domain_name;
5882         char* acct_name;
5883         fstring pdc_name;
5884         char *dc_name;
5885         union lsa_PolicyInformation *info = NULL;
5886
5887         /*
5888          * Connect to \\server\ipc$ as 'our domain' account with password
5889          */
5890
5891         if (argc != 1) {
5892                 d_printf("Usage: net rpc trustdom establish <domain_name>\n");
5893                 return -1;
5894         }
5895
5896         domain_name = smb_xstrdup(argv[0]);
5897         strupper_m(domain_name);
5898
5899         /* account name used at first is our domain's name with '$' */
5900         asprintf(&acct_name, "%s$", lp_workgroup());
5901         strupper_m(acct_name);
5902
5903         /*
5904          * opt_workgroup will be used by connection functions further,
5905          * hence it should be set to remote domain name instead of ours
5906          */
5907         if (opt_workgroup) {
5908                 opt_workgroup = smb_xstrdup(domain_name);
5909         };
5910
5911         opt_user_name = acct_name;
5912
5913         /* find the domain controller */
5914         if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5915                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5916                 return -1;
5917         }
5918
5919         /* connect to ipc$ as username/password */
5920         nt_status = connect_to_ipc(&cli, &server_ss, pdc_name);
5921         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5922
5923                 /* Is it trusting domain account for sure ? */
5924                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5925                         nt_errstr(nt_status)));
5926                 return -1;
5927         }
5928
5929         /* store who we connected to */
5930
5931         saf_store( domain_name, pdc_name );
5932
5933         /*
5934          * Connect to \\server\ipc$ again (this time anonymously)
5935          */
5936
5937         nt_status = connect_to_ipc_anonymous(&cli, &server_ss, (char*)pdc_name);
5938
5939         if (NT_STATUS_IS_ERR(nt_status)) {
5940                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5941                         domain_name, nt_errstr(nt_status)));
5942                 return -1;
5943         }
5944
5945         /*
5946          * Use NetServerEnum2 to make sure we're talking to a proper server
5947          */
5948
5949         if (!cli_get_pdc_name(cli, domain_name, &dc_name)) {
5950                 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
5951                          for domain %s\n", domain_name));
5952                 cli_shutdown(cli);
5953                 return -1;
5954         }
5955         SAFE_FREE(dc_name);
5956          
5957         if (!(mem_ctx = talloc_init("establishing trust relationship to "
5958                                     "domain %s", domain_name))) {
5959                 DEBUG(0, ("talloc_init() failed\n"));
5960                 cli_shutdown(cli);
5961                 return -1;
5962         }
5963
5964         /*
5965          * Call LsaOpenPolicy and LsaQueryInfo
5966          */
5967          
5968         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
5969         if (!pipe_hnd) {
5970                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5971                 cli_shutdown(cli);
5972                 talloc_destroy(mem_ctx);
5973                 return -1;
5974         }
5975
5976         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
5977                                          &connect_hnd);
5978         if (NT_STATUS_IS_ERR(nt_status)) {
5979                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5980                         nt_errstr(nt_status)));
5981                 cli_shutdown(cli);
5982                 talloc_destroy(mem_ctx);
5983                 return -1;
5984         }
5985
5986         /* Querying info level 5 */
5987
5988         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5989                                                &connect_hnd,
5990                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5991                                                &info);
5992         if (NT_STATUS_IS_ERR(nt_status)) {
5993                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5994                         nt_errstr(nt_status)));
5995                 cli_shutdown(cli);
5996                 talloc_destroy(mem_ctx);
5997                 return -1;
5998         }
5999
6000         domain_sid = info->account_domain.sid;
6001
6002         /* There should be actually query info level 3 (following nt serv behaviour),
6003            but I still don't know if it's _really_ necessary */
6004                         
6005         /*
6006          * Store the password in secrets db
6007          */
6008
6009         if (!pdb_set_trusteddom_pw(domain_name, opt_password, domain_sid)) {
6010                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6011                 cli_shutdown(cli);
6012                 talloc_destroy(mem_ctx);
6013                 return -1;
6014         }
6015         
6016         /*
6017          * Close the pipes and clean up
6018          */
6019          
6020         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6021         if (NT_STATUS_IS_ERR(nt_status)) {
6022                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6023                         nt_errstr(nt_status)));
6024                 cli_shutdown(cli);
6025                 talloc_destroy(mem_ctx);
6026                 return -1;
6027         }
6028
6029         cli_shutdown(cli);
6030          
6031         talloc_destroy(mem_ctx);
6032          
6033         d_printf("Trust to domain %s established\n", domain_name);
6034         return 0;
6035 }
6036
6037 /**
6038  * Revoke trust relationship to the remote domain
6039  *
6040  * @param argc standard argc
6041  * @param argv standard argv without initial components
6042  *
6043  * @return Integer status (0 means success)
6044  **/
6045
6046 static int rpc_trustdom_revoke(int argc, const char **argv)
6047 {
6048         char* domain_name;
6049         int rc = -1;
6050
6051         if (argc < 1) return -1;
6052         
6053         /* generate upper cased domain name */
6054         domain_name = smb_xstrdup(argv[0]);
6055         strupper_m(domain_name);
6056
6057         /* delete password of the trust */
6058         if (!pdb_del_trusteddom_pw(domain_name)) {
6059                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6060                           domain_name));
6061                 goto done;
6062         };
6063         
6064         rc = 0;
6065 done:
6066         SAFE_FREE(domain_name);
6067         return rc;
6068 }
6069
6070 /**
6071  * Usage for 'net rpc trustdom' command
6072  *
6073  * @param argc standard argc
6074  * @param argv standard argv without inital components
6075  *
6076  * @return Integer status returned to shell
6077  **/
6078  
6079 static int rpc_trustdom_usage(int argc, const char **argv)
6080 {
6081         d_printf("  net rpc trustdom add \t\t add trusting domain's account\n");
6082         d_printf("  net rpc trustdom del \t\t delete trusting domain's account\n");
6083         d_printf("  net rpc trustdom establish \t establish relationship to trusted domain\n");
6084         d_printf("  net rpc trustdom revoke \t abandon relationship to trusted domain\n");
6085         d_printf("  net rpc trustdom list \t show current interdomain trust relationships\n");
6086         d_printf("  net rpc trustdom vampire \t vampire interdomain trust relationships from remote server\n");
6087         return -1;
6088 }
6089
6090
6091 static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, 
6092                                         const char *domain_name, 
6093                                         struct cli_state *cli,
6094                                         struct rpc_pipe_client *pipe_hnd,
6095                                         TALLOC_CTX *mem_ctx,
6096                                         int argc,
6097                                         const char **argv)
6098 {
6099         fstring str_sid;
6100         sid_to_fstring(str_sid, domain_sid);
6101         d_printf("%s\n", str_sid);
6102         return NT_STATUS_OK;
6103 }
6104
6105 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
6106 {
6107         fstring ascii_sid, padding;
6108         int pad_len, col_len = 20;
6109
6110         /* convert sid into ascii string */
6111         sid_to_fstring(ascii_sid, dom_sid);
6112
6113         /* calculate padding space for d_printf to look nicer */
6114         pad_len = col_len - strlen(trusted_dom_name);
6115         padding[pad_len] = 0;
6116         do padding[--pad_len] = ' '; while (pad_len);
6117                         
6118         d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
6119 }
6120
6121 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6122                                       TALLOC_CTX *mem_ctx, 
6123                                       POLICY_HND *pol, 
6124                                       DOM_SID dom_sid, 
6125                                       const char *trusted_dom_name)
6126 {
6127         NTSTATUS nt_status;
6128         union lsa_TrustedDomainInfo info;
6129         char *cleartextpwd = NULL;
6130         DATA_BLOB data;
6131
6132         nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
6133                                                            pol,
6134                                                            &dom_sid,
6135                                                            LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6136                                                            &info);
6137         if (NT_STATUS_IS_ERR(nt_status)) {
6138                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6139                 nt_errstr(nt_status)));
6140                 goto done;
6141         }
6142
6143         data = data_blob(NULL, info.password.password->length);
6144
6145         memcpy(data.data,
6146                info.password.password->data,
6147                info.password.password->length);
6148         data.length = info.password.password->length;
6149
6150         cleartextpwd = decrypt_trustdom_secret(pipe_hnd->cli->pwd.password,
6151                                                &data);
6152
6153         if (cleartextpwd == NULL) {
6154                 DEBUG(0,("retrieved NULL password\n"));
6155                 nt_status = NT_STATUS_UNSUCCESSFUL;
6156                 goto done;
6157         }
6158         
6159         if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6160                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6161                 nt_status = NT_STATUS_UNSUCCESSFUL;
6162                 goto done;
6163         }
6164
6165 #ifdef DEBUG_PASSWORD
6166         DEBUG(100,("sucessfully vampired trusted domain [%s], sid: [%s], "
6167                    "password: [%s]\n", trusted_dom_name,
6168                    sid_string_dbg(&dom_sid), cleartextpwd));
6169 #endif
6170
6171 done:
6172         SAFE_FREE(cleartextpwd);
6173         data_blob_free(&data);
6174
6175         return nt_status;
6176 }
6177
6178 static int rpc_trustdom_vampire(int argc, const char **argv)
6179 {
6180         /* common variables */
6181         TALLOC_CTX* mem_ctx;
6182         struct cli_state *cli = NULL;
6183         struct rpc_pipe_client *pipe_hnd = NULL;
6184         NTSTATUS nt_status;
6185         const char *domain_name = NULL;
6186         DOM_SID *queried_dom_sid;
6187         POLICY_HND connect_hnd;
6188         union lsa_PolicyInformation *info = NULL;
6189
6190         /* trusted domains listing variables */
6191         unsigned int num_domains, enum_ctx = 0;
6192         int i;
6193         DOM_SID *domain_sids;
6194         char **trusted_dom_names;
6195         fstring pdc_name;
6196
6197         /*
6198          * Listing trusted domains (stored in secrets.tdb, if local)
6199          */
6200
6201         mem_ctx = talloc_init("trust relationships vampire");
6202
6203         /*
6204          * set domain and pdc name to local samba server (default)
6205          * or to remote one given in command line
6206          */
6207
6208         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
6209                 domain_name = opt_workgroup;
6210                 opt_target_workgroup = opt_workgroup;
6211         } else {
6212                 fstrcpy(pdc_name, global_myname());
6213                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6214                 opt_target_workgroup = domain_name;
6215         };
6216
6217         /* open \PIPE\lsarpc and open policy handle */
6218         nt_status = net_make_ipc_connection(NET_FLAGS_PDC, &cli);
6219         if (!NT_STATUS_IS_OK(nt_status)) {
6220                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6221                           nt_errstr(nt_status)));
6222                 talloc_destroy(mem_ctx);
6223                 return -1;
6224         };
6225
6226         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
6227         if (!pipe_hnd) {
6228                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6229                         nt_errstr(nt_status) ));
6230                 cli_shutdown(cli);
6231                 talloc_destroy(mem_ctx);
6232                 return -1;
6233         };
6234
6235         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
6236                                         &connect_hnd);
6237         if (NT_STATUS_IS_ERR(nt_status)) {
6238                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6239                         nt_errstr(nt_status)));
6240                 cli_shutdown(cli);
6241                 talloc_destroy(mem_ctx);
6242                 return -1;
6243         };
6244
6245         /* query info level 5 to obtain sid of a domain being queried */
6246         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6247                                                &connect_hnd,
6248                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6249                                                &info);
6250
6251         if (NT_STATUS_IS_ERR(nt_status)) {
6252                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6253                         nt_errstr(nt_status)));
6254                 cli_shutdown(cli);
6255                 talloc_destroy(mem_ctx);
6256                 return -1;
6257         }
6258
6259         queried_dom_sid = info->account_domain.sid;
6260
6261         /*
6262          * Keep calling LsaEnumTrustdom over opened pipe until
6263          * the end of enumeration is reached
6264          */
6265
6266         d_printf("Vampire trusted domains:\n\n");
6267
6268         do {
6269                 nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
6270                                                    &num_domains,
6271                                                    &trusted_dom_names, &domain_sids);
6272                 
6273                 if (NT_STATUS_IS_ERR(nt_status)) {
6274                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6275                                 nt_errstr(nt_status)));
6276                         cli_shutdown(cli);
6277                         talloc_destroy(mem_ctx);
6278                         return -1;
6279                 };
6280                 
6281                 for (i = 0; i < num_domains; i++) {
6282
6283                         print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
6284
6285                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
6286                                                            domain_sids[i], trusted_dom_names[i]);
6287                         if (!NT_STATUS_IS_OK(nt_status)) {
6288                                 cli_shutdown(cli);
6289                                 talloc_destroy(mem_ctx);
6290                                 return -1;
6291                         }
6292                 };
6293
6294                 /*
6295                  * in case of no trusted domains say something rather
6296                  * than just display blank line
6297                  */
6298                 if (!num_domains) d_printf("none\n");
6299
6300         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6301
6302         /* close this connection before doing next one */
6303         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6304         if (NT_STATUS_IS_ERR(nt_status)) {
6305                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6306                         nt_errstr(nt_status)));
6307                 cli_shutdown(cli);
6308                 talloc_destroy(mem_ctx);
6309                 return -1;
6310         };
6311
6312         /* close lsarpc pipe and connection to IPC$ */
6313         cli_shutdown(cli);
6314
6315         talloc_destroy(mem_ctx);         
6316         return 0;
6317 }
6318
6319 static int rpc_trustdom_list(int argc, const char **argv)
6320 {
6321         /* common variables */
6322         TALLOC_CTX* mem_ctx;
6323         struct cli_state *cli = NULL, *remote_cli = NULL;
6324         struct rpc_pipe_client *pipe_hnd = NULL;
6325         NTSTATUS nt_status;
6326         const char *domain_name = NULL;
6327         DOM_SID *queried_dom_sid;
6328         fstring padding;
6329         int ascii_dom_name_len;
6330         POLICY_HND connect_hnd;
6331         union lsa_PolicyInformation *info = NULL;
6332
6333         /* trusted domains listing variables */
6334         unsigned int num_domains, enum_ctx = 0;
6335         int i, pad_len, col_len = 20;
6336         DOM_SID *domain_sids;
6337         char **trusted_dom_names;
6338         fstring pdc_name;
6339
6340         /* trusting domains listing variables */
6341         POLICY_HND domain_hnd;
6342         char **trusting_dom_names;
6343         uint32 *trusting_dom_rids;
6344         
6345         /*
6346          * Listing trusted domains (stored in secrets.tdb, if local)
6347          */
6348
6349         mem_ctx = talloc_init("trust relationships listing");
6350
6351         /*
6352          * set domain and pdc name to local samba server (default)
6353          * or to remote one given in command line
6354          */
6355         
6356         if (StrCaseCmp(opt_workgroup, lp_workgroup())) {
6357                 domain_name = opt_workgroup;
6358                 opt_target_workgroup = opt_workgroup;
6359         } else {
6360                 fstrcpy(pdc_name, global_myname());
6361                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6362                 opt_target_workgroup = domain_name;
6363         };
6364
6365         /* open \PIPE\lsarpc and open policy handle */
6366         nt_status = net_make_ipc_connection(NET_FLAGS_PDC, &cli);
6367         if (!NT_STATUS_IS_OK(nt_status)) {
6368                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6369                           nt_errstr(nt_status)));
6370                 talloc_destroy(mem_ctx);
6371                 return -1;
6372         };
6373
6374         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
6375         if (!pipe_hnd) {
6376                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6377                         nt_errstr(nt_status) ));
6378                 cli_shutdown(cli);
6379                 talloc_destroy(mem_ctx);
6380                 return -1;
6381         };
6382
6383         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
6384                                         &connect_hnd);
6385         if (NT_STATUS_IS_ERR(nt_status)) {
6386                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6387                         nt_errstr(nt_status)));
6388                 cli_shutdown(cli);
6389                 talloc_destroy(mem_ctx);
6390                 return -1;
6391         };
6392         
6393         /* query info level 5 to obtain sid of a domain being queried */
6394         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6395                                                &connect_hnd,
6396                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6397                                                &info);
6398
6399         if (NT_STATUS_IS_ERR(nt_status)) {
6400                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6401                         nt_errstr(nt_status)));
6402                 cli_shutdown(cli);
6403                 talloc_destroy(mem_ctx);
6404                 return -1;
6405         }
6406
6407         queried_dom_sid = info->account_domain.sid;
6408
6409         /*
6410          * Keep calling LsaEnumTrustdom over opened pipe until
6411          * the end of enumeration is reached
6412          */
6413          
6414         d_printf("Trusted domains list:\n\n");
6415
6416         do {
6417                 nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
6418                                                    &num_domains,
6419                                                    &trusted_dom_names, &domain_sids);
6420                 
6421                 if (NT_STATUS_IS_ERR(nt_status)) {
6422                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6423                                 nt_errstr(nt_status)));
6424                         cli_shutdown(cli);
6425                         talloc_destroy(mem_ctx);
6426                         return -1;
6427                 };
6428                 
6429                 for (i = 0; i < num_domains; i++) {
6430                         print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
6431                 };
6432                 
6433                 /*
6434                  * in case of no trusted domains say something rather
6435                  * than just display blank line
6436                  */
6437                 if (!num_domains) d_printf("none\n");
6438
6439         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6440
6441         /* close this connection before doing next one */
6442         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6443         if (NT_STATUS_IS_ERR(nt_status)) {
6444                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6445                         nt_errstr(nt_status)));
6446                 cli_shutdown(cli);
6447                 talloc_destroy(mem_ctx);
6448                 return -1;
6449         };
6450         
6451         cli_rpc_pipe_close(pipe_hnd);
6452
6453         /*
6454          * Listing trusting domains (stored in passdb backend, if local)
6455          */
6456         
6457         d_printf("\nTrusting domains list:\n\n");
6458
6459         /*
6460          * Open \PIPE\samr and get needed policy handles
6461          */
6462         pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status);
6463         if (!pipe_hnd) {
6464                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6465                 cli_shutdown(cli);
6466                 talloc_destroy(mem_ctx);
6467                 return -1;
6468         };
6469
6470         /* SamrConnect2 */
6471         nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6472                                          pipe_hnd->cli->desthost,
6473                                          SA_RIGHT_SAM_OPEN_DOMAIN,
6474                                          &connect_hnd);
6475         if (!NT_STATUS_IS_OK(nt_status)) {
6476                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6477                         nt_errstr(nt_status)));
6478                 cli_shutdown(cli);
6479                 talloc_destroy(mem_ctx);
6480                 return -1;
6481         };
6482
6483         /* SamrOpenDomain - we have to open domain policy handle in order to be
6484            able to enumerate accounts*/
6485         nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6486                                            &connect_hnd,
6487                                            SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
6488                                            queried_dom_sid,
6489                                            &domain_hnd);
6490         if (!NT_STATUS_IS_OK(nt_status)) {
6491                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6492                         nt_errstr(nt_status)));
6493                 cli_shutdown(cli);
6494                 talloc_destroy(mem_ctx);
6495                 return -1;
6496         };
6497         
6498         /*
6499          * perform actual enumeration
6500          */
6501          
6502         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6503         do {
6504                         
6505                 nt_status = rpccli_samr_enum_dom_users(pipe_hnd, mem_ctx, &domain_hnd,
6506                                                     &enum_ctx, ACB_DOMTRUST, 0xffff,
6507                                                     &trusting_dom_names, &trusting_dom_rids,
6508                                                     &num_domains);
6509                 if (NT_STATUS_IS_ERR(nt_status)) {
6510                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6511                                 nt_errstr(nt_status)));
6512                         cli_shutdown(cli);
6513                         talloc_destroy(mem_ctx);
6514                         return -1;
6515                 };
6516                 
6517                 for (i = 0; i < num_domains; i++) {
6518
6519                         /*
6520                          * get each single domain's sid (do we _really_ need this ?):
6521                          *  1) connect to domain's pdc
6522                          *  2) query the pdc for domain's sid
6523                          */
6524
6525                         /* get rid of '$' tail */
6526                         ascii_dom_name_len = strlen(trusting_dom_names[i]);
6527                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6528                                 trusting_dom_names[i][ascii_dom_name_len - 1] = '\0';
6529                         
6530                         /* calculate padding space for d_printf to look nicer */
6531                         pad_len = col_len - strlen(trusting_dom_names[i]);
6532                         padding[pad_len] = 0;
6533                         do padding[--pad_len] = ' '; while (pad_len);
6534
6535                         /* set opt_* variables to remote domain */
6536                         strupper_m(trusting_dom_names[i]);
6537                         opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]);
6538                         opt_target_workgroup = opt_workgroup;
6539                         
6540                         d_printf("%s%s", trusting_dom_names[i], padding);
6541                         
6542                         /* connect to remote domain controller */
6543                         nt_status = net_make_ipc_connection(
6544                                         NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6545                                         &remote_cli);
6546                         if (NT_STATUS_IS_OK(nt_status)) {
6547                                 /* query for domain's sid */
6548                                 if (run_rpc_command(remote_cli, PI_LSARPC, 0, rpc_query_domain_sid, argc, argv))
6549                                         d_fprintf(stderr, "couldn't get domain's sid\n");
6550
6551                                 cli_shutdown(remote_cli);
6552                         
6553                         } else {
6554                                 d_fprintf(stderr, "domain controller is not "
6555                                           "responding: %s\n",
6556                                           nt_errstr(nt_status));
6557                         };
6558                 };
6559                 
6560                 if (!num_domains) d_printf("none\n");
6561                 
6562         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6563
6564         /* close opened samr and domain policy handles */
6565         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6566         if (!NT_STATUS_IS_OK(nt_status)) {
6567                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6568         };
6569         
6570         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6571         if (!NT_STATUS_IS_OK(nt_status)) {
6572                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6573         };
6574         
6575         /* close samr pipe and connection to IPC$ */
6576         cli_shutdown(cli);
6577
6578         talloc_destroy(mem_ctx);         
6579         return 0;
6580 }
6581
6582 /**
6583  * Entrypoint for 'net rpc trustdom' code
6584  *
6585  * @param argc standard argc
6586  * @param argv standard argv without initial components
6587  *
6588  * @return Integer status (0 means success)
6589  */
6590
6591 static int rpc_trustdom(int argc, const char **argv)
6592 {
6593         struct functable func[] = {
6594                 {"add", rpc_trustdom_add},
6595                 {"del", rpc_trustdom_del},
6596                 {"establish", rpc_trustdom_establish},
6597                 {"revoke", rpc_trustdom_revoke},
6598                 {"help", rpc_trustdom_usage},
6599                 {"list", rpc_trustdom_list},
6600                 {"vampire", rpc_trustdom_vampire},
6601                 {NULL, NULL}
6602         };
6603
6604         if (argc == 0) {
6605                 rpc_trustdom_usage(argc, argv);
6606                 return -1;
6607         }
6608
6609         return (net_run_function(argc, argv, func, rpc_user_usage));
6610 }
6611
6612 /**
6613  * Check if a server will take rpc commands
6614  * @param flags Type of server to connect to (PDC, DMB, localhost)
6615  *              if the host is not explicitly specified
6616  * @return  bool (true means rpc supported)
6617  */
6618 bool net_rpc_check(unsigned flags)
6619 {
6620         struct cli_state *cli;
6621         bool ret = False;
6622         struct sockaddr_storage server_ss;
6623         char *server_name = NULL;
6624         NTSTATUS status;
6625
6626         /* flags (i.e. server type) may depend on command */
6627         if (!net_find_server(NULL, flags, &server_ss, &server_name))
6628                 return False;
6629
6630         if ((cli = cli_initialise()) == NULL) {
6631                 return False;
6632         }
6633
6634         status = cli_connect(cli, server_name, &server_ss);
6635         if (!NT_STATUS_IS_OK(status))
6636                 goto done;
6637         if (!attempt_netbios_session_request(&cli, global_myname(),
6638                                              server_name, &server_ss))
6639                 goto done;
6640         if (!cli_negprot(cli))
6641                 goto done;
6642         if (cli->protocol < PROTOCOL_NT1)
6643                 goto done;
6644
6645         ret = True;
6646  done:
6647         cli_shutdown(cli);
6648         return ret;
6649 }
6650
6651 /* dump sam database via samsync rpc calls */
6652 static int rpc_samdump(int argc, const char **argv) {
6653                 return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
6654                                argc, argv);
6655 }
6656
6657 /* syncronise sam database via samsync rpc calls */
6658 static int rpc_vampire(int argc, const char **argv) {
6659         return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_vampire_internals,
6660                                argc, argv);
6661 }
6662
6663 /** 
6664  * Migrate everything from a print-server
6665  *
6666  * @param argc  Standard main() style argc
6667  * @param argv  Standard main() style argv.  Initial components are already
6668  *              stripped
6669  *
6670  * @return A shell status integer (0 for success)
6671  *
6672  * The order is important !
6673  * To successfully add drivers the print-queues have to exist !
6674  * Applying ACLs should be the last step, because you're easily locked out
6675  *
6676  **/
6677 static int rpc_printer_migrate_all(int argc, const char **argv)
6678 {
6679         int ret;
6680
6681         if (!opt_host) {
6682                 printf("no server to migrate\n");
6683                 return -1;
6684         }
6685
6686         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv);
6687         if (ret)
6688                 return ret;
6689
6690         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, argc, argv);
6691         if (ret)
6692                 return ret;
6693
6694         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, argc, argv);
6695         if (ret)
6696                 return ret;
6697
6698         ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, argc, argv);
6699         if (ret)
6700                 return ret;
6701
6702         return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, argc, argv);
6703
6704 }
6705
6706 /** 
6707  * Migrate print-drivers from a print-server
6708  *
6709  * @param argc  Standard main() style argc
6710  * @param argv  Standard main() style argv.  Initial components are already
6711  *              stripped
6712  *
6713  * @return A shell status integer (0 for success)
6714  **/
6715 static int rpc_printer_migrate_drivers(int argc, const char **argv)
6716 {
6717         if (!opt_host) {
6718                 printf("no server to migrate\n");
6719                 return -1;
6720         }
6721
6722         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6723                                rpc_printer_migrate_drivers_internals,
6724                                argc, argv);
6725 }
6726
6727 /** 
6728  * Migrate print-forms from a print-server
6729  *
6730  * @param argc  Standard main() style argc
6731  * @param argv  Standard main() style argv.  Initial components are already
6732  *              stripped
6733  *
6734  * @return A shell status integer (0 for success)
6735  **/
6736 static int rpc_printer_migrate_forms(int argc, const char **argv)
6737 {
6738         if (!opt_host) {
6739                 printf("no server to migrate\n");
6740                 return -1;
6741         }
6742
6743         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6744                                rpc_printer_migrate_forms_internals,
6745                                argc, argv);
6746 }
6747
6748 /** 
6749  * Migrate printers from a print-server
6750  *
6751  * @param argc  Standard main() style argc
6752  * @param argv  Standard main() style argv.  Initial components are already
6753  *              stripped
6754  *
6755  * @return A shell status integer (0 for success)
6756  **/
6757 static int rpc_printer_migrate_printers(int argc, const char **argv)
6758 {
6759         if (!opt_host) {
6760                 printf("no server to migrate\n");
6761                 return -1;
6762         }
6763
6764         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6765                                rpc_printer_migrate_printers_internals,
6766                                argc, argv);
6767 }
6768
6769 /** 
6770  * Migrate printer-ACLs from a print-server
6771  *
6772  * @param argc  Standard main() style argc
6773  * @param argv  Standard main() style argv.  Initial components are already
6774  *              stripped
6775  *
6776  * @return A shell status integer (0 for success)
6777  **/
6778 static int rpc_printer_migrate_security(int argc, const char **argv)
6779 {
6780         if (!opt_host) {
6781                 printf("no server to migrate\n");
6782                 return -1;
6783         }
6784
6785         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6786                                rpc_printer_migrate_security_internals,
6787                                argc, argv);
6788 }
6789
6790 /** 
6791  * Migrate printer-settings from a print-server
6792  *
6793  * @param argc  Standard main() style argc
6794  * @param argv  Standard main() style argv.  Initial components are already
6795  *              stripped
6796  *
6797  * @return A shell status integer (0 for success)
6798  **/
6799 static int rpc_printer_migrate_settings(int argc, const char **argv)
6800 {
6801         if (!opt_host) {
6802                 printf("no server to migrate\n");
6803                 return -1;
6804         }
6805
6806         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6807                                rpc_printer_migrate_settings_internals,
6808                                argc, argv);
6809 }
6810
6811 /** 
6812  * 'net rpc printer' entrypoint.
6813  * @param argc  Standard main() style argc
6814  * @param argv  Standard main() style argv.  Initial components are already
6815  *              stripped
6816  **/
6817
6818 int rpc_printer_migrate(int argc, const char **argv) 
6819 {
6820
6821         /* ouch: when addriver and setdriver are called from within
6822            rpc_printer_migrate_drivers_internals, the printer-queue already
6823            *has* to exist */
6824
6825         struct functable func[] = {
6826                 {"all",         rpc_printer_migrate_all},
6827                 {"drivers",     rpc_printer_migrate_drivers},
6828                 {"forms",       rpc_printer_migrate_forms},
6829                 {"help",        rpc_printer_usage},
6830                 {"printers",    rpc_printer_migrate_printers},
6831                 {"security",    rpc_printer_migrate_security},
6832                 {"settings",    rpc_printer_migrate_settings},
6833                 {NULL, NULL}
6834         };
6835
6836         return net_run_function(argc, argv, func, rpc_printer_usage);
6837 }
6838
6839
6840 /** 
6841  * List printers on a remote RPC server
6842  *
6843  * @param argc  Standard main() style argc
6844  * @param argv  Standard main() style argv.  Initial components are already
6845  *              stripped
6846  *
6847  * @return A shell status integer (0 for success)
6848  **/
6849 static int rpc_printer_list(int argc, const char **argv)
6850 {
6851
6852         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6853                                rpc_printer_list_internals,
6854                                argc, argv);
6855 }
6856
6857 /** 
6858  * List printer-drivers on a remote RPC server
6859  *
6860  * @param argc  Standard main() style argc
6861  * @param argv  Standard main() style argv.  Initial components are already
6862  *              stripped
6863  *
6864  * @return A shell status integer (0 for success)
6865  **/
6866 static int rpc_printer_driver_list(int argc, const char **argv)
6867 {
6868
6869         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6870                                rpc_printer_driver_list_internals,
6871                                argc, argv);
6872 }
6873
6874 /** 
6875  * Publish printer in ADS via MSRPC
6876  *
6877  * @param argc  Standard main() style argc
6878  * @param argv  Standard main() style argv.  Initial components are already
6879  *              stripped
6880  *
6881  * @return A shell status integer (0 for success)
6882  **/
6883 static int rpc_printer_publish_publish(int argc, const char **argv)
6884 {
6885
6886         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6887                                rpc_printer_publish_publish_internals,
6888                                argc, argv);
6889 }
6890
6891 /** 
6892  * Update printer in ADS via MSRPC
6893  *
6894  * @param argc  Standard main() style argc
6895  * @param argv  Standard main() style argv.  Initial components are already
6896  *              stripped
6897  *
6898  * @return A shell status integer (0 for success)
6899  **/
6900 static int rpc_printer_publish_update(int argc, const char **argv)
6901 {
6902
6903         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6904                                rpc_printer_publish_update_internals,
6905                                argc, argv);
6906 }
6907
6908 /** 
6909  * UnPublish printer in ADS via MSRPC
6910  *
6911  * @param argc  Standard main() style argc
6912  * @param argv  Standard main() style argv.  Initial components are already
6913  *              stripped
6914  *
6915  * @return A shell status integer (0 for success)
6916  **/
6917 static int rpc_printer_publish_unpublish(int argc, const char **argv)
6918 {
6919
6920         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6921                                rpc_printer_publish_unpublish_internals,
6922                                argc, argv);
6923 }
6924
6925 /** 
6926  * List published printers via MSRPC
6927  *
6928  * @param argc  Standard main() style argc
6929  * @param argv  Standard main() style argv.  Initial components are already
6930  *              stripped
6931  *
6932  * @return A shell status integer (0 for success)
6933  **/
6934 static int rpc_printer_publish_list(int argc, const char **argv)
6935 {
6936
6937         return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6938                                rpc_printer_publish_list_internals,
6939                                argc, argv);
6940 }
6941
6942
6943 /** 
6944  * Publish printer in ADS
6945  *
6946  * @param argc  Standard main() style argc
6947  * @param argv  Standard main() style argv.  Initial components are already
6948  *              stripped
6949  *
6950  * @return A shell status integer (0 for success)
6951  **/
6952 static int rpc_printer_publish(int argc, const char **argv)
6953 {
6954
6955         struct functable func[] = {
6956                 {"publish",     rpc_printer_publish_publish},
6957                 {"update",      rpc_printer_publish_update},
6958                 {"unpublish",   rpc_printer_publish_unpublish},
6959                 {"list",        rpc_printer_publish_list},
6960                 {"help",        rpc_printer_usage},
6961                 {NULL, NULL}
6962         };
6963
6964         if (argc == 0)
6965                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
6966                                rpc_printer_publish_list_internals,
6967                                argc, argv);
6968
6969         return net_run_function(argc, argv, func, rpc_printer_usage);
6970
6971 }
6972
6973
6974 /** 
6975  * Display rpc printer help page.
6976  * @param argc  Standard main() style argc
6977  * @param argv  Standard main() style argv.  Initial components are already
6978  *              stripped
6979  **/
6980 int rpc_printer_usage(int argc, const char **argv)
6981 {
6982         return net_help_printer(argc, argv);
6983 }
6984
6985 /** 
6986  * 'net rpc printer' entrypoint.
6987  * @param argc  Standard main() style argc
6988  * @param argv  Standard main() style argv.  Initial components are already
6989  *              stripped
6990  **/
6991 int net_rpc_printer(int argc, const char **argv) 
6992 {
6993         struct functable func[] = {
6994                 {"list", rpc_printer_list},
6995                 {"migrate", rpc_printer_migrate},
6996                 {"driver", rpc_printer_driver_list},
6997                 {"publish", rpc_printer_publish},
6998                 {NULL, NULL}
6999         };
7000
7001         if (argc == 0)
7002                 return run_rpc_command(NULL, PI_SPOOLSS, 0, 
7003                                rpc_printer_list_internals,
7004                                argc, argv);
7005
7006         return net_run_function(argc, argv, func, rpc_printer_usage);
7007 }
7008
7009 /****************************************************************************/
7010
7011
7012 /** 
7013  * Basic usage function for 'net rpc'
7014  * @param argc  Standard main() style argc
7015  * @param argv  Standard main() style argv.  Initial components are already
7016  *              stripped
7017  **/
7018
7019 int net_rpc_usage(int argc, const char **argv) 
7020 {
7021         d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
7022         d_printf("  net rpc join \t\t\tto join a domain \n");
7023         d_printf("  net rpc oldjoin \t\tto join a domain created in server manager\n");
7024         d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
7025         d_printf("  net rpc user \t\t\tto add, delete and list users\n");
7026         d_printf("  net rpc password <username> [<password>] -Uadmin_username%%admin_pass\n");
7027         d_printf("  net rpc group \t\tto list groups\n");
7028         d_printf("  net rpc share \t\tto add, delete, list and migrate shares\n");
7029         d_printf("  net rpc printer \t\tto list and migrate printers\n");
7030         d_printf("  net rpc file \t\t\tto list open files\n");
7031         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
7032         d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
7033         d_printf("  net rpc vampire \t\tsyncronise an NT PDC's users and groups into the local passdb\n");
7034         d_printf("  net rpc samdump \t\tdisplay an NT PDC's users, groups and other data\n");
7035         d_printf("  net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
7036         d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
7037         d_printf("  net rpc shutdown \t\tto shutdown a remote server\n");
7038         d_printf("  net rpc rights\t\tto manage privileges assigned to SIDs\n");
7039         d_printf("  net rpc registry\t\tto manage registry hives\n");
7040         d_printf("  net rpc service\t\tto start, stop and query services\n");
7041         d_printf("  net rpc audit\t\t\tto modify global auditing settings\n");
7042         d_printf("  net rpc shell\t\t\tto open an interactive shell for remote server/account management\n");
7043         d_printf("\n");
7044         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
7045         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
7046         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
7047         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
7048         d_printf("\t-C or --comment=<message>\ttext message to display on impending shutdown\n");
7049         return -1;
7050 }
7051
7052
7053 /**
7054  * Help function for 'net rpc'.  Calls command specific help if requested
7055  * or displays usage of net rpc
7056  * @param argc  Standard main() style argc
7057  * @param argv  Standard main() style argv.  Initial components are already
7058  *              stripped
7059  **/
7060
7061 int net_rpc_help(int argc, const char **argv)
7062 {
7063         struct functable func[] = {
7064                 {"join", rpc_join_usage},
7065                 {"user", rpc_user_usage},
7066                 {"group", rpc_group_usage},
7067                 {"share", rpc_share_usage},
7068                 /*{"changetrustpw", rpc_changetrustpw_usage}, */
7069                 {"trustdom", rpc_trustdom_usage},
7070                 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
7071                 /*{"shutdown", rpc_shutdown_usage}, */
7072                 {"vampire", rpc_vampire_usage},
7073                 {NULL, NULL}
7074         };
7075
7076         if (argc == 0) {
7077                 net_rpc_usage(argc, argv);
7078                 return -1;
7079         }
7080
7081         return (net_run_function(argc, argv, func, rpc_user_usage));
7082 }
7083
7084 /** 
7085  * 'net rpc' entrypoint.
7086  * @param argc  Standard main() style argc
7087  * @param argv  Standard main() style argv.  Initial components are already
7088  *              stripped
7089  **/
7090
7091 int net_rpc(int argc, const char **argv)
7092 {
7093         struct functable func[] = {
7094                 {"audit", net_rpc_audit},
7095                 {"info", net_rpc_info},
7096                 {"join", net_rpc_join},
7097                 {"oldjoin", net_rpc_oldjoin},
7098                 {"testjoin", net_rpc_testjoin},
7099                 {"user", net_rpc_user},
7100                 {"password", rpc_user_password},
7101                 {"group", net_rpc_group},
7102                 {"share", net_rpc_share},
7103                 {"file", net_rpc_file},
7104                 {"printer", net_rpc_printer},
7105                 {"changetrustpw", net_rpc_changetrustpw},
7106                 {"trustdom", rpc_trustdom},
7107                 {"abortshutdown", rpc_shutdown_abort},
7108                 {"shutdown", rpc_shutdown},
7109                 {"samdump", rpc_samdump},
7110                 {"vampire", rpc_vampire},
7111                 {"getsid", net_rpc_getsid},
7112                 {"rights", net_rpc_rights},
7113                 {"service", net_rpc_service},
7114                 {"registry", net_rpc_registry},
7115                 {"shell", net_rpc_shell},
7116                 {"help", net_rpc_help},
7117                 {NULL, NULL}
7118         };
7119         return net_run_function(argc, argv, func, net_rpc_usage);
7120 }