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