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