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