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