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