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