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