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