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