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