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