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