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