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