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