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