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