s3-net: prefer dcerpc_samr_X functions in rpc_sh_user_flag_edit_internals.
[ira/wip.git] / source3 / utils / net_rpc.c
1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
6    Copyright (C) 2004,2008 Guenther Deschner (gd@samba.org)
7    Copyright (C) 2005 Jeremy Allison (jra@samba.org)
8    Copyright (C) 2006 Jelmer Vernooij (jelmer@samba.org)
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
23 #include "includes.h"
24 #include "utils/net.h"
25 #include "../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 result = NT_STATUS_UNSUCCESSFUL;
1576         uint32_t group_rid;
1577         struct samr_RidAttrArray *rids = NULL;
1578         /* char **names; */
1579         int i;
1580         /* struct samr_RidWithAttribute *user_gids; */
1581
1582         struct samr_Ids group_rids, name_types;
1583         struct lsa_String lsa_acct_name;
1584         union samr_UserInfo *info = NULL;
1585
1586         if (argc < 1 || c->display_usage) {
1587                 rpc_group_usage(c, argc,argv);
1588                 return NT_STATUS_OK; /* ok? */
1589         }
1590
1591         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1592                                       pipe_hnd->desthost,
1593                                       MAXIMUM_ALLOWED_ACCESS,
1594                                       &connect_pol);
1595
1596         if (!NT_STATUS_IS_OK(result)) {
1597                 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1598                 goto done;
1599         }
1600
1601         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1602                                         &connect_pol,
1603                                         MAXIMUM_ALLOWED_ACCESS,
1604                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1605                                         &domain_pol);
1606
1607         if (!NT_STATUS_IS_OK(result)) {
1608                 d_fprintf(stderr, _("Request open_domain failed\n"));
1609                 goto done;
1610         }
1611
1612         init_lsa_String(&lsa_acct_name, argv[0]);
1613
1614         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1615                                          &domain_pol,
1616                                          1,
1617                                          &lsa_acct_name,
1618                                          &group_rids,
1619                                          &name_types);
1620         if (!NT_STATUS_IS_OK(result)) {
1621                 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1622                 goto done;
1623         }
1624
1625         switch (name_types.ids[0])
1626         {
1627         case SID_NAME_DOM_GRP:
1628                 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1629                                                &domain_pol,
1630                                                MAXIMUM_ALLOWED_ACCESS,
1631                                                group_rids.ids[0],
1632                                                &group_pol);
1633                 if (!NT_STATUS_IS_OK(result)) {
1634                         d_fprintf(stderr, _("Request open_group failed"));
1635                         goto done;
1636                 }
1637
1638                 group_rid = group_rids.ids[0];
1639
1640                 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
1641                                                       &group_pol,
1642                                                       &rids);
1643
1644                 if (!NT_STATUS_IS_OK(result)) {
1645                         d_fprintf(stderr,
1646                                   _("Unable to query group members of %s"),
1647                                   argv[0]);
1648                         goto done;
1649                 }
1650
1651                 if (c->opt_verbose) {
1652                         d_printf(
1653                                 _("Domain Group %s (rid: %d) has %d members\n"),
1654                                 argv[0],group_rid, rids->count);
1655                 }
1656
1657                 /* Check if group is anyone's primary group */
1658                 for (i = 0; i < rids->count; i++)
1659                 {
1660                         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1661                                                       &domain_pol,
1662                                                       MAXIMUM_ALLOWED_ACCESS,
1663                                                       rids->rids[i],
1664                                                       &user_pol);
1665
1666                         if (!NT_STATUS_IS_OK(result)) {
1667                                 d_fprintf(stderr,
1668                                         _("Unable to open group member %d\n"),
1669                                         rids->rids[i]);
1670                                 goto done;
1671                         }
1672
1673                         result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1674                                                            &user_pol,
1675                                                            21,
1676                                                            &info);
1677
1678                         if (!NT_STATUS_IS_OK(result)) {
1679                                 d_fprintf(stderr,
1680                                         _("Unable to lookup userinfo for group "
1681                                           "member %d\n"),
1682                                         rids->rids[i]);
1683                                 goto done;
1684                         }
1685
1686                         if (info->info21.primary_gid == group_rid) {
1687                                 if (c->opt_verbose) {
1688                                         d_printf(_("Group is primary group "
1689                                                    "of %s\n"),
1690                                                 info->info21.account_name.string);
1691                                 }
1692                                 group_is_primary = true;
1693                         }
1694
1695                         rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1696                 }
1697
1698                 if (group_is_primary) {
1699                         d_fprintf(stderr, _("Unable to delete group because "
1700                                  "some of it's members have it as primary "
1701                                  "group\n"));
1702                         result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1703                         goto done;
1704                 }
1705
1706                 /* remove all group members */
1707                 for (i = 0; i < rids->count; i++)
1708                 {
1709                         if (c->opt_verbose)
1710                                 d_printf(_("Remove group member %d..."),
1711                                         rids->rids[i]);
1712                         result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
1713                                                                &group_pol,
1714                                                                rids->rids[i]);
1715
1716                         if (NT_STATUS_IS_OK(result)) {
1717                                 if (c->opt_verbose)
1718                                         d_printf(_("ok\n"));
1719                         } else {
1720                                 if (c->opt_verbose)
1721                                         d_printf("%s\n", _("failed"));
1722                                 goto done;
1723                         }
1724                 }
1725
1726                 result = rpccli_samr_DeleteDomainGroup(pipe_hnd, mem_ctx,
1727                                                        &group_pol);
1728
1729                 break;
1730         /* removing a local group is easier... */
1731         case SID_NAME_ALIAS:
1732                 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1733                                                &domain_pol,
1734                                                MAXIMUM_ALLOWED_ACCESS,
1735                                                group_rids.ids[0],
1736                                                &group_pol);
1737
1738                 if (!NT_STATUS_IS_OK(result)) {
1739                         d_fprintf(stderr, _("Request open_alias failed\n"));
1740                         goto done;
1741                 }
1742
1743                 result = rpccli_samr_DeleteDomAlias(pipe_hnd, mem_ctx,
1744                                                     &group_pol);
1745                 break;
1746         default:
1747                 d_fprintf(stderr, _("%s is of type %s. This command is only "
1748                                     "for deleting local or global groups\n"),
1749                         argv[0],sid_type_lookup(name_types.ids[0]));
1750                 result = NT_STATUS_UNSUCCESSFUL;
1751                 goto done;
1752         }
1753
1754         if (NT_STATUS_IS_OK(result)) {
1755                 if (c->opt_verbose)
1756                         d_printf(_("Deleted %s '%s'\n"),
1757                                  sid_type_lookup(name_types.ids[0]), argv[0]);
1758         } else {
1759                 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
1760                         get_friendly_nt_error_msg(result));
1761         }
1762
1763  done:
1764         return result;
1765
1766 }
1767
1768 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1769 {
1770         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1771                                rpc_group_delete_internals, argc,argv);
1772 }
1773
1774 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1775 {
1776         NET_API_STATUS status;
1777         struct GROUP_INFO_1 info1;
1778         uint32_t parm_error = 0;
1779
1780         if (argc != 1 || c->display_usage) {
1781                 rpc_group_usage(c, argc, argv);
1782                 return 0;
1783         }
1784
1785         ZERO_STRUCT(info1);
1786
1787         info1.grpi1_name = argv[0];
1788         if (c->opt_comment && strlen(c->opt_comment) > 0) {
1789                 info1.grpi1_comment = c->opt_comment;
1790         }
1791
1792         status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1793
1794         if (status != 0) {
1795                 d_fprintf(stderr,
1796                         _("Failed to add group '%s' with error: %s.\n"),
1797                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
1798                                                             status));
1799                 return -1;
1800         } else {
1801                 d_printf(_("Added group '%s'.\n"), argv[0]);
1802         }
1803
1804         return 0;
1805 }
1806
1807 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
1808 {
1809         NET_API_STATUS status;
1810         struct LOCALGROUP_INFO_1 info1;
1811         uint32_t parm_error = 0;
1812
1813         if (argc != 1 || c->display_usage) {
1814                 rpc_group_usage(c, argc, argv);
1815                 return 0;
1816         }
1817
1818         ZERO_STRUCT(info1);
1819
1820         info1.lgrpi1_name = argv[0];
1821         if (c->opt_comment && strlen(c->opt_comment) > 0) {
1822                 info1.lgrpi1_comment = c->opt_comment;
1823         }
1824
1825         status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1826
1827         if (status != 0) {
1828                 d_fprintf(stderr,
1829                         _("Failed to add alias '%s' with error: %s.\n"),
1830                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
1831                                                             status));
1832                 return -1;
1833         } else {
1834                 d_printf(_("Added alias '%s'.\n"), argv[0]);
1835         }
1836
1837         return 0;
1838 }
1839
1840 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1841 {
1842         if (c->opt_localgroup)
1843                 return rpc_alias_add_internals(c, argc, argv);
1844
1845         return rpc_group_add_internals(c, argc, argv);
1846 }
1847
1848 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1849                                 TALLOC_CTX *mem_ctx,
1850                                 const char *name,
1851                                 struct dom_sid *sid,
1852                                 enum lsa_SidType *type)
1853 {
1854         struct dom_sid *sids = NULL;
1855         enum lsa_SidType *types = NULL;
1856         struct rpc_pipe_client *pipe_hnd = NULL;
1857         struct policy_handle lsa_pol;
1858         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1859
1860         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1861                                           &pipe_hnd);
1862         if (!NT_STATUS_IS_OK(result)) {
1863                 goto done;
1864         }
1865
1866         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1867                                      SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1868
1869         if (!NT_STATUS_IS_OK(result)) {
1870                 goto done;
1871         }
1872
1873         result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1874                                       &name, NULL, 1, &sids, &types);
1875
1876         if (NT_STATUS_IS_OK(result)) {
1877                 sid_copy(sid, &sids[0]);
1878                 *type = types[0];
1879         }
1880
1881         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
1882
1883  done:
1884         if (pipe_hnd) {
1885                 TALLOC_FREE(pipe_hnd);
1886         }
1887
1888         if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
1889
1890                 /* Try as S-1-5-whatever */
1891
1892                 struct dom_sid tmp_sid;
1893
1894                 if (string_to_sid(&tmp_sid, name)) {
1895                         sid_copy(sid, &tmp_sid);
1896                         *type = SID_NAME_UNKNOWN;
1897                         result = NT_STATUS_OK;
1898                 }
1899         }
1900
1901         return result;
1902 }
1903
1904 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
1905                                 TALLOC_CTX *mem_ctx,
1906                                 const struct dom_sid *group_sid,
1907                                 const char *member)
1908 {
1909         struct policy_handle connect_pol, domain_pol;
1910         NTSTATUS result;
1911         uint32 group_rid;
1912         struct policy_handle group_pol;
1913
1914         struct samr_Ids rids, rid_types;
1915         struct lsa_String lsa_acct_name;
1916
1917         struct dom_sid sid;
1918
1919         sid_copy(&sid, group_sid);
1920
1921         if (!sid_split_rid(&sid, &group_rid)) {
1922                 return NT_STATUS_UNSUCCESSFUL;
1923         }
1924
1925         /* Get sam policy handle */
1926         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1927                                       pipe_hnd->desthost,
1928                                       MAXIMUM_ALLOWED_ACCESS,
1929                                       &connect_pol);
1930         if (!NT_STATUS_IS_OK(result)) {
1931                 return result;
1932         }
1933
1934         /* Get domain policy handle */
1935         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1936                                         &connect_pol,
1937                                         MAXIMUM_ALLOWED_ACCESS,
1938                                         &sid,
1939                                         &domain_pol);
1940         if (!NT_STATUS_IS_OK(result)) {
1941                 return result;
1942         }
1943
1944         init_lsa_String(&lsa_acct_name, member);
1945
1946         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1947                                          &domain_pol,
1948                                          1,
1949                                          &lsa_acct_name,
1950                                          &rids,
1951                                          &rid_types);
1952
1953         if (!NT_STATUS_IS_OK(result)) {
1954                 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
1955                           member);
1956                 goto done;
1957         }
1958
1959         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1960                                        &domain_pol,
1961                                        MAXIMUM_ALLOWED_ACCESS,
1962                                        group_rid,
1963                                        &group_pol);
1964
1965         if (!NT_STATUS_IS_OK(result)) {
1966                 goto done;
1967         }
1968
1969         result = rpccli_samr_AddGroupMember(pipe_hnd, mem_ctx,
1970                                             &group_pol,
1971                                             rids.ids[0],
1972                                             0x0005); /* unknown flags */
1973
1974  done:
1975         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1976         return result;
1977 }
1978
1979 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
1980                                 TALLOC_CTX *mem_ctx,
1981                                 const struct dom_sid *alias_sid,
1982                                 const char *member)
1983 {
1984         struct policy_handle connect_pol, domain_pol;
1985         NTSTATUS result;
1986         uint32 alias_rid;
1987         struct policy_handle alias_pol;
1988
1989         struct dom_sid member_sid;
1990         enum lsa_SidType member_type;
1991
1992         struct dom_sid sid;
1993
1994         sid_copy(&sid, alias_sid);
1995
1996         if (!sid_split_rid(&sid, &alias_rid)) {
1997                 return NT_STATUS_UNSUCCESSFUL;
1998         }
1999
2000         result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2001                                    member, &member_sid, &member_type);
2002
2003         if (!NT_STATUS_IS_OK(result)) {
2004                 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2005                           member);
2006                 return result;
2007         }
2008
2009         /* Get sam policy handle */
2010         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2011                                       pipe_hnd->desthost,
2012                                       MAXIMUM_ALLOWED_ACCESS,
2013                                       &connect_pol);
2014         if (!NT_STATUS_IS_OK(result)) {
2015                 goto done;
2016         }
2017
2018         /* Get domain policy handle */
2019         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2020                                         &connect_pol,
2021                                         MAXIMUM_ALLOWED_ACCESS,
2022                                         &sid,
2023                                         &domain_pol);
2024         if (!NT_STATUS_IS_OK(result)) {
2025                 goto done;
2026         }
2027
2028         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2029                                        &domain_pol,
2030                                        MAXIMUM_ALLOWED_ACCESS,
2031                                        alias_rid,
2032                                        &alias_pol);
2033
2034         if (!NT_STATUS_IS_OK(result)) {
2035                 return result;
2036         }
2037
2038         result = rpccli_samr_AddAliasMember(pipe_hnd, mem_ctx,
2039                                             &alias_pol,
2040                                             &member_sid);
2041
2042         if (!NT_STATUS_IS_OK(result)) {
2043                 return result;
2044         }
2045
2046  done:
2047         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2048         return result;
2049 }
2050
2051 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2052                                         const struct dom_sid *domain_sid,
2053                                         const char *domain_name,
2054                                         struct cli_state *cli,
2055                                         struct rpc_pipe_client *pipe_hnd,
2056                                         TALLOC_CTX *mem_ctx,
2057                                         int argc,
2058                                         const char **argv)
2059 {
2060         struct dom_sid group_sid;
2061         enum lsa_SidType group_type;
2062
2063         if (argc != 2 || c->display_usage) {
2064                 d_printf("%s\n%s",
2065                          _("Usage:"),
2066                          _("net rpc group addmem <group> <member>\n"
2067                            "  Add a member to a group\n"
2068                            "    group\tGroup to add member to\n"
2069                            "    member\tMember to add to group\n"));
2070                 return NT_STATUS_UNSUCCESSFUL;
2071         }
2072
2073         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2074                                                &group_sid, &group_type))) {
2075                 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2076                           argv[0]);
2077                 return NT_STATUS_UNSUCCESSFUL;
2078         }
2079
2080         if (group_type == SID_NAME_DOM_GRP) {
2081                 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2082                                                    &group_sid, argv[1]);
2083
2084                 if (!NT_STATUS_IS_OK(result)) {
2085                         d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2086                                  argv[1], argv[0], nt_errstr(result));
2087                 }
2088                 return result;
2089         }
2090
2091         if (group_type == SID_NAME_ALIAS) {
2092                 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2093                                                    &group_sid, argv[1]);
2094
2095                 if (!NT_STATUS_IS_OK(result)) {
2096                         d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2097                                  argv[1], argv[0], nt_errstr(result));
2098                 }
2099                 return result;
2100         }
2101
2102         d_fprintf(stderr, _("Can only add members to global or local groups "
2103                  "which %s is not\n"), argv[0]);
2104
2105         return NT_STATUS_UNSUCCESSFUL;
2106 }
2107
2108 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2109 {
2110         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2111                                rpc_group_addmem_internals,
2112                                argc, argv);
2113 }
2114
2115 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2116                                 struct rpc_pipe_client *pipe_hnd,
2117                                 TALLOC_CTX *mem_ctx,
2118                                 const struct dom_sid *group_sid,
2119                                 const char *member)
2120 {
2121         struct policy_handle connect_pol, domain_pol;
2122         NTSTATUS result;
2123         uint32 group_rid;
2124         struct policy_handle group_pol;
2125
2126         struct samr_Ids rids, rid_types;
2127         struct lsa_String lsa_acct_name;
2128
2129         struct dom_sid sid;
2130
2131         sid_copy(&sid, group_sid);
2132
2133         if (!sid_split_rid(&sid, &group_rid))
2134                 return NT_STATUS_UNSUCCESSFUL;
2135
2136         /* Get sam policy handle */
2137         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2138                                       pipe_hnd->desthost,
2139                                       MAXIMUM_ALLOWED_ACCESS,
2140                                       &connect_pol);
2141         if (!NT_STATUS_IS_OK(result))
2142                 return result;
2143
2144         /* Get domain policy handle */
2145         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2146                                         &connect_pol,
2147                                         MAXIMUM_ALLOWED_ACCESS,
2148                                         &sid,
2149                                         &domain_pol);
2150         if (!NT_STATUS_IS_OK(result))
2151                 return result;
2152
2153         init_lsa_String(&lsa_acct_name, member);
2154
2155         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2156                                          &domain_pol,
2157                                          1,
2158                                          &lsa_acct_name,
2159                                          &rids,
2160                                          &rid_types);
2161         if (!NT_STATUS_IS_OK(result)) {
2162                 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2163                           member);
2164                 goto done;
2165         }
2166
2167         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2168                                        &domain_pol,
2169                                        MAXIMUM_ALLOWED_ACCESS,
2170                                        group_rid,
2171                                        &group_pol);
2172
2173         if (!NT_STATUS_IS_OK(result))
2174                 goto done;
2175
2176         result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
2177                                                &group_pol,
2178                                                rids.ids[0]);
2179
2180  done:
2181         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2182         return result;
2183 }
2184
2185 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2186                                 TALLOC_CTX *mem_ctx,
2187                                 const struct dom_sid *alias_sid,
2188                                 const char *member)
2189 {
2190         struct policy_handle connect_pol, domain_pol;
2191         NTSTATUS result;
2192         uint32 alias_rid;
2193         struct policy_handle alias_pol;
2194
2195         struct dom_sid member_sid;
2196         enum lsa_SidType member_type;
2197
2198         struct dom_sid sid;
2199
2200         sid_copy(&sid, alias_sid);
2201
2202         if (!sid_split_rid(&sid, &alias_rid))
2203                 return NT_STATUS_UNSUCCESSFUL;
2204
2205         result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2206                                    member, &member_sid, &member_type);
2207
2208         if (!NT_STATUS_IS_OK(result)) {
2209                 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2210                           member);
2211                 return result;
2212         }
2213
2214         /* Get sam policy handle */
2215         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2216                                       pipe_hnd->desthost,
2217                                       MAXIMUM_ALLOWED_ACCESS,
2218                                       &connect_pol);
2219         if (!NT_STATUS_IS_OK(result)) {
2220                 goto done;
2221         }
2222
2223         /* Get domain policy handle */
2224         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2225                                         &connect_pol,
2226                                         MAXIMUM_ALLOWED_ACCESS,
2227                                         &sid,
2228                                         &domain_pol);
2229         if (!NT_STATUS_IS_OK(result)) {
2230                 goto done;
2231         }
2232
2233         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2234                                        &domain_pol,
2235                                        MAXIMUM_ALLOWED_ACCESS,
2236                                        alias_rid,
2237                                        &alias_pol);
2238
2239         if (!NT_STATUS_IS_OK(result))
2240                 return result;
2241
2242         result = rpccli_samr_DeleteAliasMember(pipe_hnd, mem_ctx,
2243                                                &alias_pol,
2244                                                &member_sid);
2245
2246         if (!NT_STATUS_IS_OK(result))
2247                 return result;
2248
2249  done:
2250         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2251         return result;
2252 }
2253
2254 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2255                                         const struct dom_sid *domain_sid,
2256                                         const char *domain_name,
2257                                         struct cli_state *cli,
2258                                         struct rpc_pipe_client *pipe_hnd,
2259                                         TALLOC_CTX *mem_ctx,
2260                                         int argc,
2261                                         const char **argv)
2262 {
2263         struct dom_sid group_sid;
2264         enum lsa_SidType group_type;
2265
2266         if (argc != 2 || c->display_usage) {
2267                 d_printf("%s\n%s",
2268                          _("Usage:"),
2269                          _("net rpc group delmem <group> <member>\n"
2270                            "  Delete a member from a group\n"
2271                            "    group\tGroup to delete member from\n"
2272                            "    member\tMember to delete from group\n"));
2273                 return NT_STATUS_UNSUCCESSFUL;
2274         }
2275
2276         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2277                                                &group_sid, &group_type))) {
2278                 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2279                           argv[0]);
2280                 return NT_STATUS_UNSUCCESSFUL;
2281         }
2282
2283         if (group_type == SID_NAME_DOM_GRP) {
2284                 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2285                                                    &group_sid, argv[1]);
2286
2287                 if (!NT_STATUS_IS_OK(result)) {
2288                         d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2289                                  argv[1], argv[0], nt_errstr(result));
2290                 }
2291                 return result;
2292         }
2293
2294         if (group_type == SID_NAME_ALIAS) {
2295                 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2296                                                    &group_sid, argv[1]);
2297
2298                 if (!NT_STATUS_IS_OK(result)) {
2299                         d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2300                                  argv[1], argv[0], nt_errstr(result));
2301                 }
2302                 return result;
2303         }
2304
2305         d_fprintf(stderr, _("Can only delete members from global or local "
2306                  "groups which %s is not\n"), argv[0]);
2307
2308         return NT_STATUS_UNSUCCESSFUL;
2309 }
2310
2311 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2312 {
2313         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2314                                rpc_group_delmem_internals,
2315                                argc, argv);
2316 }
2317
2318 /**
2319  * List groups on a remote RPC server.
2320  *
2321  * All parameters are provided by the run_rpc_command function, except for
2322  * argc, argv which are passes through.
2323  *
2324  * @param domain_sid The domain sid acquired from the remote server.
2325  * @param cli A cli_state connected to the server.
2326  * @param mem_ctx Talloc context, destroyed on completion of the function.
2327  * @param argc  Standard main() style argc.
2328  * @param argv  Standard main() style argv. Initial components are already
2329  *              stripped.
2330  *
2331  * @return Normal NTSTATUS return.
2332  **/
2333
2334 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2335                                         const struct dom_sid *domain_sid,
2336                                         const char *domain_name,
2337                                         struct cli_state *cli,
2338                                         struct rpc_pipe_client *pipe_hnd,
2339                                         TALLOC_CTX *mem_ctx,
2340                                         int argc,
2341                                         const char **argv)
2342 {
2343         struct policy_handle connect_pol, domain_pol;
2344         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2345         uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2346         struct samr_SamArray *groups = NULL;
2347         bool global = false;
2348         bool local = false;
2349         bool builtin = false;
2350
2351         if (c->display_usage) {
2352                 d_printf("%s\n%s",
2353                          _("Usage:"),
2354                          _("net rpc group list [global] [local] [builtin]\n"
2355                            "  List groups on RPC server\n"
2356                            "    global\tList global groups\n"
2357                            "    local\tList local groups\n"
2358                            "    builtin\tList builtin groups\n"
2359                            "    If none of global, local or builtin is "
2360                            "specified, all three options are considered "
2361                            "set\n"));
2362                 return NT_STATUS_OK;
2363         }
2364
2365         if (argc == 0) {
2366                 global = true;
2367                 local = true;
2368                 builtin = true;
2369         }
2370
2371         for (i=0; i<argc; i++) {
2372                 if (strequal(argv[i], "global"))
2373                         global = true;
2374
2375                 if (strequal(argv[i], "local"))
2376                         local = true;
2377
2378                 if (strequal(argv[i], "builtin"))
2379                         builtin = true;
2380         }
2381
2382         /* Get sam policy handle */
2383
2384         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2385                                       pipe_hnd->desthost,
2386                                       MAXIMUM_ALLOWED_ACCESS,
2387                                       &connect_pol);
2388         if (!NT_STATUS_IS_OK(result)) {
2389                 goto done;
2390         }
2391
2392         /* Get domain policy handle */
2393
2394         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2395                                         &connect_pol,
2396                                         MAXIMUM_ALLOWED_ACCESS,
2397                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2398                                         &domain_pol);
2399         if (!NT_STATUS_IS_OK(result)) {
2400                 goto done;
2401         }
2402
2403         /* Query domain groups */
2404         if (c->opt_long_list_entries)
2405                 d_printf(_("\nGroup name            Comment"
2406                            "\n-----------------------------\n"));
2407         do {
2408                 uint32_t max_size, total_size, returned_size;
2409                 union samr_DispInfo info;
2410
2411                 if (!global) break;
2412
2413                 dcerpc_get_query_dispinfo_params(
2414                         loop_count, &max_entries, &max_size);
2415
2416                 result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
2417                                                       &domain_pol,
2418                                                       3,
2419                                                       start_idx,
2420                                                       max_entries,
2421                                                       max_size,
2422                                                       &total_size,
2423                                                       &returned_size,
2424                                                       &info);
2425                 num_entries = info.info3.count;
2426                 start_idx += info.info3.count;
2427
2428                 if (!NT_STATUS_IS_OK(result) &&
2429                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2430                         break;
2431
2432                 for (i = 0; i < num_entries; i++) {
2433
2434                         const char *group = NULL;
2435                         const char *desc = NULL;
2436
2437                         group = info.info3.entries[i].account_name.string;
2438                         desc = info.info3.entries[i].description.string;
2439
2440                         if (c->opt_long_list_entries)
2441                                 printf("%-21.21s %-50.50s\n",
2442                                        group, desc);
2443                         else
2444                                 printf("%s\n", group);
2445                 }
2446         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2447         /* query domain aliases */
2448         start_idx = 0;
2449         do {
2450                 if (!local) break;
2451
2452                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2453                                                        &domain_pol,
2454                                                        &start_idx,
2455                                                        &groups,
2456                                                        0xffff,
2457                                                        &num_entries);
2458                 if (!NT_STATUS_IS_OK(result) &&
2459                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2460                         break;
2461
2462                 for (i = 0; i < num_entries; i++) {
2463
2464                         const char *description = NULL;
2465
2466                         if (c->opt_long_list_entries) {
2467
2468                                 struct policy_handle alias_pol;
2469                                 union samr_AliasInfo *info = NULL;
2470
2471                                 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2472                                                                            &domain_pol,
2473                                                                            0x8,
2474                                                                            groups->entries[i].idx,
2475                                                                            &alias_pol))) &&
2476                                     (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2477                                                                                 &alias_pol,
2478                                                                                 3,
2479                                                                                 &info))) &&
2480                                     (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2481                                                                     &alias_pol)))) {
2482                                         description = info->description.string;
2483                                 }
2484                         }
2485
2486                         if (description != NULL) {
2487                                 printf("%-21.21s %-50.50s\n",
2488                                        groups->entries[i].name.string,
2489                                        description);
2490                         } else {
2491                                 printf("%s\n", groups->entries[i].name.string);
2492                         }
2493                 }
2494         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2495         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2496         /* Get builtin policy handle */
2497
2498         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2499                                         &connect_pol,
2500                                         MAXIMUM_ALLOWED_ACCESS,
2501                                         CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2502                                         &domain_pol);
2503         if (!NT_STATUS_IS_OK(result)) {
2504                 goto done;
2505         }
2506         /* query builtin aliases */
2507         start_idx = 0;
2508         do {
2509                 if (!builtin) break;
2510
2511                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2512                                                        &domain_pol,
2513                                                        &start_idx,
2514                                                        &groups,
2515                                                        max_entries,
2516                                                        &num_entries);
2517                 if (!NT_STATUS_IS_OK(result) &&
2518                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2519                         break;
2520
2521                 for (i = 0; i < num_entries; i++) {
2522
2523                         const char *description = NULL;
2524
2525                         if (c->opt_long_list_entries) {
2526
2527                                 struct policy_handle alias_pol;
2528                                 union samr_AliasInfo *info = NULL;
2529
2530                                 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2531                                                                            &domain_pol,
2532                                                                            0x8,
2533                                                                            groups->entries[i].idx,
2534                                                                            &alias_pol))) &&
2535                                     (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2536                                                                                 &alias_pol,
2537                                                                                 3,
2538                                                                                 &info))) &&
2539                                     (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2540                                                                     &alias_pol)))) {
2541                                         description = info->description.string;
2542                                 }
2543                         }
2544
2545                         if (description != NULL) {
2546                                 printf("%-21.21s %-50.50s\n",
2547                                        groups->entries[i].name.string,
2548                                        description);
2549                         } else {
2550                                 printf("%s\n", groups->entries[i].name.string);
2551                         }
2552                 }
2553         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2554
2555  done:
2556         return result;
2557 }
2558
2559 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2560 {
2561         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2562                                rpc_group_list_internals,
2563                                argc, argv);
2564 }
2565
2566 static NTSTATUS rpc_list_group_members(struct net_context *c,
2567                                         struct rpc_pipe_client *pipe_hnd,
2568                                         TALLOC_CTX *mem_ctx,
2569                                         const char *domain_name,
2570                                         const struct dom_sid *domain_sid,
2571                                         struct policy_handle *domain_pol,
2572                                         uint32 rid)
2573 {
2574         NTSTATUS result;
2575         struct policy_handle group_pol;
2576         uint32 num_members, *group_rids;
2577         int i;
2578         struct samr_RidAttrArray *rids = NULL;
2579         struct lsa_Strings names;
2580         struct samr_Ids types;
2581
2582         fstring sid_str;
2583         sid_to_fstring(sid_str, domain_sid);
2584
2585         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2586                                        domain_pol,
2587                                        MAXIMUM_ALLOWED_ACCESS,
2588                                        rid,
2589                                        &group_pol);
2590
2591         if (!NT_STATUS_IS_OK(result))
2592                 return result;
2593
2594         result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
2595                                               &group_pol,
2596                                               &rids);
2597
2598         if (!NT_STATUS_IS_OK(result))
2599                 return result;
2600
2601         num_members = rids->count;
2602         group_rids = rids->rids;
2603
2604         while (num_members > 0) {
2605                 int this_time = 512;
2606
2607                 if (num_members < this_time)
2608                         this_time = num_members;
2609
2610                 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
2611                                                 domain_pol,
2612                                                 this_time,
2613                                                 group_rids,
2614                                                 &names,
2615                                                 &types);
2616
2617                 if (!NT_STATUS_IS_OK(result))
2618                         return result;
2619
2620                 /* We only have users as members, but make the output
2621                    the same as the output of alias members */
2622
2623                 for (i = 0; i < this_time; i++) {
2624
2625                         if (c->opt_long_list_entries) {
2626                                 printf("%s-%d %s\\%s %d\n", sid_str,
2627                                        group_rids[i], domain_name,
2628                                        names.names[i].string,
2629                                        SID_NAME_USER);
2630                         } else {
2631                                 printf("%s\\%s\n", domain_name,
2632                                         names.names[i].string);
2633                         }
2634                 }
2635
2636                 num_members -= this_time;
2637                 group_rids += 512;
2638         }
2639
2640         return NT_STATUS_OK;
2641 }
2642
2643 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2644                                         struct rpc_pipe_client *pipe_hnd,
2645                                         TALLOC_CTX *mem_ctx,
2646                                         struct policy_handle *domain_pol,
2647                                         uint32 rid)
2648 {
2649         NTSTATUS result;
2650         struct rpc_pipe_client *lsa_pipe;
2651         struct policy_handle alias_pol, lsa_pol;
2652         uint32 num_members;
2653         struct dom_sid *alias_sids;
2654         char **domains;
2655         char **names;
2656         enum lsa_SidType *types;
2657         int i;
2658         struct lsa_SidArray sid_array;
2659
2660         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2661                                        domain_pol,
2662                                        MAXIMUM_ALLOWED_ACCESS,
2663                                        rid,
2664                                        &alias_pol);
2665
2666         if (!NT_STATUS_IS_OK(result))
2667                 return result;
2668
2669         result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
2670                                                &alias_pol,
2671                                                &sid_array);
2672
2673         if (!NT_STATUS_IS_OK(result)) {
2674                 d_fprintf(stderr, _("Couldn't list alias members\n"));
2675                 return result;
2676         }
2677
2678         num_members = sid_array.num_sids;
2679
2680         if (num_members == 0) {
2681                 return NT_STATUS_OK;
2682         }
2683
2684         result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2685                                           &ndr_table_lsarpc.syntax_id,
2686                                           &lsa_pipe);
2687         if (!NT_STATUS_IS_OK(result)) {
2688                 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
2689                         nt_errstr(result) );
2690                 return result;
2691         }
2692
2693         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2694                                      SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2695
2696         if (!NT_STATUS_IS_OK(result)) {
2697                 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
2698                 TALLOC_FREE(lsa_pipe);
2699                 return result;
2700         }
2701
2702         alias_sids = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, num_members);
2703         if (!alias_sids) {
2704                 d_fprintf(stderr, _("Out of memory\n"));
2705                 TALLOC_FREE(lsa_pipe);
2706                 return NT_STATUS_NO_MEMORY;
2707         }
2708
2709         for (i=0; i<num_members; i++) {
2710                 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2711         }
2712
2713         result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
2714                                      num_members,  alias_sids,
2715                                      &domains, &names, &types);
2716
2717         if (!NT_STATUS_IS_OK(result) &&
2718             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2719                 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
2720                 TALLOC_FREE(lsa_pipe);
2721                 return result;
2722         }
2723
2724         for (i = 0; i < num_members; i++) {
2725                 fstring sid_str;
2726                 sid_to_fstring(sid_str, &alias_sids[i]);
2727
2728                 if (c->opt_long_list_entries) {
2729                         printf("%s %s\\%s %d\n", sid_str,
2730                                domains[i] ? domains[i] : _("*unknown*"),
2731                                names[i] ? names[i] : _("*unknown*"), types[i]);
2732                 } else {
2733                         if (domains[i])
2734                                 printf("%s\\%s\n", domains[i], names[i]);
2735                         else
2736                                 printf("%s\n", sid_str);
2737                 }
2738         }
2739
2740         TALLOC_FREE(lsa_pipe);
2741         return NT_STATUS_OK;
2742 }
2743
2744 static NTSTATUS rpc_group_members_internals(struct net_context *c,
2745                                         const struct dom_sid *domain_sid,
2746                                         const char *domain_name,
2747                                         struct cli_state *cli,
2748                                         struct rpc_pipe_client *pipe_hnd,
2749                                         TALLOC_CTX *mem_ctx,
2750                                         int argc,
2751                                         const char **argv)
2752 {
2753         NTSTATUS result;
2754         struct policy_handle connect_pol, domain_pol;
2755         struct samr_Ids rids, rid_types;
2756         struct lsa_String lsa_acct_name;
2757
2758         /* Get sam policy handle */
2759
2760         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2761                                       pipe_hnd->desthost,
2762                                       MAXIMUM_ALLOWED_ACCESS,
2763                                       &connect_pol);
2764
2765         if (!NT_STATUS_IS_OK(result))
2766                 return result;
2767
2768         /* Get domain policy handle */
2769
2770         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2771                                         &connect_pol,
2772                                         MAXIMUM_ALLOWED_ACCESS,
2773                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2774                                         &domain_pol);
2775
2776         if (!NT_STATUS_IS_OK(result))
2777                 return result;
2778
2779         init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
2780
2781         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2782                                          &domain_pol,
2783                                          1,
2784                                          &lsa_acct_name,
2785                                          &rids,
2786                                          &rid_types);
2787
2788         if (!NT_STATUS_IS_OK(result)) {
2789
2790                 /* Ok, did not find it in the global sam, try with builtin */
2791
2792                 struct dom_sid sid_Builtin;
2793
2794                 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2795
2796                 sid_copy(&sid_Builtin, &global_sid_Builtin);
2797
2798                 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2799                                                 &connect_pol,
2800                                                 MAXIMUM_ALLOWED_ACCESS,
2801                                                 &sid_Builtin,
2802                                                 &domain_pol);
2803
2804                 if (!NT_STATUS_IS_OK(result)) {
2805                         d_fprintf(stderr, _("Couldn't find group %s\n"),
2806                                   argv[0]);
2807                         return result;
2808                 }
2809
2810                 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2811                                                  &domain_pol,
2812                                                  1,
2813                                                  &lsa_acct_name,
2814                                                  &rids,
2815                                                  &rid_types);
2816
2817                 if (!NT_STATUS_IS_OK(result)) {
2818                         d_fprintf(stderr, _("Couldn't find group %s\n"),
2819                                   argv[0]);
2820                         return result;
2821                 }
2822         }
2823
2824         if (rids.count != 1) {
2825                 d_fprintf(stderr, _("Couldn't find group %s\n"),
2826                           argv[0]);
2827                 return result;
2828         }
2829
2830         if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
2831                 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
2832                                               domain_sid, &domain_pol,
2833                                               rids.ids[0]);
2834         }
2835
2836         if (rid_types.ids[0] == SID_NAME_ALIAS) {
2837                 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
2838                                               rids.ids[0]);
2839         }
2840
2841         return NT_STATUS_NO_SUCH_GROUP;
2842 }
2843
2844 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
2845 {
2846         if (argc != 1 || c->display_usage) {
2847                 return rpc_group_usage(c, argc, argv);
2848         }
2849
2850         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2851                                rpc_group_members_internals,
2852                                argc, argv);
2853 }
2854
2855 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
2856 {
2857         NET_API_STATUS status;
2858         struct GROUP_INFO_0 g0;
2859         uint32_t parm_err;
2860
2861         if (argc != 2) {
2862                 d_printf(_("Usage:\n"));
2863                 d_printf("net rpc group rename group newname\n");
2864                 return -1;
2865         }
2866
2867         g0.grpi0_name = argv[1];
2868
2869         status = NetGroupSetInfo(c->opt_host,
2870                                  argv[0],
2871                                  0,
2872                                  (uint8_t *)&g0,
2873                                  &parm_err);
2874
2875         if (status != 0) {
2876                 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
2877                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
2878                         status));
2879                 return -1;
2880         }
2881
2882         return 0;
2883 }
2884
2885 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
2886 {
2887         if (argc != 2 || c->display_usage) {
2888                 return rpc_group_usage(c, argc, argv);
2889         }
2890
2891         return rpc_group_rename_internals(c, argc, argv);
2892 }
2893
2894 /**
2895  * 'net rpc group' entrypoint.
2896  * @param argc  Standard main() style argc.
2897  * @param argv  Standard main() style argv. Initial components are already
2898  *              stripped.
2899  **/
2900
2901 int net_rpc_group(struct net_context *c, int argc, const char **argv)
2902 {
2903         NET_API_STATUS status;
2904
2905         struct functable func[] = {
2906                 {
2907                         "add",
2908                         rpc_group_add,
2909                         NET_TRANSPORT_RPC,
2910                         N_("Create specified group"),
2911                         N_("net rpc group add\n"
2912                            "    Create specified group")
2913                 },
2914                 {
2915                         "delete",
2916                         rpc_group_delete,
2917                         NET_TRANSPORT_RPC,
2918                         N_("Delete specified group"),
2919                         N_("net rpc group delete\n"
2920                            "    Delete specified group")
2921                 },
2922                 {
2923                         "addmem",
2924                         rpc_group_addmem,
2925                         NET_TRANSPORT_RPC,
2926                         N_("Add member to group"),
2927                         N_("net rpc group addmem\n"
2928                            "    Add member to group")
2929                 },
2930                 {
2931                         "delmem",
2932                         rpc_group_delmem,
2933                         NET_TRANSPORT_RPC,
2934                         N_("Remove member from group"),
2935                         N_("net rpc group delmem\n"
2936                            "    Remove member from group")
2937                 },
2938                 {
2939                         "list",
2940                         rpc_group_list,
2941                         NET_TRANSPORT_RPC,
2942                         N_("List groups"),
2943                         N_("net rpc group list\n"
2944                            "    List groups")
2945                 },
2946                 {
2947                         "members",
2948                         rpc_group_members,
2949                         NET_TRANSPORT_RPC,
2950                         N_("List group members"),
2951                         N_("net rpc group members\n"
2952                            "    List group members")
2953                 },
2954                 {
2955                         "rename",
2956                         rpc_group_rename,
2957                         NET_TRANSPORT_RPC,
2958                         N_("Rename group"),
2959                         N_("net rpc group rename\n"
2960                            "    Rename group")
2961                 },
2962                 {NULL, NULL, 0, NULL, NULL}
2963         };
2964
2965         status = libnetapi_net_init(&c->netapi_ctx);
2966         if (status != 0) {
2967                 return -1;
2968         }
2969         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
2970         libnetapi_set_password(c->netapi_ctx, c->opt_password);
2971         if (c->opt_kerberos) {
2972                 libnetapi_set_use_kerberos(c->netapi_ctx);
2973         }
2974
2975         if (argc == 0) {
2976                 if (c->display_usage) {
2977                         d_printf(_("Usage:\n"));
2978                         d_printf(_("net rpc group\n"
2979                                    "    Alias for net rpc group list global "
2980                                    "local builtin\n"));
2981                         net_display_usage_from_functable(func);
2982                         return 0;
2983                 }
2984
2985                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2986                                        rpc_group_list_internals,
2987                                        argc, argv);
2988         }
2989
2990         return net_run_function(c, argc, argv, "net rpc group", func);
2991 }
2992
2993 /****************************************************************************/
2994
2995 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
2996 {
2997         return net_share_usage(c, argc, argv);
2998 }
2999
3000 /**
3001  * Add a share on a remote RPC server.
3002  *
3003  * @param argc  Standard main() style argc.
3004  * @param argv  Standard main() style argv. Initial components are already
3005  *              stripped.
3006  *
3007  * @return A shell status integer (0 for success).
3008  **/
3009
3010 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3011 {
3012         NET_API_STATUS status;
3013         char *sharename;
3014         char *path;
3015         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3016         uint32 num_users=0, perms=0;
3017         char *password=NULL; /* don't allow a share password */
3018         struct SHARE_INFO_2 i2;
3019         uint32_t parm_error = 0;
3020
3021         if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3022                 return rpc_share_usage(c, argc, argv);
3023         }
3024
3025         if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
3026                 return -1;
3027         }
3028
3029         path = strchr(sharename, '=');
3030         if (!path) {
3031                 return -1;
3032         }
3033
3034         *path++ = '\0';
3035
3036         i2.shi2_netname         = sharename;
3037         i2.shi2_type            = type;
3038         i2.shi2_remark          = c->opt_comment;
3039         i2.shi2_permissions     = perms;
3040         i2.shi2_max_uses        = c->opt_maxusers;
3041         i2.shi2_current_uses    = num_users;
3042         i2.shi2_path            = path;
3043         i2.shi2_passwd          = password;
3044
3045         status = NetShareAdd(c->opt_host,
3046                              2,
3047                              (uint8_t *)&i2,
3048                              &parm_error);
3049         if (status != 0) {
3050                 printf(_("NetShareAdd failed with: %s\n"),
3051                         libnetapi_get_error_string(c->netapi_ctx, status));
3052         }
3053
3054         return status;
3055 }
3056
3057 /**
3058  * Delete a share on a remote RPC server.
3059  *
3060  * @param domain_sid The domain sid acquired from the remote server.
3061  * @param argc  Standard main() style argc.
3062  * @param argv  Standard main() style argv. Initial components are already
3063  *              stripped.
3064  *
3065  * @return A shell status integer (0 for success).
3066  **/
3067 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3068 {
3069         if (argc < 1 || c->display_usage) {
3070                 return rpc_share_usage(c, argc, argv);
3071         }
3072
3073         return NetShareDel(c->opt_host, argv[0], 0);
3074 }
3075
3076 /**
3077  * Formatted print of share info
3078  *
3079  * @param r  pointer to SHARE_INFO_1 to format
3080  **/
3081
3082 static void display_share_info_1(struct net_context *c,
3083                                  struct SHARE_INFO_1 *r)
3084 {
3085         if (c->opt_long_list_entries) {
3086                 d_printf("%-12s %-8.8s %-50s\n",
3087                          r->shi1_netname,
3088                          net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3089                          r->shi1_remark);
3090         } else {
3091                 d_printf("%s\n", r->shi1_netname);
3092         }
3093 }
3094
3095 static WERROR get_share_info(struct net_context *c,
3096                              struct rpc_pipe_client *pipe_hnd,
3097                              TALLOC_CTX *mem_ctx,
3098                              uint32 level,
3099                              int argc,
3100                              const char **argv,
3101                              struct srvsvc_NetShareInfoCtr *info_ctr)
3102 {
3103         WERROR result;
3104         NTSTATUS status;
3105         union srvsvc_NetShareInfo info;
3106         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3107
3108         /* no specific share requested, enumerate all */
3109         if (argc == 0) {
3110
3111                 uint32_t preferred_len = 0xffffffff;
3112                 uint32_t total_entries = 0;
3113                 uint32_t resume_handle = 0;
3114
3115                 info_ctr->level = level;
3116
3117                 status = dcerpc_srvsvc_NetShareEnumAll(b, mem_ctx,
3118                                                        pipe_hnd->desthost,
3119                                                        info_ctr,
3120                                                        preferred_len,
3121                                                        &total_entries,
3122                                                        &resume_handle,
3123                                                        &result);
3124                 if (!NT_STATUS_IS_OK(status)) {
3125                         return ntstatus_to_werror(status);
3126                 }
3127                 return result;
3128         }
3129
3130         /* request just one share */
3131         status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
3132                                                pipe_hnd->desthost,
3133                                                argv[0],
3134                                                level,
3135                                                &info,
3136                                                &result);
3137
3138         if (!NT_STATUS_IS_OK(status)) {
3139                 result = ntstatus_to_werror(status);
3140                 goto done;
3141         }
3142
3143         if (!W_ERROR_IS_OK(result)) {
3144                 goto done;
3145         }
3146
3147         /* construct ctr */
3148         ZERO_STRUCTP(info_ctr);
3149
3150         info_ctr->level = level;
3151
3152         switch (level) {
3153         case 1:
3154         {
3155                 struct srvsvc_NetShareCtr1 *ctr1;
3156
3157                 ctr1 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr1);
3158                 W_ERROR_HAVE_NO_MEMORY(ctr1);
3159
3160                 ctr1->count = 1;
3161                 ctr1->array = info.info1;
3162
3163                 info_ctr->ctr.ctr1 = ctr1;
3164
3165                 break;
3166         }
3167         case 2:
3168         {
3169                 struct srvsvc_NetShareCtr2 *ctr2;
3170
3171                 ctr2 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr2);
3172                 W_ERROR_HAVE_NO_MEMORY(ctr2);
3173
3174                 ctr2->count = 1;
3175                 ctr2->array = info.info2;
3176
3177                 info_ctr->ctr.ctr2 = ctr2;
3178
3179                 break;
3180         }
3181         case 502:
3182         {
3183                 struct srvsvc_NetShareCtr502 *ctr502;
3184
3185                 ctr502 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr502);
3186                 W_ERROR_HAVE_NO_MEMORY(ctr502);
3187
3188                 ctr502->count = 1;
3189                 ctr502->array = info.info502;
3190
3191                 info_ctr->ctr.ctr502 = ctr502;
3192
3193                 break;
3194         }
3195         } /* switch */
3196 done:
3197         return result;
3198 }
3199
3200 /***
3201  * 'net rpc share list' entrypoint.
3202  * @param argc  Standard main() style argc.
3203  * @param argv  Standard main() style argv. Initial components are already
3204  *              stripped.
3205  **/
3206 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3207 {
3208         NET_API_STATUS status;
3209         struct SHARE_INFO_1 *i1 = NULL;
3210         uint32_t entries_read = 0;
3211         uint32_t total_entries = 0;
3212         uint32_t resume_handle = 0;
3213         uint32_t i, level = 1;
3214
3215         if (c->display_usage) {
3216                 d_printf(  "%s\n"
3217                            "net rpc share list\n"
3218                            "    %s\n",
3219                          _("Usage:"),
3220                          _("List shares on remote server"));
3221                 return 0;
3222         }
3223
3224         status = NetShareEnum(c->opt_host,
3225                               level,
3226                               (uint8_t **)(void *)&i1,
3227                               (uint32_t)-1,
3228                               &entries_read,
3229                               &total_entries,
3230                               &resume_handle);
3231         if (status != 0) {
3232                 goto done;
3233         }
3234
3235         /* Display results */
3236
3237         if (c->opt_long_list_entries) {
3238                 d_printf(_(
3239         "\nEnumerating shared resources (exports) on remote server:\n\n"
3240         "\nShare name   Type     Description\n"
3241         "----------   ----     -----------\n"));
3242         }
3243         for (i = 0; i < entries_read; i++)
3244                 display_share_info_1(c, &i1[i]);
3245  done:
3246         return status;
3247 }
3248
3249 static bool check_share_availability(struct cli_state *cli, const char *netname)
3250 {
3251         NTSTATUS status;
3252
3253         status = cli_tcon_andx(cli, netname, "A:", "", 0);
3254         if (!NT_STATUS_IS_OK(status)) {
3255                 d_printf(_("skipping   [%s]: not a file share.\n"), netname);
3256                 return false;
3257         }
3258
3259         status = cli_tdis(cli);
3260         if (!NT_STATUS_IS_OK(status)) {
3261                 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3262                 return false;
3263         }
3264
3265         return true;
3266 }
3267
3268 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3269                                const char *netname, uint32 type)
3270 {
3271         /* only support disk shares */
3272         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3273                 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3274                        type);
3275                 return false;
3276         }
3277
3278         /* skip builtin shares */
3279         /* FIXME: should print$ be added too ? */
3280         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3281             strequal(netname,"global"))
3282                 return false;
3283
3284         if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3285                 printf(_("excluding  [%s]\n"), netname);
3286                 return false;
3287         }
3288
3289         return check_share_availability(cli, netname);
3290 }
3291
3292 /**
3293  * Migrate shares from a remote RPC server to the local RPC server.
3294  *
3295  * All parameters are provided by the run_rpc_command function, except for
3296  * argc, argv which are passed through.
3297  *
3298  * @param domain_sid The domain sid acquired from the remote server.
3299  * @param cli A cli_state connected to the server.
3300  * @param mem_ctx Talloc context, destroyed on completion of the function.
3301  * @param argc  Standard main() style argc.
3302  * @param argv  Standard main() style argv. Initial components are already
3303  *              stripped.
3304  *
3305  * @return Normal NTSTATUS return.
3306  **/
3307
3308 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3309                                                 const struct dom_sid *domain_sid,
3310                                                 const char *domain_name,
3311                                                 struct cli_state *cli,
3312                                                 struct rpc_pipe_client *pipe_hnd,
3313                                                 TALLOC_CTX *mem_ctx,
3314                                                 int argc,
3315                                                 const char **argv)
3316 {
3317         WERROR result;
3318         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3319         struct srvsvc_NetShareInfoCtr ctr_src;
3320         uint32 i;
3321         struct rpc_pipe_client *srvsvc_pipe = NULL;
3322         struct cli_state *cli_dst = NULL;
3323         uint32 level = 502; /* includes secdesc */
3324         uint32_t parm_error = 0;
3325         struct dcerpc_binding_handle *b;
3326
3327         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3328                                 &ctr_src);
3329         if (!W_ERROR_IS_OK(result))
3330                 goto done;
3331
3332         /* connect destination PI_SRVSVC */
3333         nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3334                                      &ndr_table_srvsvc.syntax_id);
3335         if (!NT_STATUS_IS_OK(nt_status))
3336                 return nt_status;
3337
3338         b = srvsvc_pipe->binding_handle;
3339
3340         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3341
3342                 union srvsvc_NetShareInfo info;
3343                 struct srvsvc_NetShareInfo502 info502 =
3344                         ctr_src.ctr.ctr502->array[i];
3345
3346                 /* reset error-code */
3347                 nt_status = NT_STATUS_UNSUCCESSFUL;
3348
3349                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3350                         continue;
3351
3352                 /* finally add the share on the dst server */
3353
3354                 printf(_("migrating: [%s], path: %s, comment: %s, without "
3355                          "share-ACLs\n"),
3356                         info502.name, info502.path, info502.comment);
3357
3358                 info.info502 = &info502;
3359
3360                 nt_status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
3361                                                       srvsvc_pipe->desthost,
3362                                                       502,
3363                                                       &info,
3364                                                       &parm_error,
3365                                                       &result);
3366                 if (!NT_STATUS_IS_OK(nt_status)) {
3367                         printf(_("cannot add share: %s\n"),
3368                                 nt_errstr(nt_status));
3369                         goto done;
3370                 }
3371                 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3372                         printf(_("           [%s] does already exist\n"),
3373                                 info502.name);
3374                         continue;
3375                 }
3376
3377                 if (!W_ERROR_IS_OK(result)) {
3378                         nt_status = werror_to_ntstatus(result);
3379                         printf(_("cannot add share: %s\n"),
3380                                 win_errstr(result));
3381                         goto done;
3382                 }
3383
3384         }
3385
3386         nt_status = NT_STATUS_OK;
3387
3388 done:
3389         if (cli_dst) {
3390                 cli_shutdown(cli_dst);
3391         }
3392
3393         return nt_status;
3394
3395 }
3396
3397 /**
3398  * Migrate shares from a RPC server to another.
3399  *
3400  * @param argc  Standard main() style argc.
3401  * @param argv  Standard main() style argv. Initial components are already
3402  *              stripped.
3403  *
3404  * @return A shell status integer (0 for success).
3405  **/
3406 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3407                                     const char **argv)
3408 {
3409         if (c->display_usage) {
3410                 d_printf(  "%s\n"
3411                            "net rpc share migrate shares\n"
3412                            "    %s\n",
3413                          _("Usage:"),
3414                          _("Migrate shares to local server"));
3415                 return 0;
3416         }
3417
3418         if (!c->opt_host) {
3419                 printf(_("no server to migrate\n"));
3420                 return -1;
3421         }
3422
3423         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3424                                rpc_share_migrate_shares_internals,
3425                                argc, argv);
3426 }
3427
3428 /**
3429  * Copy a file/dir
3430  *
3431  * @param f     file_info
3432  * @param mask  current search mask
3433  * @param state arg-pointer
3434  *
3435  **/
3436 static NTSTATUS copy_fn(const char *mnt, struct file_info *f,
3437                     const char *mask, void *state)
3438 {
3439         static NTSTATUS nt_status;
3440         static struct copy_clistate *local_state;
3441         static fstring filename, new_mask;
3442         fstring dir;
3443         char *old_dir;
3444         struct net_context *c;
3445
3446         local_state = (struct copy_clistate *)state;
3447         nt_status = NT_STATUS_UNSUCCESSFUL;
3448
3449         c = local_state->c;
3450
3451         if (strequal(f->name, ".") || strequal(f->name, ".."))
3452                 return NT_STATUS_OK;
3453
3454         DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3455
3456         /* DIRECTORY */
3457         if (f->mode & aDIR) {
3458
3459                 DEBUG(3,("got dir: %s\n", f->name));
3460
3461                 fstrcpy(dir, local_state->cwd);
3462                 fstrcat(dir, "\\");
3463                 fstrcat(dir, f->name);
3464
3465                 switch (net_mode_share)
3466                 {
3467                 case NET_MODE_SHARE_MIGRATE:
3468                         /* create that directory */
3469                         nt_status = net_copy_file(c, local_state->mem_ctx,
3470                                                   local_state->cli_share_src,
3471                                                   local_state->cli_share_dst,
3472                                                   dir, dir,
3473                                                   c->opt_acls? true : false,
3474                                                   c->opt_attrs? true : false,
3475                                                   c->opt_timestamps? true:false,
3476                                                   false);
3477                         break;
3478                 default:
3479                         d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3480                         return NT_STATUS_INTERNAL_ERROR;
3481                 }
3482
3483                 if (!NT_STATUS_IS_OK(nt_status)) {
3484                         printf(_("could not handle dir %s: %s\n"),
3485                                 dir, nt_errstr(nt_status));
3486                         return nt_status;
3487                 }
3488
3489                 /* search below that directory */
3490                 fstrcpy(new_mask, dir);
3491                 fstrcat(new_mask, "\\*");
3492
3493                 old_dir = local_state->cwd;
3494                 local_state->cwd = dir;
3495                 nt_status = sync_files(local_state, new_mask);
3496                 if (!NT_STATUS_IS_OK(nt_status)) {
3497                         printf(_("could not handle files\n"));
3498                 }
3499                 local_state->cwd = old_dir;
3500
3501                 return nt_status;
3502         }
3503
3504
3505         /* FILE */
3506         fstrcpy(filename, local_state->cwd);
3507         fstrcat(filename, "\\");
3508         fstrcat(filename, f->name);
3509
3510         DEBUG(3,("got file: %s\n", filename));
3511
3512         switch (net_mode_share)
3513         {
3514         case NET_MODE_SHARE_MIGRATE:
3515                 nt_status = net_copy_file(c, local_state->mem_ctx,
3516                                           local_state->cli_share_src,
3517                                           local_state->cli_share_dst,
3518                                           filename, filename,
3519                                           c->opt_acls? true : false,
3520                                           c->opt_attrs? true : false,
3521                                           c->opt_timestamps? true: false,
3522                                           true);
3523                 break;
3524         default:
3525                 d_fprintf(stderr, _("Unsupported file mode %d\n"),
3526                           net_mode_share);
3527                 return NT_STATUS_INTERNAL_ERROR;
3528         }
3529
3530         if (!NT_STATUS_IS_OK(nt_status))
3531                 printf(_("could not handle file %s: %s\n"),
3532                         filename, nt_errstr(nt_status));
3533         return nt_status;
3534 }
3535
3536 /**
3537  * sync files, can be called recursivly to list files
3538  * and then call copy_fn for each file
3539  *
3540  * @param cp_clistate   pointer to the copy_clistate we work with
3541  * @param mask          the current search mask
3542  *
3543  * @return              Boolean result
3544  **/
3545 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask)
3546 {
3547         struct cli_state *targetcli;
3548         char *targetpath = NULL;
3549         NTSTATUS status;
3550
3551         DEBUG(3,("calling cli_list with mask: %s\n", mask));
3552
3553         if ( !cli_resolve_path(talloc_tos(), "", NULL, cp_clistate->cli_share_src,
3554                                 mask, &targetcli, &targetpath ) ) {
3555                 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
3556                                     "%s\n"),
3557                         mask, cli_errstr(cp_clistate->cli_share_src));
3558                 return cli_nt_error(cp_clistate->cli_share_src);
3559         }
3560
3561         status = cli_list(targetcli, targetpath, cp_clistate->attribute,
3562                           copy_fn, cp_clistate);
3563         if (!NT_STATUS_IS_OK(status)) {
3564                 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
3565                           mask, nt_errstr(status));
3566         }
3567
3568         return status;
3569 }
3570
3571
3572 /**
3573  * Set the top level directory permissions before we do any further copies.
3574  * Should set up ACL inheritance.
3575  **/
3576
3577 bool copy_top_level_perms(struct net_context *c,
3578                                 struct copy_clistate *cp_clistate,
3579                                 const char *sharename)
3580 {
3581         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3582
3583         switch (net_mode_share) {
3584         case NET_MODE_SHARE_MIGRATE:
3585                 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3586                 nt_status = net_copy_fileattr(c,
3587                                                 cp_clistate->mem_ctx,
3588                                                 cp_clistate->cli_share_src,
3589                                                 cp_clistate->cli_share_dst,
3590                                                 "\\", "\\",
3591                                                 c->opt_acls? true : false,
3592                                                 c->opt_attrs? true : false,
3593                                                 c->opt_timestamps? true: false,
3594                                                 false);
3595                 break;
3596         default:
3597                 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3598                 break;
3599         }
3600
3601         if (!NT_STATUS_IS_OK(nt_status))  {
3602                 printf(_("Could handle directory attributes for top level "
3603                          "directory of share %s. Error %s\n"),
3604                         sharename, nt_errstr(nt_status));
3605                 return false;
3606         }
3607
3608         return true;
3609 }
3610
3611 /**
3612  * Sync all files inside a remote share to another share (over smb).
3613  *
3614  * All parameters are provided by the run_rpc_command function, except for
3615  * argc, argv which are passed through.
3616  *
3617  * @param domain_sid The domain sid acquired from the remote server.
3618  * @param cli A cli_state connected to the server.
3619  * @param mem_ctx Talloc context, destroyed on completion of the function.
3620  * @param argc  Standard main() style argc.
3621  * @param argv  Standard main() style argv. Initial components are already
3622  *              stripped.
3623  *
3624  * @return Normal NTSTATUS return.
3625  **/
3626
3627 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
3628                                                 const struct dom_sid *domain_sid,
3629                                                 const char *domain_name,
3630                                                 struct cli_state *cli,
3631                                                 struct rpc_pipe_client *pipe_hnd,
3632                                                 TALLOC_CTX *mem_ctx,
3633                                                 int argc,
3634                                                 const char **argv)
3635 {
3636         WERROR result;
3637         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3638         struct srvsvc_NetShareInfoCtr ctr_src;
3639         uint32 i;
3640         uint32 level = 502;
3641         struct copy_clistate cp_clistate;
3642         bool got_src_share = false;
3643         bool got_dst_share = false;
3644         const char *mask = "\\*";
3645         char *dst = NULL;
3646
3647         dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3648         if (dst == NULL) {
3649                 nt_status = NT_STATUS_NO_MEMORY;
3650                 goto done;
3651         }
3652
3653         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3654                                 &ctr_src);
3655
3656         if (!W_ERROR_IS_OK(result))
3657                 goto done;
3658
3659         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3660
3661                 struct srvsvc_NetShareInfo502 info502 =
3662                         ctr_src.ctr.ctr502->array[i];
3663
3664                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3665                         continue;
3666
3667                 /* one might not want to mirror whole discs :) */
3668                 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3669                         d_printf(_("skipping   [%s]: builtin/hidden share\n"),
3670                                  info502.name);
3671                         continue;
3672                 }
3673
3674                 switch (net_mode_share)
3675                 {
3676                 case NET_MODE_SHARE_MIGRATE:
3677                         printf("syncing");
3678                         break;
3679                 default:
3680                         d_fprintf(stderr, _("Unsupported mode %d\n"),
3681                                   net_mode_share);
3682                         break;
3683                 }
3684                 printf(_("    [%s] files and directories %s ACLs, %s DOS "
3685                          "Attributes %s\n"),
3686                         info502.name,
3687                         c->opt_acls ? _("including") : _("without"),
3688                         c->opt_attrs ? _("including") : _("without"),
3689                         c->opt_timestamps ? _("(preserving timestamps)") : "");
3690
3691                 cp_clistate.mem_ctx = mem_ctx;
3692                 cp_clistate.cli_share_src = NULL;
3693                 cp_clistate.cli_share_dst = NULL;
3694                 cp_clistate.cwd = NULL;
3695                 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3696                 cp_clistate.c = c;
3697
3698                 /* open share source */
3699                 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
3700                                                &cli->dest_ss, cli->desthost,
3701                                                info502.name, "A:");
3702                 if (!NT_STATUS_IS_OK(nt_status))
3703                         goto done;
3704
3705                 got_src_share = true;
3706
3707                 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3708                         /* open share destination */
3709                         nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
3710                                                        NULL, dst, info502.name, "A:");
3711                         if (!NT_STATUS_IS_OK(nt_status))
3712                                 goto done;
3713
3714                         got_dst_share = true;
3715                 }
3716
3717                 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
3718                         d_fprintf(stderr, _("Could not handle the top level "
3719                                             "directory permissions for the "
3720                                             "share: %s\n"), info502.name);
3721                         nt_status = NT_STATUS_UNSUCCESSFUL;
3722                         goto done;
3723                 }
3724
3725                 nt_status = sync_files(&cp_clistate, mask);
3726                 if (!NT_STATUS_IS_OK(nt_status)) {
3727                         d_fprintf(stderr, _("could not handle files for share: "
3728                                             "%s\n"), info502.name);
3729                         goto done;
3730                 }
3731         }
3732
3733         nt_status = NT_STATUS_OK;
3734
3735 done:
3736
3737         if (got_src_share)
3738                 cli_shutdown(cp_clistate.cli_share_src);
3739
3740         if (got_dst_share)
3741                 cli_shutdown(cp_clistate.cli_share_dst);
3742
3743         SAFE_FREE(dst);
3744         return nt_status;
3745
3746 }
3747
3748 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
3749 {
3750         if (c->display_usage) {
3751                 d_printf(  "%s\n"
3752                            "net share migrate files\n"
3753                            "    %s\n",
3754                          _("Usage:"),
3755                          _("Migrate files to local server"));
3756                 return 0;
3757         }
3758
3759         if (!c->opt_host) {
3760                 d_printf(_("no server to migrate\n"));
3761                 return -1;
3762         }
3763
3764         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3765                                rpc_share_migrate_files_internals,
3766                                argc, argv);
3767 }
3768
3769 /**
3770  * Migrate share-ACLs from a remote RPC server to the local RPC server.
3771  *
3772  * All parameters are provided by the run_rpc_command function, except for
3773  * argc, argv which are passed through.
3774  *
3775  * @param domain_sid The domain sid acquired from the remote server.
3776  * @param cli A cli_state connected to the server.
3777  * @param mem_ctx Talloc context, destroyed on completion of the function.
3778  * @param argc  Standard main() style argc.
3779  * @param argv  Standard main() style argv. Initial components are already
3780  *              stripped.
3781  *
3782  * @return Normal NTSTATUS return.
3783  **/
3784
3785 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
3786                                                 const struct dom_sid *domain_sid,
3787                                                 const char *domain_name,
3788                                                 struct cli_state *cli,
3789                                                 struct rpc_pipe_client *pipe_hnd,
3790                                                 TALLOC_CTX *mem_ctx,
3791                                                 int argc,
3792                                                 const char **argv)
3793 {
3794         WERROR result;
3795         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3796         struct srvsvc_NetShareInfoCtr ctr_src;
3797         union srvsvc_NetShareInfo info;
3798         uint32 i;
3799         struct rpc_pipe_client *srvsvc_pipe = NULL;
3800         struct cli_state *cli_dst = NULL;
3801         uint32 level = 502; /* includes secdesc */
3802         uint32_t parm_error = 0;
3803         struct dcerpc_binding_handle *b;
3804
3805         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3806                                 &ctr_src);
3807
3808         if (!W_ERROR_IS_OK(result))
3809                 goto done;
3810
3811         /* connect destination PI_SRVSVC */
3812         nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3813                                      &ndr_table_srvsvc.syntax_id);
3814         if (!NT_STATUS_IS_OK(nt_status))
3815                 return nt_status;
3816
3817         b = srvsvc_pipe->binding_handle;
3818
3819         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3820
3821                 struct srvsvc_NetShareInfo502 info502 =
3822                         ctr_src.ctr.ctr502->array[i];
3823
3824                 /* reset error-code */
3825                 nt_status = NT_STATUS_UNSUCCESSFUL;
3826
3827                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3828                         continue;
3829
3830                 printf(_("migrating: [%s], path: %s, comment: %s, including "
3831                          "share-ACLs\n"),
3832                         info502.name, info502.path, info502.comment);
3833
3834                 if (c->opt_verbose)
3835                         display_sec_desc(info502.sd_buf.sd);
3836
3837                 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3838                 info.info502 = &info502;
3839
3840                 /* finally modify the share on the dst server */
3841                 nt_status = dcerpc_srvsvc_NetShareSetInfo(b, mem_ctx,
3842                                                           srvsvc_pipe->desthost,
3843                                                           info502.name,
3844                                                           level,
3845                                                           &info,
3846                                                           &parm_error,
3847                                                           &result);
3848                 if (!NT_STATUS_IS_OK(nt_status)) {
3849                         printf(_("cannot set share-acl: %s\n"),
3850                                nt_errstr(nt_status));
3851                         goto done;
3852                 }
3853                 if (!W_ERROR_IS_OK(result)) {
3854                         nt_status = werror_to_ntstatus(result);
3855                         printf(_("cannot set share-acl: %s\n"),
3856                                win_errstr(result));
3857                         goto done;
3858                 }
3859
3860         }
3861
3862         nt_status = NT_STATUS_OK;
3863
3864 done:
3865         if (cli_dst) {
3866                 cli_shutdown(cli_dst);
3867         }
3868
3869         return nt_status;
3870
3871 }
3872
3873 /**
3874  * Migrate share-acls from a RPC server to another.
3875  *
3876  * @param argc  Standard main() style argc.
3877  * @param argv  Standard main() style argv. Initial components are already
3878  *              stripped.
3879  *
3880  * @return A shell status integer (0 for success).
3881  **/
3882 static int rpc_share_migrate_security(struct net_context *c, int argc,
3883                                       const char **argv)
3884 {
3885         if (c->display_usage) {
3886                 d_printf(  "%s\n"
3887                            "net rpc share migrate security\n"
3888                            "    %s\n",
3889                          _("Usage:"),
3890                          _("Migrate share-acls to local server"));
3891                 return 0;
3892         }
3893
3894         if (!c->opt_host) {
3895                 d_printf(_("no server to migrate\n"));
3896                 return -1;
3897         }
3898
3899         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3900                                rpc_share_migrate_security_internals,
3901                                argc, argv);
3902 }
3903
3904 /**
3905  * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3906  * from one server to another.
3907  *
3908  * @param argc  Standard main() style argc.
3909  * @param argv  Standard main() style argv. Initial components are already
3910  *              stripped.
3911  *
3912  * @return A shell status integer (0 for success).
3913  *
3914  **/
3915 static int rpc_share_migrate_all(struct net_context *c, int argc,
3916                                  const char **argv)
3917 {
3918         int ret;
3919
3920         if (c->display_usage) {
3921                 d_printf(  "%s\n"
3922                            "net rpc share migrate all\n"
3923                            "    %s\n",
3924                          _("Usage:"),
3925                          _("Migrates shares including all share settings"));
3926                 return 0;
3927         }
3928
3929         if (!c->opt_host) {
3930                 d_printf(_("no server to migrate\n"));
3931                 return -1;
3932         }
3933
3934         /* order is important. we don't want to be locked out by the share-acl
3935          * before copying files - gd */
3936
3937         ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3938                               rpc_share_migrate_shares_internals, argc, argv);
3939         if (ret)
3940                 return ret;
3941
3942         ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3943                               rpc_share_migrate_files_internals, argc, argv);
3944         if (ret)
3945                 return ret;
3946
3947         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3948                                rpc_share_migrate_security_internals, argc,
3949                                argv);
3950 }
3951
3952
3953 /**
3954  * 'net rpc share migrate' entrypoint.
3955  * @param argc  Standard main() style argc.
3956  * @param argv  Standard main() style argv. Initial components are already
3957  *              stripped.
3958  **/
3959 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
3960 {
3961
3962         struct functable func[] = {
3963                 {
3964                         "all",
3965                         rpc_share_migrate_all,
3966                         NET_TRANSPORT_RPC,
3967                         N_("Migrate shares from remote to local server"),
3968                         N_("net rpc share migrate all\n"
3969                            "    Migrate shares from remote to local server")
3970                 },
3971                 {
3972                         "files",
3973                         rpc_share_migrate_files,
3974                         NET_TRANSPORT_RPC,
3975                         N_("Migrate files from remote to local server"),
3976                         N_("net rpc share migrate files\n"
3977                            "    Migrate files from remote to local server")
3978                 },
3979                 {
3980                         "security",
3981                         rpc_share_migrate_security,
3982                         NET_TRANSPORT_RPC,
3983                         N_("Migrate share-ACLs from remote to local server"),
3984                         N_("net rpc share migrate security\n"
3985                            "    Migrate share-ACLs from remote to local server")
3986                 },
3987                 {
3988                         "shares",
3989                         rpc_share_migrate_shares,
3990                         NET_TRANSPORT_RPC,
3991                         N_("Migrate shares from remote to local server"),
3992                         N_("net rpc share migrate shares\n"
3993                            "    Migrate shares from remote to local server")
3994                 },
3995                 {NULL, NULL, 0, NULL, NULL}
3996         };
3997
3998         net_mode_share = NET_MODE_SHARE_MIGRATE;
3999
4000         return net_run_function(c, argc, argv, "net rpc share migrate", func);
4001 }
4002
4003 struct full_alias {
4004         struct dom_sid sid;
4005         uint32 num_members;
4006         struct dom_sid *members;
4007 };
4008
4009 static int num_server_aliases;
4010 static struct full_alias *server_aliases;
4011
4012 /*
4013  * Add an alias to the static list.
4014  */
4015 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
4016 {
4017         if (server_aliases == NULL)
4018                 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
4019
4020         server_aliases[num_server_aliases] = *alias;
4021         num_server_aliases += 1;
4022 }
4023
4024 /*
4025  * For a specific domain on the server, fetch all the aliases
4026  * and their members. Add all of them to the server_aliases.
4027  */
4028
4029 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4030                                         TALLOC_CTX *mem_ctx,
4031                                         struct policy_handle *connect_pol,
4032                                         const struct dom_sid *domain_sid)
4033 {
4034         uint32 start_idx, max_entries, num_entries, i;
4035         struct samr_SamArray *groups = NULL;
4036         NTSTATUS result;
4037         struct policy_handle domain_pol;
4038
4039         /* Get domain policy handle */
4040
4041         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
4042                                         connect_pol,
4043                                         MAXIMUM_ALLOWED_ACCESS,
4044                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
4045                                         &domain_pol);
4046         if (!NT_STATUS_IS_OK(result))
4047                 return result;
4048
4049         start_idx = 0;
4050         max_entries = 250;
4051
4052         do {
4053                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
4054                                                        &domain_pol,
4055                                                        &start_idx,
4056                                                        &groups,
4057                                                        max_entries,
4058                                                        &num_entries);
4059                 for (i = 0; i < num_entries; i++) {
4060
4061                         struct policy_handle alias_pol;
4062                         struct full_alias alias;
4063                         struct lsa_SidArray sid_array;
4064                         int j;
4065
4066                         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
4067                                                        &domain_pol,
4068                                                        MAXIMUM_ALLOWED_ACCESS,
4069                                                        groups->entries[i].idx,
4070                                                        &alias_pol);
4071                         if (!NT_STATUS_IS_OK(result))
4072                                 goto done;
4073
4074                         result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
4075                                                                &alias_pol,
4076                                                                &sid_array);
4077                         if (!NT_STATUS_IS_OK(result))
4078                                 goto done;
4079
4080                         alias.num_members = sid_array.num_sids;
4081
4082                         result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
4083                         if (!NT_STATUS_IS_OK(result))
4084                                 goto done;
4085
4086                         alias.members = NULL;
4087
4088                         if (alias.num_members > 0) {
4089                                 alias.members = SMB_MALLOC_ARRAY(struct dom_sid, alias.num_members);
4090
4091                                 for (j = 0; j < alias.num_members; j++)
4092                                         sid_copy(&alias.members[j],
4093                                                  sid_array.sids[j].sid);
4094                         }
4095
4096                         sid_compose(&alias.sid, domain_sid,
4097                                     groups->entries[i].idx);
4098
4099                         push_alias(mem_ctx, &alias);
4100                 }
4101         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4102
4103         result = NT_STATUS_OK;
4104
4105  done:
4106         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
4107
4108         return result;
4109 }
4110
4111 /*
4112  * Dump server_aliases as names for debugging purposes.
4113  */
4114
4115 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4116                                 const struct dom_sid *domain_sid,
4117                                 const char *domain_name,
4118                                 struct cli_state *cli,
4119                                 struct rpc_pipe_client *pipe_hnd,
4120                                 TALLOC_CTX *mem_ctx,
4121                                 int argc,
4122                                 const char **argv)
4123 {
4124         int i;
4125         NTSTATUS result;
4126         struct policy_handle lsa_pol;
4127
4128         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4129                                      SEC_FLAG_MAXIMUM_ALLOWED,
4130                                      &lsa_pol);
4131         if (!NT_STATUS_IS_OK(result))
4132                 return result;
4133
4134         for (i=0; i<num_server_aliases; i++) {
4135                 char **names;
4136                 char **domains;
4137                 enum lsa_SidType *types;
4138                 int j;
4139
4140                 struct full_alias *alias = &server_aliases[i];
4141
4142                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4143                                              &alias->sid,
4144                                              &domains, &names, &types);
4145                 if (!NT_STATUS_IS_OK(result))
4146                         continue;
4147
4148                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4149
4150                 if (alias->num_members == 0) {
4151                         DEBUG(1, ("\n"));
4152                         continue;
4153                 }
4154
4155                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4156                                              alias->num_members,
4157                                              alias->members,
4158                                              &domains, &names, &types);
4159
4160                 if (!NT_STATUS_IS_OK(result) &&
4161                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4162                         continue;
4163
4164                 for (j=0; j<alias->num_members; j++)
4165                         DEBUG(1, ("%s\\%s (%d); ",
4166                                   domains[j] ? domains[j] : "*unknown*", 
4167                                   names[j] ? names[j] : "*unknown*",types[j]));
4168                 DEBUG(1, ("\n"));
4169         }
4170
4171         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
4172
4173         return NT_STATUS_OK;
4174 }
4175
4176 /*
4177  * Fetch a list of all server aliases and their members into
4178  * server_aliases.
4179  */
4180
4181 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4182                                         const struct dom_sid *domain_sid,
4183                                         const char *domain_name,
4184                                         struct cli_state *cli,
4185                                         struct rpc_pipe_client *pipe_hnd,
4186                                         TALLOC_CTX *mem_ctx,
4187                                         int argc,
4188                                         const char **argv)
4189 {
4190         NTSTATUS result;
4191         struct policy_handle connect_pol;
4192
4193         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
4194                                       pipe_hnd->desthost,
4195                                       MAXIMUM_ALLOWED_ACCESS,
4196                                       &connect_pol);
4197
4198         if (!NT_STATUS_IS_OK(result))
4199                 goto done;
4200
4201         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4202                                           &global_sid_Builtin);
4203
4204         if (!NT_STATUS_IS_OK(result))
4205                 goto done;
4206
4207         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4208                                           domain_sid);
4209
4210         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
4211  done:
4212         return result;
4213 }
4214
4215 static void init_user_token(struct security_token *token, struct dom_sid *user_sid)
4216 {
4217         token->num_sids = 4;
4218
4219         if (!(token->sids = SMB_MALLOC_ARRAY(struct dom_sid, 4))) {
4220                 d_fprintf(stderr, "malloc %s\n",_("failed"));
4221                 token->num_sids = 0;
4222                 return;
4223         }
4224
4225         token->sids[0] = *user_sid;
4226         sid_copy(&token->sids[1], &global_sid_World);
4227         sid_copy(&token->sids[2], &global_sid_Network);
4228         sid_copy(&token->sids[3], &global_sid_Authenticated_Users);
4229 }
4230
4231 static void free_user_token(struct security_token *token)
4232 {
4233         SAFE_FREE(token->sids);
4234 }
4235
4236 static void add_sid_to_token(struct security_token *token, struct dom_sid *sid)
4237 {
4238         if (security_token_has_sid(token, sid))
4239                 return;
4240
4241         token->sids = SMB_REALLOC_ARRAY(token->sids, struct dom_sid, token->num_sids+1);
4242         if (!token->sids) {
4243                 return;
4244         }
4245
4246         sid_copy(&token->sids[token->num_sids], sid);
4247
4248         token->num_sids += 1;
4249 }
4250
4251 struct user_token {
4252         fstring name;
4253         struct security_token token;
4254 };
4255
4256 static void dump_user_token(struct user_token *token)
4257 {
4258         int i;
4259
4260         d_printf("%s\n", token->name);
4261
4262         for (i=0; i<token->token.num_sids; i++) {
4263                 d_printf(" %s\n", sid_string_tos(&token->token.sids[i]));
4264         }
4265 }
4266
4267 static bool is_alias_member(struct dom_sid *sid, struct full_alias *alias)
4268 {
4269         int i;
4270
4271         for (i=0; i<alias->num_members; i++) {
4272                 if (dom_sid_compare(sid, &alias->members[i]) == 0)
4273                         return true;
4274         }
4275
4276         return false;
4277 }
4278
4279 static void collect_sid_memberships(struct security_token *token, struct dom_sid sid)
4280 {
4281         int i;
4282
4283         for (i=0; i<num_server_aliases; i++) {
4284                 if (is_alias_member(&sid, &server_aliases[i]))
4285                         add_sid_to_token(token, &server_aliases[i].sid);
4286         }
4287 }
4288
4289 /*
4290  * We got a user token with all the SIDs we can know about without asking the
4291  * server directly. These are the user and domain group sids. All of these can
4292  * be members of aliases. So scan the list of aliases for each of the SIDs and
4293  * add them to the token.
4294  */
4295
4296 static void collect_alias_memberships(struct security_token *token)
4297 {
4298         int num_global_sids = token->num_sids;
4299         int i;
4300
4301         for (i=0; i<num_global_sids; i++) {
4302                 collect_sid_memberships(token, token->sids[i]);
4303         }
4304 }
4305
4306 static bool get_user_sids(const char *domain, const char *user, struct security_token *token)
4307 {
4308         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4309         enum wbcSidType type;
4310         fstring full_name;
4311         struct wbcDomainSid wsid;
4312         char *sid_str = NULL;
4313         struct dom_sid user_sid;
4314         uint32_t num_groups;
4315         gid_t *groups = NULL;
4316         uint32_t i;
4317
4318         fstr_sprintf(full_name, "%s%c%s",
4319                      domain, *lp_winbind_separator(), user);
4320
4321         /* First let's find out the user sid */
4322
4323         wbc_status = wbcLookupName(domain, user, &wsid, &type);
4324
4325         if (!WBC_ERROR_IS_OK(wbc_status)) {
4326                 DEBUG(1, ("winbind could not find %s: %s\n",
4327                           full_name, wbcErrorString(wbc_status)));
4328                 return false;
4329         }
4330
4331         wbc_status = wbcSidToString(&wsid, &sid_str);
4332         if (!WBC_ERROR_IS_OK(wbc_status)) {
4333                 return false;
4334         }
4335
4336         if (type != WBC_SID_NAME_USER) {
4337                 wbcFreeMemory(sid_str);
4338                 DEBUG(1, ("%s is not a user\n", full_name));
4339                 return false;
4340         }
4341
4342         if (!string_to_sid(&user_sid, sid_str)) {
4343                 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4344                 return false;
4345         }
4346
4347         wbcFreeMemory(sid_str);
4348         sid_str = NULL;
4349
4350         init_user_token(token, &user_sid);
4351
4352         /* And now the groups winbind knows about */
4353
4354         wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4355         if (!WBC_ERROR_IS_OK(wbc_status)) {
4356                 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4357                         full_name, wbcErrorString(wbc_status)));
4358                 return false;
4359         }
4360
4361         for (i = 0; i < num_groups; i++) {
4362                 gid_t gid = groups[i];
4363                 struct dom_sid sid;
4364
4365                 wbc_status = wbcGidToSid(gid, &wsid);
4366                 if (!WBC_ERROR_IS_OK(wbc_status)) {
4367                         DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4368                                   (unsigned int)gid, wbcErrorString(wbc_status)));
4369                         wbcFreeMemory(groups);
4370                         return false;
4371                 }
4372
4373                 wbc_status = wbcSidToString(&wsid, &sid_str);
4374                 if (!WBC_ERROR_IS_OK(wbc_status)) {
4375                         wbcFreeMemory(groups);
4376                         return false;
4377                 }
4378
4379                 DEBUG(3, (" %s\n", sid_str));
4380
4381                 string_to_sid(&sid, sid_str);
4382                 wbcFreeMemory(sid_str);
4383                 sid_str = NULL;
4384
4385                 add_sid_to_token(token, &sid);
4386         }
4387         wbcFreeMemory(groups);
4388
4389         return true;
4390 }
4391
4392 /**
4393  * Get a list of all user tokens we want to look at
4394  **/
4395
4396 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4397                             struct user_token **user_tokens)
4398 {
4399         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4400         uint32_t i, num_users;
4401         const char **users;
4402         struct user_token *result;
4403         TALLOC_CTX *frame = NULL;
4404
4405         if (lp_winbind_use_default_domain() &&
4406             (c->opt_target_workgroup == NULL)) {
4407                 d_fprintf(stderr, _("winbind use default domain = yes set, "
4408                          "please specify a workgroup\n"));
4409                 return false;
4410         }
4411
4412         /* Send request to winbind daemon */
4413
4414         wbc_status = wbcListUsers(NULL, &num_users, &users);
4415         if (!WBC_ERROR_IS_OK(wbc_status)) {
4416                 DEBUG(1, (_("winbind could not list users: %s\n"),
4417                           wbcErrorString(wbc_status)));
4418                 return false;
4419         }
4420
4421         result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4422
4423         if (result == NULL) {
4424                 DEBUG(1, ("Could not malloc sid array\n"));
4425                 wbcFreeMemory(users);
4426                 return false;
4427         }
4428
4429         frame = talloc_stackframe();
4430         for (i=0; i < num_users; i++) {
4431                 fstring domain, user;
4432                 char *p;
4433
4434                 fstrcpy(result[i].name, users[i]);
4435
4436                 p = strchr(users[i], *lp_winbind_separator());
4437
4438                 DEBUG(3, ("%s\n", users[i]));
4439
4440                 if (p == NULL) {
4441                         fstrcpy(domain, c->opt_target_workgroup);
4442                         fstrcpy(user, users[i]);
4443                 } else {
4444                         *p++ = '\0';
4445                         fstrcpy(domain, users[i]);
4446                         strupper_m(domain);
4447                         fstrcpy(user, p);
4448                 }
4449
4450                 get_user_sids(domain, user, &(result[i].token));
4451         }
4452         TALLOC_FREE(frame);
4453         wbcFreeMemory(users);
4454
4455         *num_tokens = num_users;
4456         *user_tokens = result;
4457
4458         return true;
4459 }
4460
4461 static bool get_user_tokens_from_file(FILE *f,
4462                                       int *num_tokens,
4463                                       struct user_token **tokens)
4464 {
4465         struct user_token *token = NULL;
4466
4467         while (!feof(f)) {
4468                 fstring line;
4469
4470                 if (fgets(line, sizeof(line)-1, f) == NULL) {
4471                         return true;
4472                 }
4473
4474                 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
4475                         line[strlen(line)-1] = '\0';
4476                 }
4477
4478                 if (line[0] == ' ') {
4479                         /* We have a SID */
4480
4481                         struct dom_sid sid;
4482                         if(!string_to_sid(&sid, &line[1])) {
4483                                 DEBUG(1,("get_user_tokens_from_file: Could "
4484                                         "not convert sid %s \n",&line[1]));
4485                                 return false;
4486                         }
4487
4488                         if (token == NULL) {
4489                                 DEBUG(0, ("File does not begin with username"));
4490                                 return false;
4491                         }
4492
4493                         add_sid_to_token(&token->token, &sid);
4494                         continue;
4495                 }
4496
4497                 /* And a new user... */
4498
4499                 *num_tokens += 1;
4500                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4501                 if (*tokens == NULL) {
4502                         DEBUG(0, ("Could not realloc tokens\n"));
4503                         return false;
4504                 }
4505
4506                 token = &((*tokens)[*num_tokens-1]);
4507
4508                 fstrcpy(token->name, line);
4509                 token->token.num_sids = 0;
4510                 token->token.sids = NULL;
4511                 continue;
4512         }
4513         
4514         return false;
4515 }
4516
4517
4518 /*
4519  * Show the list of all users that have access to a share
4520  */
4521
4522 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4523                         TALLOC_CTX *mem_ctx,
4524                         const char *netname,
4525                         int num_tokens,
4526                         struct user_token *tokens)
4527 {
4528         uint16_t fnum;
4529         struct security_descriptor *share_sd = NULL;
4530         struct security_descriptor *root_sd = NULL;
4531         struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4532         int i;
4533         union srvsvc_NetShareInfo info;
4534         WERROR result;
4535         NTSTATUS status;
4536         uint16 cnum;
4537         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4538
4539         status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
4540                                                pipe_hnd->desthost,
4541                                                netname,
4542                                                502,
4543                                                &info,
4544                                                &result);
4545
4546         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4547                 DEBUG(1, ("Coult not query secdesc for share %s\n",
4548                           netname));
4549                 return;
4550         }
4551
4552         share_sd = info.info502->sd_buf.sd;
4553         if (share_sd == NULL) {
4554                 DEBUG(1, ("Got no secdesc for share %s\n",
4555                           netname));
4556         }
4557
4558         cnum = cli->cnum;
4559
4560         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
4561                 return;
4562         }
4563
4564         if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
4565                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
4566                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4567         }
4568
4569         for (i=0; i<num_tokens; i++) {
4570                 uint32 acc_granted;
4571
4572                 if (share_sd != NULL) {
4573                         status = se_access_check(share_sd, &tokens[i].token,
4574                                              1, &acc_granted);
4575
4576                         if (!NT_STATUS_IS_OK(status)) {
4577                                 DEBUG(1, ("Could not check share_sd for "
4578                                           "user %s\n",
4579                                           tokens[i].name));
4580                                 continue;
4581                         }
4582                 }
4583
4584                 if (root_sd == NULL) {
4585                         d_printf(" %s\n", tokens[i].name);
4586                         continue;
4587                 }
4588
4589                 status = se_access_check(root_sd, &tokens[i].token,
4590                                      1, &acc_granted);
4591                 if (!NT_STATUS_IS_OK(status)) {
4592                         DEBUG(1, ("Could not check root_sd for user %s\n",
4593                                   tokens[i].name));
4594                         continue;
4595                 }
4596                 d_printf(" %s\n", tokens[i].name);
4597         }
4598
4599         if (fnum != (uint16_t)-1)
4600                 cli_close(cli, fnum);
4601         cli_tdis(cli);
4602         cli->cnum = cnum;
4603         
4604         return;
4605 }
4606
4607 struct share_list {
4608         int num_shares;
4609         char **shares;
4610 };
4611
4612 static void collect_share(const char *name, uint32 m,
4613                           const char *comment, void *state)
4614 {
4615         struct share_list *share_list = (struct share_list *)state;
4616
4617         if (m != STYPE_DISKTREE)
4618                 return;
4619
4620         share_list->num_shares += 1;
4621         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4622         if (!share_list->shares) {
4623                 share_list->num_shares = 0;
4624                 return;
4625         }
4626         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4627 }
4628
4629 /**
4630  * List shares on a remote RPC server, including the security descriptors.
4631  *
4632  * All parameters are provided by the run_rpc_command function, except for
4633  * argc, argv which are passed through.
4634  *
4635  * @param domain_sid The domain sid acquired from the remote server.
4636  * @param cli A cli_state connected to the server.
4637  * @param mem_ctx Talloc context, destroyed on completion of the function.
4638  * @param argc  Standard main() style argc.
4639  * @param argv  Standard main() style argv. Initial components are already
4640  *              stripped.
4641  *
4642  * @return Normal NTSTATUS return.
4643  **/
4644
4645 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
4646                                                 const struct dom_sid *domain_sid,
4647                                                 const char *domain_name,
4648                                                 struct cli_state *cli,
4649                                                 struct rpc_pipe_client *pipe_hnd,
4650                                                 TALLOC_CTX *mem_ctx,
4651                                                 int argc,
4652                                                 const char **argv)
4653 {
4654         int ret;
4655         bool r;
4656         uint32 i;
4657         FILE *f;
4658
4659         struct user_token *tokens = NULL;
4660         int num_tokens = 0;
4661
4662         struct share_list share_list;
4663
4664         if (argc == 0) {
4665                 f = stdin;
4666         } else {
4667                 f = fopen(argv[0], "r");
4668         }
4669
4670         if (f == NULL) {
4671                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4672                 return NT_STATUS_UNSUCCESSFUL;
4673         }
4674
4675         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4676
4677         if (f != stdin)
4678                 fclose(f);
4679
4680         if (!r) {
4681                 DEBUG(0, ("Could not read users from file\n"));
4682                 return NT_STATUS_UNSUCCESSFUL;
4683         }
4684
4685         for (i=0; i<num_tokens; i++)
4686                 collect_alias_memberships(&tokens[i].token);
4687
4688         share_list.num_shares = 0;
4689         share_list.shares = NULL;
4690
4691         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4692
4693         if (ret == -1) {
4694                 DEBUG(0, ("Error returning browse list: %s\n",
4695                           cli_errstr(cli)));
4696                 goto done;
4697         }
4698
4699         for (i = 0; i < share_list.num_shares; i++) {
4700                 char *netname = share_list.shares[i];
4701
4702                 if (netname[strlen(netname)-1] == '$')
4703                         continue;
4704
4705                 d_printf("%s\n", netname);
4706
4707                 show_userlist(pipe_hnd, mem_ctx, netname,
4708                               num_tokens, tokens);
4709         }
4710  done:
4711         for (i=0; i<num_tokens; i++) {
4712                 free_user_token(&tokens[i].token);
4713         }
4714         SAFE_FREE(tokens);
4715         SAFE_FREE(share_list.shares);
4716
4717         return NT_STATUS_OK;
4718 }
4719
4720 static int rpc_share_allowedusers(struct net_context *c, int argc,
4721                                   const char **argv)
4722 {
4723         int result;
4724
4725         if (c->display_usage) {
4726                 d_printf(  "%s\n"
4727                            "net rpc share allowedusers\n"
4728                             "    %s\n",
4729                           _("Usage:"),
4730                           _("List allowed users"));
4731                 return 0;
4732         }
4733
4734         result = run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
4735                                  rpc_aliaslist_internals,
4736                                  argc, argv);
4737         if (result != 0)
4738                 return result;
4739
4740         result = run_rpc_command(c, NULL, &ndr_table_lsarpc.syntax_id, 0,
4741                                  rpc_aliaslist_dump,
4742                                  argc, argv);
4743         if (result != 0)
4744                 return result;
4745
4746         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4747                                rpc_share_allowedusers_internals,
4748                                argc, argv);
4749 }
4750
4751 int net_usersidlist(struct net_context *c, int argc, const char **argv)
4752 {
4753         int num_tokens = 0;
4754         struct user_token *tokens = NULL;
4755         int i;
4756
4757         if (argc != 0) {
4758                 net_usersidlist_usage(c, argc, argv);
4759                 return 0;
4760         }
4761
4762         if (!get_user_tokens(c, &num_tokens, &tokens)) {
4763                 DEBUG(0, ("Could not get the user/sid list\n"));
4764                 return 0;
4765         }
4766
4767         for (i=0; i<num_tokens; i++) {
4768                 dump_user_token(&tokens[i]);
4769                 free_user_token(&tokens[i].token);
4770         }
4771
4772         SAFE_FREE(tokens);
4773         return 1;
4774 }
4775
4776 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
4777 {
4778         d_printf(_("net usersidlist\n"
4779                    "\tprints out a list of all users the running winbind knows\n"
4780                    "\tabout, together with all their SIDs. This is used as\n"
4781                    "\tinput to the 'net rpc share allowedusers' command.\n\n"));
4782
4783         net_common_flags_usage(c, argc, argv);
4784         return -1;
4785 }
4786
4787 /**
4788  * 'net rpc share' entrypoint.
4789  * @param argc  Standard main() style argc.
4790  * @param argv  Standard main() style argv. Initial components are already
4791  *              stripped.
4792  **/
4793
4794 int net_rpc_share(struct net_context *c, int argc, const char **argv)
4795 {
4796         NET_API_STATUS status;
4797
4798         struct functable func[] = {
4799                 {
4800                         "add",
4801                         rpc_share_add,
4802                         NET_TRANSPORT_RPC,
4803                         N_("Add share"),
4804                         N_("net rpc share add\n"
4805                            "    Add share")
4806                 },
4807                 {
4808                         "delete",
4809                         rpc_share_delete,
4810                         NET_TRANSPORT_RPC,
4811                         N_("Remove share"),
4812                         N_("net rpc share delete\n"
4813                            "    Remove share")
4814                 },
4815                 {
4816                         "allowedusers",
4817                         rpc_share_allowedusers,
4818                         NET_TRANSPORT_RPC,
4819                         N_("Modify allowed users"),
4820                         N_("net rpc share allowedusers\n"
4821                            "    Modify allowed users")
4822                 },
4823                 {
4824                         "migrate",
4825                         rpc_share_migrate,
4826                         NET_TRANSPORT_RPC,
4827                         N_("Migrate share to local server"),
4828                         N_("net rpc share migrate\n"
4829                            "    Migrate share to local server")
4830                 },
4831                 {
4832                         "list",
4833                         rpc_share_list,
4834                         NET_TRANSPORT_RPC,
4835                         N_("List shares"),
4836                         N_("net rpc share list\n"
4837                            "    List shares")
4838                 },
4839                 {NULL, NULL, 0, NULL, NULL}
4840         };
4841
4842         status = libnetapi_net_init(&c->netapi_ctx);
4843         if (status != 0) {
4844                 return -1;
4845         }
4846         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
4847         libnetapi_set_password(c->netapi_ctx, c->opt_password);
4848         if (c->opt_kerberos) {
4849                 libnetapi_set_use_kerberos(c->netapi_ctx);
4850         }
4851
4852         if (argc == 0) {
4853                 if (c->display_usage) {
4854                         d_printf("%s\n%s",
4855                                  _("Usage:"),
4856                                  _("net rpc share\n"
4857                                    "    List shares\n"
4858                                    "    Alias for net rpc share list\n"));
4859                         net_display_usage_from_functable(func);
4860                         return 0;
4861                 }
4862
4863                 return rpc_share_list(c, argc, argv);
4864         }
4865
4866         return net_run_function(c, argc, argv, "net rpc share", func);
4867 }
4868
4869 static NTSTATUS rpc_sh_share_list(struct net_context *c,
4870                                   TALLOC_CTX *mem_ctx,
4871                                   struct rpc_sh_ctx *ctx,
4872                                   struct rpc_pipe_client *pipe_hnd,
4873                                   int argc, const char **argv)
4874 {
4875
4876         return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
4877 }
4878
4879 static NTSTATUS rpc_sh_share_add(struct net_context *c,
4880                                  TALLOC_CTX *mem_ctx,
4881                                  struct rpc_sh_ctx *ctx,
4882                                  struct rpc_pipe_client *pipe_hnd,
4883                                  int argc, const char **argv)
4884 {
4885         NET_API_STATUS status;
4886         uint32_t parm_err = 0;
4887         struct SHARE_INFO_2 i2;
4888
4889         if ((argc < 2) || (argc > 3)) {
4890                 d_fprintf(stderr, _("Usage: %s <share> <path> [comment]\n"),
4891                           ctx->whoami);
4892                 return NT_STATUS_INVALID_PARAMETER;
4893         }
4894
4895         i2.shi2_netname         = argv[0];
4896         i2.shi2_type            = STYPE_DISKTREE;
4897         i2.shi2_remark          = (argc == 3) ? argv[2] : "";
4898         i2.shi2_permissions     = 0;
4899         i2.shi2_max_uses        = 0;
4900         i2.shi2_current_uses    = 0;
4901         i2.shi2_path            = argv[1];
4902         i2.shi2_passwd          = NULL;
4903
4904         status = NetShareAdd(pipe_hnd->desthost,
4905                              2,
4906                              (uint8_t *)&i2,
4907                              &parm_err);
4908
4909         return werror_to_ntstatus(W_ERROR(status));
4910 }
4911
4912 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
4913                                     TALLOC_CTX *mem_ctx,
4914                                     struct rpc_sh_ctx *ctx,
4915                                     struct rpc_pipe_client *pipe_hnd,
4916                                     int argc, const char **argv)
4917 {
4918         if (argc != 1) {
4919                 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
4920                 return NT_STATUS_INVALID_PARAMETER;
4921         }
4922
4923         return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
4924 }
4925
4926 static NTSTATUS rpc_sh_share_info(struct net_context *c,
4927                                   TALLOC_CTX *mem_ctx,
4928                                   struct rpc_sh_ctx *ctx,
4929                                   struct rpc_pipe_client *pipe_hnd,
4930                                   int argc, const char **argv)
4931 {
4932         union srvsvc_NetShareInfo info;
4933         WERROR result;
4934         NTSTATUS status;
4935         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
4936
4937         if (argc != 1) {
4938                 d_fprintf(stderr, "%s %s <share>\n", _("Usage:"), ctx->whoami);
4939                 return NT_STATUS_INVALID_PARAMETER;
4940         }
4941
4942         status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
4943                                                pipe_hnd->desthost,
4944                                                argv[0],
4945                                                2,
4946                                                &info,
4947                                                &result);
4948         if (!NT_STATUS_IS_OK(status)) {
4949                 result = ntstatus_to_werror(status);
4950                 goto done;
4951         }
4952         if (!W_ERROR_IS_OK(result)) {
4953                 goto done;
4954         }
4955
4956         d_printf(_("Name:     %s\n"), info.info2->name);
4957         d_printf(_("Comment:  %s\n"), info.info2->comment);
4958         d_printf(_("Path:     %s\n"), info.info2->path);
4959         d_printf(_("Password: %s\n"), info.info2->password);
4960
4961  done:
4962         return werror_to_ntstatus(result);
4963 }
4964
4965 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
4966                                       struct rpc_sh_ctx *ctx)
4967 {
4968         static struct rpc_sh_cmd cmds[] = {
4969
4970         { "list", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_list,
4971           N_("List available shares") },
4972
4973         { "add", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_add,
4974           N_("Add a share") },
4975
4976         { "delete", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_delete,
4977           N_("Delete a share") },
4978
4979         { "info", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_info,
4980           N_("Get information about a share") },
4981
4982         { NULL, NULL, 0, NULL, NULL }
4983         };
4984
4985         return cmds;
4986 }
4987
4988 /****************************************************************************/
4989
4990 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
4991 {
4992         return net_file_usage(c, argc, argv);
4993 }
4994
4995 /**
4996  * Close a file on a remote RPC server.
4997  *
4998  * @param argc  Standard main() style argc.
4999  * @param argv  Standard main() style argv. Initial components are already
5000  *              stripped.
5001  *
5002  * @return A shell status integer (0 for success).
5003  **/
5004 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5005 {
5006         if (argc < 1 || c->display_usage) {
5007                 return rpc_file_usage(c, argc, argv);
5008         }
5009
5010         return NetFileClose(c->opt_host, atoi(argv[0]));
5011 }
5012
5013 /**
5014  * Formatted print of open file info
5015  *
5016  * @param r  struct FILE_INFO_3 contents
5017  **/
5018
5019 static void display_file_info_3(struct FILE_INFO_3 *r)
5020 {
5021         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5022                  r->fi3_id, r->fi3_username, r->fi3_permissions,
5023                  r->fi3_num_locks, r->fi3_pathname);
5024 }
5025
5026 /**
5027  * List files for a user on a remote RPC server.
5028  *
5029  * @param argc  Standard main() style argc.
5030  * @param argv  Standard main() style argv. Initial components are already
5031  *              stripped.
5032  *
5033  * @return A shell status integer (0 for success)..
5034  **/
5035
5036 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5037 {
5038         NET_API_STATUS status;
5039         uint32 preferred_len = 0xffffffff, i;
5040         const char *username=NULL;
5041         uint32_t total_entries = 0;
5042         uint32_t entries_read = 0;
5043         uint32_t resume_handle = 0;
5044         struct FILE_INFO_3 *i3 = NULL;
5045
5046         if (c->display_usage) {
5047                 return rpc_file_usage(c, argc, argv);
5048         }
5049
5050         /* if argc > 0, must be user command */
5051         if (argc > 0) {
5052                 username = smb_xstrdup(argv[0]);
5053         }
5054
5055         status = NetFileEnum(c->opt_host,
5056                              NULL,
5057                              username,
5058                              3,
5059                              (uint8_t **)(void *)&i3,
5060                              preferred_len,
5061                              &entries_read,
5062                              &total_entries,
5063                              &resume_handle);
5064
5065         if (status != 0) {
5066                 goto done;
5067         }
5068
5069         /* Display results */
5070
5071         d_printf(_(
5072                  "\nEnumerating open files on remote server:\n\n"
5073                  "\nFileId  Opened by            Perms  Locks  Path"
5074                  "\n------  ---------            -----  -----  ---- \n"));
5075         for (i = 0; i < entries_read; i++) {
5076                 display_file_info_3(&i3[i]);
5077         }
5078  done:
5079         return status;
5080 }
5081
5082 /**
5083  * 'net rpc file' entrypoint.
5084  * @param argc  Standard main() style argc.
5085  * @param argv  Standard main() style argv. Initial components are already
5086  *              stripped.
5087  **/
5088
5089 int net_rpc_file(struct net_context *c, int argc, const char **argv)
5090 {
5091         NET_API_STATUS status;
5092
5093         struct functable func[] = {
5094                 {
5095                         "close",
5096                         rpc_file_close,
5097                         NET_TRANSPORT_RPC,
5098                         N_("Close opened file"),
5099                         N_("net rpc file close\n"
5100                            "    Close opened file")
5101                 },
5102                 {
5103                         "user",
5104                         rpc_file_user,
5105                         NET_TRANSPORT_RPC,
5106                         N_("List files opened by user"),
5107                         N_("net rpc file user\n"
5108                            "    List files opened by user")
5109                 },
5110 #if 0
5111                 {
5112                         "info",
5113                         rpc_file_info,
5114                         NET_TRANSPORT_RPC,
5115                         N_("Display information about opened file"),
5116                         N_("net rpc file info\n"
5117                            "    Display information about opened file")
5118                 },
5119 #endif
5120                 {NULL, NULL, 0, NULL, NULL}
5121         };
5122
5123         status = libnetapi_net_init(&c->netapi_ctx);
5124         if (status != 0) {
5125                 return -1;
5126         }
5127         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
5128         libnetapi_set_password(c->netapi_ctx, c->opt_password);
5129         if (c->opt_kerberos) {
5130                 libnetapi_set_use_kerberos(c->netapi_ctx);
5131         }
5132
5133         if (argc == 0) {
5134                 if (c->display_usage) {
5135                         d_printf(_("Usage:\n"));
5136                         d_printf(_("net rpc file\n"
5137                                    "    List opened files\n"));
5138                         net_display_usage_from_functable(func);
5139                         return 0;
5140                 }
5141
5142                 return rpc_file_user(c, argc, argv);
5143         }
5144
5145         return net_run_function(c, argc, argv, "net rpc file", func);
5146 }
5147
5148 /**
5149  * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5150  *
5151  * All parameters are provided by the run_rpc_command function, except for
5152  * argc, argv which are passed through.
5153  *
5154  * @param c     A net_context structure.
5155  * @param domain_sid The domain sid acquired from the remote server.
5156  * @param cli A cli_state connected to the server.
5157  * @param mem_ctx Talloc context, destroyed on completion of the function.
5158  * @param argc  Standard main() style argc.
5159  * @param argv  Standard main() style argv. Initial components are already
5160  *              stripped.
5161  *
5162  * @return Normal NTSTATUS return.
5163  **/
5164
5165 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5166                                         const struct dom_sid *domain_sid,
5167                                         const char *domain_name,
5168                                         struct cli_state *cli,
5169                                         struct rpc_pipe_client *pipe_hnd,
5170                                         TALLOC_CTX *mem_ctx,
5171                                         int argc,
5172                                         const char **argv)
5173 {
5174         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5175         WERROR result;
5176         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5177
5178         status = dcerpc_initshutdown_Abort(b, mem_ctx, NULL, &result);
5179         if (!NT_STATUS_IS_OK(status)) {
5180                 return status;
5181         }
5182         if (W_ERROR_IS_OK(result)) {
5183                 d_printf(_("\nShutdown successfully aborted\n"));
5184                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5185         } else
5186                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5187
5188         return werror_to_ntstatus(result);
5189 }
5190
5191 /**
5192  * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5193  *
5194  * All parameters are provided by the run_rpc_command function, except for
5195  * argc, argv which are passed through.
5196  *
5197  * @param c     A net_context structure.
5198  * @param domain_sid The domain sid acquired from the remote server.
5199  * @param cli A cli_state connected to the server.
5200  * @param mem_ctx Talloc context, destroyed on completion of the function.
5201  * @param argc  Standard main() style argc.
5202  * @param argv  Standard main() style argv. Initial components are already
5203  *              stripped.
5204  *
5205  * @return Normal NTSTATUS return.
5206  **/
5207
5208 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5209                                                 const struct dom_sid *domain_sid,
5210                                                 const char *domain_name,
5211                                                 struct cli_state *cli,
5212                                                 struct rpc_pipe_client *pipe_hnd,
5213                                                 TALLOC_CTX *mem_ctx,
5214                                                 int argc,
5215                                                 const char **argv)
5216 {
5217         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5218         WERROR werr;
5219         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5220
5221         result = dcerpc_winreg_AbortSystemShutdown(b, mem_ctx, NULL, &werr);
5222
5223         if (!NT_STATUS_IS_OK(result)) {
5224                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5225                 return result;
5226         }
5227         if (W_ERROR_IS_OK(werr)) {
5228                 d_printf(_("\nShutdown successfully aborted\n"));
5229                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5230         } else
5231                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5232
5233         return werror_to_ntstatus(werr);
5234 }
5235
5236 /**
5237  * ABORT the shutdown of a remote RPC server.
5238  *
5239  * @param argc  Standard main() style argc.
5240  * @param argv  Standard main() style argv. Initial components are already
5241  *              stripped.
5242  *
5243  * @return A shell status integer (0 for success).
5244  **/
5245
5246 static int rpc_shutdown_abort(struct net_context *c, int argc,
5247                               const char **argv)
5248 {
5249         int rc = -1;
5250
5251         if (c->display_usage) {
5252                 d_printf(  "%s\n"
5253                            "net rpc abortshutdown\n"
5254                            "    %s\n",
5255                          _("Usage:"),
5256                          _("Abort a scheduled shutdown"));
5257                 return 0;
5258         }
5259
5260         rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5261                              rpc_shutdown_abort_internals, argc, argv);
5262
5263         if (rc == 0)
5264                 return rc;
5265
5266         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5267
5268         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5269                                rpc_reg_shutdown_abort_internals,
5270                                argc, argv);
5271 }
5272
5273 /**
5274  * Shut down a remote RPC Server via initshutdown pipe.
5275  *
5276  * All parameters are provided by the run_rpc_command function, except for
5277  * argc, argv which are passed through.
5278  *
5279  * @param c     A net_context structure.
5280  * @param domain_sid The domain sid acquired from the remote server.
5281  * @param cli A cli_state connected to the server.
5282  * @param mem_ctx Talloc context, destroyed on completion of the function.
5283  * @param argc  Standard main() style argc.
5284  * @param argv  Standard main() style argv. Initial components are already
5285  *              stripped.
5286  *
5287  * @return Normal NTSTATUS return.
5288  **/
5289
5290 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5291                                      const struct dom_sid *domain_sid,
5292                                      const char *domain_name,
5293                                      struct cli_state *cli,
5294                                      struct rpc_pipe_client *pipe_hnd,
5295                                      TALLOC_CTX *mem_ctx,
5296                                      int argc,
5297                                      const char **argv)
5298 {
5299         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5300         WERROR result;
5301         const char *msg = N_("This machine will be shutdown shortly");
5302         uint32 timeout = 20;
5303         struct lsa_StringLarge msg_string;
5304         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5305
5306         if (c->opt_comment) {
5307                 msg = c->opt_comment;
5308         }
5309         if (c->opt_timeout) {
5310                 timeout = c->opt_timeout;
5311         }
5312
5313         msg_string.string = msg;
5314
5315         /* create an entry */
5316         status = dcerpc_initshutdown_Init(b, mem_ctx, NULL,
5317                         &msg_string, timeout, c->opt_force, c->opt_reboot,
5318                         &result);
5319         if (!NT_STATUS_IS_OK(status)) {
5320                 return status;
5321         }
5322         if (W_ERROR_IS_OK(result)) {
5323                 d_printf(_("\nShutdown of remote machine succeeded\n"));
5324                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5325         } else {
5326                 DEBUG(1,("Shutdown of remote machine failed!\n"));
5327         }
5328         return werror_to_ntstatus(result);
5329 }
5330
5331 /**
5332  * Shut down a remote RPC Server via winreg pipe.
5333  *
5334  * All parameters are provided by the run_rpc_command function, except for
5335  * argc, argv which are passed through.
5336  *
5337  * @param c     A net_context structure.
5338  * @param domain_sid The domain sid acquired from the remote server.
5339  * @param cli A cli_state connected to the server.
5340  * @param mem_ctx Talloc context, destroyed on completion of the function.
5341  * @param argc  Standard main() style argc.
5342  * @param argv  Standard main() style argv. Initial components are already
5343  *              stripped.
5344  *
5345  * @return Normal NTSTATUS return.
5346  **/
5347
5348 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5349                                     const struct dom_sid *domain_sid,
5350                                     const char *domain_name,
5351                                     struct cli_state *cli,
5352                                     struct rpc_pipe_client *pipe_hnd,
5353                                     TALLOC_CTX *mem_ctx,
5354                                     int argc,
5355                                     const char **argv)
5356 {
5357         const char *msg = N_("This machine will be shutdown shortly");
5358         uint32 timeout = 20;
5359         struct lsa_StringLarge msg_string;
5360         NTSTATUS result;
5361         WERROR werr;
5362         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5363
5364         if (c->opt_comment) {
5365                 msg = c->opt_comment;
5366         }
5367         msg_string.string = msg;
5368
5369         if (c->opt_timeout) {
5370                 timeout = c->opt_timeout;
5371         }
5372
5373         /* create an entry */
5374         result = dcerpc_winreg_InitiateSystemShutdown(b, mem_ctx, NULL,
5375                         &msg_string, timeout, c->opt_force, c->opt_reboot,
5376                         &werr);
5377         if (!NT_STATUS_IS_OK(result)) {
5378                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5379                 return result;
5380         }
5381
5382         if (W_ERROR_IS_OK(werr)) {
5383                 d_printf(_("\nShutdown of remote machine succeeded\n"));
5384         } else {
5385                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5386                 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5387                         d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5388                 else
5389                         d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5390         }
5391
5392         return werror_to_ntstatus(werr);
5393 }
5394
5395 /**
5396  * Shut down a remote RPC server.
5397  *
5398  * @param argc  Standard main() style argc.
5399  * @param argv  Standard main() style argv. Initial components are already
5400  *              stripped.
5401  *
5402  * @return A shell status integer (0 for success).
5403  **/
5404
5405 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5406 {
5407         int rc =  -1;
5408
5409         if (c->display_usage) {
5410                 d_printf(  "%s\n"
5411                            "net rpc shutdown\n"
5412                            "    %s\n",
5413                          _("Usage:"),
5414                          _("Shut down a remote RPC server"));
5415                 return 0;
5416         }
5417
5418         rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5419                              rpc_init_shutdown_internals, argc, argv);
5420
5421         if (rc) {
5422                 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5423                 rc = run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5424                                      rpc_reg_shutdown_internals, argc, argv);
5425         }
5426
5427         return rc;
5428 }
5429
5430 /***************************************************************************
5431   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5432  ***************************************************************************/
5433
5434 /**
5435  * Add interdomain trust account to the RPC server.
5436  * All parameters (except for argc and argv) are passed by run_rpc_command
5437  * function.
5438  *
5439  * @param c     A net_context structure.
5440  * @param domain_sid The domain sid acquired from the server.
5441  * @param cli A cli_state connected to the server.
5442  * @param mem_ctx Talloc context, destroyed on completion of the function.
5443  * @param argc  Standard main() style argc.
5444  * @param argv  Standard main() style argv. Initial components are already
5445  *              stripped.
5446  *
5447  * @return normal NTSTATUS return code.
5448  */
5449
5450 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
5451                                                 const struct dom_sid *domain_sid,
5452                                                 const char *domain_name,
5453                                                 struct cli_state *cli,
5454                                                 struct rpc_pipe_client *pipe_hnd,
5455                                                 TALLOC_CTX *mem_ctx,
5456                                                 int argc,
5457                                                 const char **argv)
5458 {
5459         struct policy_handle connect_pol, domain_pol, user_pol;
5460         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5461         char *acct_name;
5462         struct lsa_String lsa_acct_name;
5463         uint32 acb_info;
5464         uint32 acct_flags=0;
5465         uint32 user_rid;
5466         uint32_t access_granted = 0;
5467         union samr_UserInfo info;
5468         unsigned int orig_timeout;
5469
5470         if (argc != 2) {
5471                 d_printf("%s\n%s",
5472                          _("Usage:"),
5473                          _(" net rpc trustdom add <domain_name> "
5474                            "<trust password>\n"));
5475                 return NT_STATUS_INVALID_PARAMETER;
5476         }
5477
5478         /*
5479          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5480          */
5481
5482         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5483                 return NT_STATUS_NO_MEMORY;
5484         }
5485
5486         strupper_m(acct_name);
5487
5488         init_lsa_String(&lsa_acct_name, acct_name);
5489
5490         /* Get samr policy handle */
5491         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5492                                       pipe_hnd->desthost,
5493                                       MAXIMUM_ALLOWED_ACCESS,
5494                                       &connect_pol);
5495         if (!NT_STATUS_IS_OK(result)) {
5496                 goto done;
5497         }
5498
5499         /* Get domain policy handle */
5500         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5501                                         &connect_pol,
5502                                         MAXIMUM_ALLOWED_ACCESS,
5503                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5504                                         &domain_pol);
5505         if (!NT_STATUS_IS_OK(result)) {
5506                 goto done;
5507         }
5508
5509         /* This call can take a long time - allow the server to time out.
5510          * 35 seconds should do it. */
5511
5512         orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5513
5514         /* Create trusting domain's account */
5515         acb_info = ACB_NORMAL;
5516         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5517                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5518                      SAMR_USER_ACCESS_SET_PASSWORD |
5519                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
5520                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
5521
5522         result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5523                                          &domain_pol,
5524                                          &lsa_acct_name,
5525                                          acb_info,
5526                                          acct_flags,
5527                                          &user_pol,
5528                                          &access_granted,
5529                                          &user_rid);
5530
5531         /* And restore our original timeout. */
5532         rpccli_set_timeout(pipe_hnd, orig_timeout);
5533
5534         if (!NT_STATUS_IS_OK(result)) {
5535                 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
5536                         acct_name, nt_errstr(result));
5537                 goto done;
5538         }
5539
5540         {
5541                 struct samr_CryptPassword crypt_pwd;
5542
5543                 ZERO_STRUCT(info.info23);
5544
5545                 init_samr_CryptPassword(argv[1],
5546                                         &cli->user_session_key,
5547                                         &crypt_pwd);
5548
5549                 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
5550                                                   SAMR_FIELD_NT_PASSWORD_PRESENT;
5551                 info.info23.info.acct_flags = ACB_DOMTRUST;
5552                 info.info23.password = crypt_pwd;
5553
5554                 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5555                                                   &user_pol,
5556                                                   23,
5557                                                   &info);
5558
5559                 if (!NT_STATUS_IS_OK(result)) {
5560                         DEBUG(0,("Could not set trust account password: %s\n",
5561                                  nt_errstr(result)));
5562                         goto done;
5563                 }
5564         }
5565
5566  done:
5567         SAFE_FREE(acct_name);
5568         return result;
5569 }
5570
5571 /**
5572  * Create interdomain trust account for a remote domain.
5573  *
5574  * @param argc Standard argc.
5575  * @param argv Standard argv without initial components.
5576  *
5577  * @return Integer status (0 means success).
5578  **/
5579
5580 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5581 {
5582         if (argc > 0 && !c->display_usage) {
5583                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5584                                        rpc_trustdom_add_internals, argc, argv);
5585         } else {
5586                 d_printf("%s\n%s",
5587                          _("Usage:"),
5588                          _("net rpc trustdom add <domain_name> <trust "
5589                            "password>\n"));
5590                 return -1;
5591         }
5592 }
5593
5594
5595 /**
5596  * Remove interdomain trust account from the RPC server.
5597  * All parameters (except for argc and argv) are passed by run_rpc_command
5598  * function.
5599  *
5600  * @param c     A net_context structure.
5601  * @param domain_sid The domain sid acquired from the server.
5602  * @param cli A cli_state connected to the server.
5603  * @param mem_ctx Talloc context, destroyed on completion of the function.
5604  * @param argc  Standard main() style argc.
5605  * @param argv  Standard main() style argv. Initial components are already
5606  *              stripped.
5607  *
5608  * @return normal NTSTATUS return code.
5609  */
5610
5611 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
5612                                         const struct dom_sid *domain_sid,
5613                                         const char *domain_name,
5614                                         struct cli_state *cli,
5615                                         struct rpc_pipe_client *pipe_hnd,
5616                                         TALLOC_CTX *mem_ctx,
5617                                         int argc,
5618                                         const char **argv)
5619 {
5620         struct policy_handle connect_pol, domain_pol, user_pol;
5621         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5622         char *acct_name;
5623         struct dom_sid trust_acct_sid;
5624         struct samr_Ids user_rids, name_types;
5625         struct lsa_String lsa_acct_name;
5626
5627         if (argc != 1) {
5628                 d_printf("%s\n%s",
5629                          _("Usage:"),
5630                          _(" net rpc trustdom del <domain_name>\n"));
5631                 return NT_STATUS_INVALID_PARAMETER;
5632         }
5633
5634         /*
5635          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5636          */
5637         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5638
5639         if (acct_name == NULL)
5640                 return NT_STATUS_NO_MEMORY;
5641
5642         strupper_m(acct_name);
5643
5644         /* Get samr policy handle */
5645         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5646                                       pipe_hnd->desthost,
5647                                       MAXIMUM_ALLOWED_ACCESS,
5648                                       &connect_pol);
5649         if (!NT_STATUS_IS_OK(result)) {
5650                 goto done;
5651         }
5652
5653         /* Get domain policy handle */
5654         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5655                                         &connect_pol,
5656                                         MAXIMUM_ALLOWED_ACCESS,
5657                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5658                                         &domain_pol);
5659         if (!NT_STATUS_IS_OK(result)) {
5660                 goto done;
5661         }
5662
5663         init_lsa_String(&lsa_acct_name, acct_name);
5664
5665         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5666                                          &domain_pol,
5667                                          1,
5668                                          &lsa_acct_name,
5669                                          &user_rids,
5670                                          &name_types);
5671
5672         if (!NT_STATUS_IS_OK(result)) {
5673                 d_printf(_("net rpc trustdom del: LookupNames on user %s "
5674                            "failed %s\n"),
5675                         acct_name, nt_errstr(result) );
5676                 goto done;
5677         }
5678
5679         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5680                                       &domain_pol,
5681                                       MAXIMUM_ALLOWED_ACCESS,
5682                                       user_rids.ids[0],
5683                                       &user_pol);
5684
5685         if (!NT_STATUS_IS_OK(result)) {
5686                 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
5687                            "%s\n"),
5688                         acct_name, nt_errstr(result) );
5689                 goto done;
5690         }
5691
5692         /* append the rid to the domain sid */
5693         if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
5694                 goto done;
5695         }
5696
5697         /* remove the sid */
5698
5699         result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5700                                                            &user_pol,
5701                                                            &trust_acct_sid);
5702         if (!NT_STATUS_IS_OK(result)) {
5703                 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
5704                            " on user %s failed %s\n"),
5705                         acct_name, nt_errstr(result) );
5706                 goto done;
5707         }
5708
5709         /* Delete user */
5710
5711         result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5712                                         &user_pol);
5713
5714         if (!NT_STATUS_IS_OK(result)) {
5715                 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
5716                            "%s\n"),
5717                         acct_name, nt_errstr(result) );
5718                 goto done;
5719         }
5720
5721         if (!NT_STATUS_IS_OK(result)) {
5722                 d_printf(_("Could not set trust account password: %s\n"),
5723                    nt_errstr(result));
5724                 goto done;
5725         }
5726
5727  done:
5728         return result;
5729 }
5730
5731 /**
5732  * Delete interdomain trust account for a remote domain.
5733  *
5734  * @param argc Standard argc.
5735  * @param argv Standard argv without initial components.
5736  *
5737  * @return Integer status (0 means success).
5738  **/
5739
5740 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
5741 {
5742         if (argc > 0 && !c->display_usage) {
5743                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5744                                        rpc_trustdom_del_internals, argc, argv);
5745         } else {
5746                 d_printf("%s\n%s",
5747                          _("Usage:"),
5748                          _("net rpc trustdom del <domain>\n"));
5749                 return -1;
5750         }
5751 }
5752
5753 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
5754                                      struct cli_state *cli,
5755                                      TALLOC_CTX *mem_ctx,
5756                                      const char *domain_name)
5757 {
5758         char *dc_name = NULL;
5759         const char *buffer = NULL;
5760         struct rpc_pipe_client *netr;
5761         NTSTATUS status;
5762         WERROR result;
5763         struct dcerpc_binding_handle *b;
5764
5765         /* Use NetServerEnum2 */
5766
5767         if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
5768                 SAFE_FREE(dc_name);
5769                 return NT_STATUS_OK;
5770         }
5771
5772         DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
5773                  for domain %s\n", domain_name));
5774
5775         /* Try netr_GetDcName */
5776
5777         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
5778                                           &netr);
5779         if (!NT_STATUS_IS_OK(status)) {
5780                 return status;
5781         }
5782
5783         b = netr->binding_handle;
5784
5785         status = dcerpc_netr_GetDcName(b, mem_ctx,
5786                                        cli->desthost,
5787                                        domain_name,
5788                                        &buffer,
5789                                        &result);
5790         TALLOC_FREE(netr);
5791
5792         if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
5793                 return status;
5794         }
5795
5796         DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
5797                  for domain %s\n", domain_name));
5798
5799         if (!NT_STATUS_IS_OK(status)) {
5800                 return status;
5801         }
5802
5803         return werror_to_ntstatus(result);
5804 }
5805
5806 /**
5807  * Establish trust relationship to a trusting domain.
5808  * Interdomain account must already be created on remote PDC.
5809  *
5810  * @param c    A net_context structure.
5811  * @param argc Standard argc.
5812  * @param argv Standard argv without initial components.
5813  *
5814  * @return Integer status (0 means success).
5815  **/
5816
5817 static int rpc_trustdom_establish(struct net_context *c, int argc,
5818                                   const char **argv)
5819 {
5820         struct cli_state *cli = NULL;
5821         struct sockaddr_storage server_ss;
5822         struct rpc_pipe_client *pipe_hnd = NULL;
5823         struct policy_handle connect_hnd;
5824         TALLOC_CTX *mem_ctx;
5825         NTSTATUS nt_status;
5826         struct dom_sid *domain_sid;
5827
5828         char* domain_name;
5829         char* acct_name;
5830         fstring pdc_name;
5831         union lsa_PolicyInformation *info = NULL;
5832
5833         /*
5834          * Connect to \\server\ipc$ as 'our domain' account with password
5835          */
5836
5837         if (argc != 1 || c->display_usage) {
5838                 d_printf("%s\n%s",
5839                          _("Usage:"),
5840                          _("net rpc trustdom establish <domain_name>\n"));
5841                 return -1;
5842         }
5843
5844         domain_name = smb_xstrdup(argv[0]);
5845         strupper_m(domain_name);
5846
5847         /* account name used at first is our domain's name with '$' */
5848         if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
5849                 return -1;
5850         }
5851         strupper_m(acct_name);
5852
5853         /*
5854          * opt_workgroup will be used by connection functions further,
5855          * hence it should be set to remote domain name instead of ours
5856          */
5857         if (c->opt_workgroup) {
5858                 c->opt_workgroup = smb_xstrdup(domain_name);
5859         };
5860
5861         c->opt_user_name = acct_name;
5862
5863         /* find the domain controller */
5864         if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5865                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5866                 return -1;
5867         }
5868
5869         /* connect to ipc$ as username/password */
5870         nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
5871         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5872
5873                 /* Is it trusting domain account for sure ? */
5874                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5875                         nt_errstr(nt_status)));
5876                 return -1;
5877         }
5878
5879         /* store who we connected to */
5880
5881         saf_store( domain_name, pdc_name );
5882
5883         /*
5884          * Connect to \\server\ipc$ again (this time anonymously)
5885          */
5886
5887         nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
5888                                              (char*)pdc_name);
5889
5890         if (NT_STATUS_IS_ERR(nt_status)) {
5891                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5892                         domain_name, nt_errstr(nt_status)));
5893                 return -1;
5894         }
5895
5896         if (!(mem_ctx = talloc_init("establishing trust relationship to "
5897                                     "domain %s", domain_name))) {
5898                 DEBUG(0, ("talloc_init() failed\n"));
5899                 cli_shutdown(cli);
5900                 return -1;
5901         }
5902
5903         /* Make sure we're talking to a proper server */
5904
5905         nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
5906         if (!NT_STATUS_IS_OK(nt_status)) {
5907                 cli_shutdown(cli);
5908                 talloc_destroy(mem_ctx);
5909                 return -1;
5910         }
5911
5912         /*
5913          * Call LsaOpenPolicy and LsaQueryInfo
5914          */
5915
5916         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5917                                              &pipe_hnd);
5918         if (!NT_STATUS_IS_OK(nt_status)) {
5919                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5920                 cli_shutdown(cli);
5921                 talloc_destroy(mem_ctx);
5922                 return -1;
5923         }
5924
5925         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
5926                                          &connect_hnd);
5927         if (NT_STATUS_IS_ERR(nt_status)) {
5928                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5929                         nt_errstr(nt_status)));
5930                 cli_shutdown(cli);
5931                 talloc_destroy(mem_ctx);
5932                 return -1;
5933         }
5934
5935         /* Querying info level 5 */
5936
5937         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5938                                                &connect_hnd,
5939                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5940                                                &info);
5941         if (NT_STATUS_IS_ERR(nt_status)) {
5942                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5943                         nt_errstr(nt_status)));
5944                 cli_shutdown(cli);
5945                 talloc_destroy(mem_ctx);
5946                 return -1;
5947         }
5948
5949         domain_sid = info->account_domain.sid;
5950
5951         /* There should be actually query info level 3 (following nt serv behaviour),
5952            but I still don't know if it's _really_ necessary */
5953
5954         /*
5955          * Store the password in secrets db
5956          */
5957
5958         if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
5959                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5960                 cli_shutdown(cli);
5961                 talloc_destroy(mem_ctx);
5962                 return -1;
5963         }
5964
5965         /*
5966          * Close the pipes and clean up
5967          */
5968
5969         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5970         if (NT_STATUS_IS_ERR(nt_status)) {
5971                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5972                         nt_errstr(nt_status)));
5973                 cli_shutdown(cli);
5974                 talloc_destroy(mem_ctx);
5975                 return -1;
5976         }
5977
5978         cli_shutdown(cli);
5979
5980         talloc_destroy(mem_ctx);
5981
5982         d_printf(_("Trust to domain %s established\n"), domain_name);
5983         return 0;
5984 }
5985
5986 /**
5987  * Revoke trust relationship to the remote domain.
5988  *
5989  * @param c    A net_context structure.
5990  * @param argc Standard argc.
5991  * @param argv Standard argv without initial components.
5992  *
5993  * @return Integer status (0 means success).
5994  **/
5995
5996 static int rpc_trustdom_revoke(struct net_context *c, int argc,
5997                                const char **argv)
5998 {
5999         char* domain_name;
6000         int rc = -1;
6001
6002         if (argc < 1 || c->display_usage) {
6003                 d_printf("%s\n%s",
6004                          _("Usage:"),
6005                          _("net rpc trustdom revoke <domain_name>\n"
6006                            "  Revoke trust relationship\n"
6007                            "    domain_name\tName of domain to revoke trust\n"));
6008                 return -1;
6009         }
6010
6011         /* generate upper cased domain name */
6012         domain_name = smb_xstrdup(argv[0]);
6013         strupper_m(domain_name);
6014
6015         /* delete password of the trust */
6016         if (!pdb_del_trusteddom_pw(domain_name)) {
6017                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6018                           domain_name));
6019                 goto done;
6020         };
6021
6022         rc = 0;
6023 done:
6024         SAFE_FREE(domain_name);
6025         return rc;
6026 }
6027
6028 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6029                                         const struct dom_sid *domain_sid,
6030                                         const char *domain_name,
6031                                         struct cli_state *cli,
6032                                         struct rpc_pipe_client *pipe_hnd,
6033                                         TALLOC_CTX *mem_ctx,
6034                                         int argc,
6035                                         const char **argv)
6036 {
6037         fstring str_sid;
6038         if (!sid_to_fstring(str_sid, domain_sid)) {
6039                 return NT_STATUS_UNSUCCESSFUL;
6040         }
6041         d_printf("%s\n", str_sid);
6042         return NT_STATUS_OK;
6043 }
6044
6045 static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
6046 {
6047         fstring ascii_sid;
6048
6049         /* convert sid into ascii string */
6050         sid_to_fstring(ascii_sid, dom_sid);
6051
6052         d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
6053 }
6054
6055 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6056                                       TALLOC_CTX *mem_ctx,
6057                                       struct policy_handle *pol,
6058                                       struct dom_sid dom_sid,
6059                                       const char *trusted_dom_name)
6060 {
6061         NTSTATUS nt_status;
6062         union lsa_TrustedDomainInfo *info = NULL;
6063         char *cleartextpwd = NULL;
6064         uint8_t session_key[16];
6065         DATA_BLOB session_key_blob;
6066         DATA_BLOB data = data_blob_null;
6067
6068         nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
6069                                                            pol,
6070                                                            &dom_sid,
6071                                                            LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6072                                                            &info);
6073         if (NT_STATUS_IS_ERR(nt_status)) {
6074                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6075                 nt_errstr(nt_status)));
6076                 goto done;
6077         }
6078
6079         data = data_blob(info->password.password->data,
6080                          info->password.password->length);
6081
6082         if (!rpccli_get_pwd_hash(pipe_hnd, session_key)) {
6083                 DEBUG(0, ("Could not retrieve password hash\n"));
6084                 goto done;
6085         }
6086
6087         session_key_blob = data_blob_const(session_key, sizeof(session_key));
6088         cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key_blob);
6089
6090         if (cleartextpwd == NULL) {
6091                 DEBUG(0,("retrieved NULL password\n"));
6092                 nt_status = NT_STATUS_UNSUCCESSFUL;
6093                 goto done;
6094         }
6095
6096         if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6097                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6098                 nt_status = NT_STATUS_UNSUCCESSFUL;
6099                 goto done;
6100         }
6101
6102 #ifdef DEBUG_PASSWORD
6103         DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
6104                    "password: [%s]\n", trusted_dom_name,
6105                    sid_string_dbg(&dom_sid), cleartextpwd));
6106 #endif
6107
6108 done:
6109         SAFE_FREE(cleartextpwd);
6110         data_blob_free(&data);
6111
6112         return nt_status;
6113 }
6114
6115 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6116                                 const char **argv)
6117 {
6118         /* common variables */
6119         TALLOC_CTX* mem_ctx;
6120         struct cli_state *cli = NULL;
6121         struct rpc_pipe_client *pipe_hnd = NULL;
6122         NTSTATUS nt_status;
6123         const char *domain_name = NULL;
6124         struct dom_sid *queried_dom_sid;
6125         struct policy_handle connect_hnd;
6126         union lsa_PolicyInformation *info = NULL;
6127
6128         /* trusted domains listing variables */
6129         unsigned int enum_ctx = 0;
6130         int i;
6131         struct lsa_DomainList dom_list;
6132         fstring pdc_name;
6133
6134         if (c->display_usage) {
6135                 d_printf(  "%s\n"
6136                            "net rpc trustdom vampire\n"
6137                            "  %s\n",
6138                          _("Usage:"),
6139                          _("Vampire trust relationship from remote server"));
6140                 return 0;
6141         }
6142
6143         /*
6144          * Listing trusted domains (stored in secrets.tdb, if local)
6145          */
6146
6147         mem_ctx = talloc_init("trust relationships vampire");
6148
6149         /*
6150          * set domain and pdc name to local samba server (default)
6151          * or to remote one given in command line
6152          */
6153
6154         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6155                 domain_name = c->opt_workgroup;
6156                 c->opt_target_workgroup = c->opt_workgroup;
6157         } else {
6158                 fstrcpy(pdc_name, global_myname());
6159                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6160                 c->opt_target_workgroup = domain_name;
6161         };
6162
6163         /* open \PIPE\lsarpc and open policy handle */
6164         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6165         if (!NT_STATUS_IS_OK(nt_status)) {
6166                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6167                           nt_errstr(nt_status)));
6168                 talloc_destroy(mem_ctx);
6169                 return -1;
6170         };
6171
6172         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6173                                              &pipe_hnd);
6174         if (!NT_STATUS_IS_OK(nt_status)) {
6175                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6176                         nt_errstr(nt_status) ));
6177                 cli_shutdown(cli);
6178                 talloc_destroy(mem_ctx);
6179                 return -1;
6180         };
6181
6182         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6183                                         &connect_hnd);
6184         if (NT_STATUS_IS_ERR(nt_status)) {
6185                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6186                         nt_errstr(nt_status)));
6187                 cli_shutdown(cli);
6188                 talloc_destroy(mem_ctx);
6189                 return -1;
6190         };
6191
6192         /* query info level 5 to obtain sid of a domain being queried */
6193         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6194                                                &connect_hnd,
6195                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6196                                                &info);
6197
6198         if (NT_STATUS_IS_ERR(nt_status)) {
6199                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6200                         nt_errstr(nt_status)));
6201                 cli_shutdown(cli);
6202                 talloc_destroy(mem_ctx);
6203                 return -1;
6204         }
6205
6206         queried_dom_sid = info->account_domain.sid;
6207
6208         /*
6209          * Keep calling LsaEnumTrustdom over opened pipe until
6210          * the end of enumeration is reached
6211          */
6212
6213         d_printf(_("Vampire trusted domains:\n\n"));
6214
6215         do {
6216                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6217                                                     &connect_hnd,
6218                                                     &enum_ctx,
6219                                                     &dom_list,
6220                                                     (uint32_t)-1);
6221                 if (NT_STATUS_IS_ERR(nt_status)) {
6222                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6223                                 nt_errstr(nt_status)));
6224                         cli_shutdown(cli);
6225                         talloc_destroy(mem_ctx);
6226                         return -1;
6227                 };
6228
6229                 for (i = 0; i < dom_list.count; i++) {
6230
6231                         print_trusted_domain(dom_list.domains[i].sid,
6232                                              dom_list.domains[i].name.string);
6233
6234                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
6235                                                            *dom_list.domains[i].sid,
6236                                                            dom_list.domains[i].name.string);
6237                         if (!NT_STATUS_IS_OK(nt_status)) {
6238                                 cli_shutdown(cli);
6239                                 talloc_destroy(mem_ctx);
6240                                 return -1;
6241                         }
6242                 };
6243
6244                 /*
6245                  * in case of no trusted domains say something rather
6246                  * than just display blank line
6247                  */
6248                 if (!dom_list.count) d_printf(_("none\n"));
6249
6250         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6251
6252         /* close this connection before doing next one */
6253         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6254         if (NT_STATUS_IS_ERR(nt_status)) {
6255                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6256                         nt_errstr(nt_status)));
6257                 cli_shutdown(cli);
6258                 talloc_destroy(mem_ctx);
6259                 return -1;
6260         };
6261
6262         /* close lsarpc pipe and connection to IPC$ */
6263         cli_shutdown(cli);
6264
6265         talloc_destroy(mem_ctx);
6266         return 0;
6267 }
6268
6269 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6270 {
6271         /* common variables */
6272         TALLOC_CTX* mem_ctx;
6273         struct cli_state *cli = NULL, *remote_cli = NULL;
6274         struct rpc_pipe_client *pipe_hnd = NULL;
6275         NTSTATUS nt_status;
6276         const char *domain_name = NULL;
6277         struct dom_sid *queried_dom_sid;
6278         int ascii_dom_name_len;
6279         struct policy_handle connect_hnd;
6280         union lsa_PolicyInformation *info = NULL;
6281
6282         /* trusted domains listing variables */
6283         unsigned int num_domains, enum_ctx = 0;
6284         int i;
6285         struct lsa_DomainList dom_list;
6286         fstring pdc_name;
6287         bool found_domain;
6288
6289         /* trusting domains listing variables */
6290         struct policy_handle domain_hnd;
6291         struct samr_SamArray *trusts = NULL;
6292
6293         if (c->display_usage) {
6294                 d_printf(  "%s\n"
6295                            "net rpc trustdom list\n"
6296                            "    %s\n",
6297                          _("Usage:"),
6298                          _("List incoming and outgoing trust relationships"));
6299                 return 0;
6300         }
6301
6302         /*
6303          * Listing trusted domains (stored in secrets.tdb, if local)
6304          */
6305
6306         mem_ctx = talloc_init("trust relationships listing");
6307
6308         /*
6309          * set domain and pdc name to local samba server (default)
6310          * or to remote one given in command line
6311          */
6312
6313         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6314                 domain_name = c->opt_workgroup;
6315                 c->opt_target_workgroup = c->opt_workgroup;
6316         } else {
6317                 fstrcpy(pdc_name, global_myname());
6318                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6319                 c->opt_target_workgroup = domain_name;
6320         };
6321
6322         /* open \PIPE\lsarpc and open policy handle */
6323         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6324         if (!NT_STATUS_IS_OK(nt_status)) {
6325                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6326                           nt_errstr(nt_status)));
6327                 talloc_destroy(mem_ctx);
6328                 return -1;
6329         };
6330
6331         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6332                                              &pipe_hnd);
6333         if (!NT_STATUS_IS_OK(nt_status)) {
6334                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6335                         nt_errstr(nt_status) ));
6336                 cli_shutdown(cli);
6337                 talloc_destroy(mem_ctx);
6338                 return -1;
6339         };
6340
6341         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6342                                         &connect_hnd);
6343         if (NT_STATUS_IS_ERR(nt_status)) {
6344                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6345                         nt_errstr(nt_status)));
6346                 cli_shutdown(cli);
6347                 talloc_destroy(mem_ctx);
6348                 return -1;
6349         };
6350         
6351         /* query info level 5 to obtain sid of a domain being queried */
6352         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6353                                                &connect_hnd,
6354                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6355                                                &info);
6356
6357         if (NT_STATUS_IS_ERR(nt_status)) {
6358                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6359                         nt_errstr(nt_status)));
6360                 cli_shutdown(cli);
6361                 talloc_destroy(mem_ctx);
6362                 return -1;
6363         }
6364
6365         queried_dom_sid = info->account_domain.sid;
6366
6367         /*
6368          * Keep calling LsaEnumTrustdom over opened pipe until
6369          * the end of enumeration is reached
6370          */
6371
6372         d_printf(_("Trusted domains list:\n\n"));
6373
6374         found_domain = false;
6375
6376         do {
6377                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6378                                                     &connect_hnd,
6379                                                     &enum_ctx,
6380                                                     &dom_list,
6381                                                     (uint32_t)-1);
6382                 if (NT_STATUS_IS_ERR(nt_status)) {
6383                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6384                                 nt_errstr(nt_status)));
6385                         cli_shutdown(cli);
6386                         talloc_destroy(mem_ctx);
6387                         return -1;
6388                 };
6389
6390                 for (i = 0; i < dom_list.count; i++) {
6391                         print_trusted_domain(dom_list.domains[i].sid,
6392                                              dom_list.domains[i].name.string);
6393                         found_domain = true;
6394                 };
6395
6396
6397         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6398
6399         /*
6400          * in case of no trusted domains say something rather
6401          * than just display blank line
6402          */
6403         if (!found_domain) {
6404                 d_printf(_("none\n"));
6405         }
6406
6407         /* close this connection before doing next one */
6408         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6409         if (NT_STATUS_IS_ERR(nt_status)) {
6410                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6411                         nt_errstr(nt_status)));
6412                 cli_shutdown(cli);
6413                 talloc_destroy(mem_ctx);
6414                 return -1;
6415         };
6416         
6417         TALLOC_FREE(pipe_hnd);
6418
6419         /*
6420          * Listing trusting domains (stored in passdb backend, if local)
6421          */
6422         
6423         d_printf(_("\nTrusting domains list:\n\n"));
6424
6425         /*
6426          * Open \PIPE\samr and get needed policy handles
6427          */
6428         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6429                                              &pipe_hnd);
6430         if (!NT_STATUS_IS_OK(nt_status)) {
6431                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6432                 cli_shutdown(cli);
6433                 talloc_destroy(mem_ctx);
6434                 return -1;
6435         };
6436
6437         /* SamrConnect2 */
6438         nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6439                                          pipe_hnd->desthost,
6440                                          SAMR_ACCESS_LOOKUP_DOMAIN,
6441                                          &connect_hnd);
6442         if (!NT_STATUS_IS_OK(nt_status)) {
6443                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6444                         nt_errstr(nt_status)));
6445                 cli_shutdown(cli);
6446                 talloc_destroy(mem_ctx);
6447                 return -1;
6448         };
6449
6450         /* SamrOpenDomain - we have to open domain policy handle in order to be
6451            able to enumerate accounts*/
6452         nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6453                                            &connect_hnd,
6454                                            SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6455                                            queried_dom_sid,
6456                                            &domain_hnd);
6457         if (!NT_STATUS_IS_OK(nt_status)) {
6458                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6459                         nt_errstr(nt_status)));
6460                 cli_shutdown(cli);
6461                 talloc_destroy(mem_ctx);
6462                 return -1;
6463         };
6464
6465         /*
6466          * perform actual enumeration
6467          */
6468
6469         found_domain = false;
6470
6471         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6472         do {
6473
6474                 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6475                                                         &domain_hnd,
6476                                                         &enum_ctx,
6477                                                         ACB_DOMTRUST,
6478                                                         &trusts,
6479                                                         0xffff,
6480                                                         &num_domains);
6481                 if (NT_STATUS_IS_ERR(nt_status)) {
6482                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6483                                 nt_errstr(nt_status)));
6484                         cli_shutdown(cli);
6485                         talloc_destroy(mem_ctx);
6486                         return -1;
6487                 };
6488
6489                 for (i = 0; i < num_domains; i++) {
6490
6491                         char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6492
6493                         found_domain = true;
6494
6495                         /*
6496                          * get each single domain's sid (do we _really_ need this ?):
6497                          *  1) connect to domain's pdc
6498                          *  2) query the pdc for domain's sid
6499                          */
6500
6501                         /* get rid of '$' tail */
6502                         ascii_dom_name_len = strlen(str);
6503                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6504                                 str[ascii_dom_name_len - 1] = '\0';
6505
6506                         /* set opt_* variables to remote domain */
6507                         strupper_m(str);
6508                         c->opt_workgroup = talloc_strdup(mem_ctx, str);
6509                         c->opt_target_workgroup = c->opt_workgroup;
6510
6511                         d_printf("%-20s", str);
6512
6513                         /* connect to remote domain controller */
6514                         nt_status = net_make_ipc_connection(c,
6515                                         NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6516                                         &remote_cli);
6517                         if (NT_STATUS_IS_OK(nt_status)) {
6518                                 /* query for domain's sid */
6519                                 if (run_rpc_command(
6520                                             c, remote_cli,
6521                                             &ndr_table_lsarpc.syntax_id, 0,
6522                                             rpc_query_domain_sid, argc,
6523                                             argv))
6524                                         d_printf(_("strange - couldn't get domain's sid\n"));
6525
6526                                 cli_shutdown(remote_cli);
6527
6528                         } else {
6529                                 d_fprintf(stderr, _("domain controller is not "
6530                                           "responding: %s\n"),
6531                                           nt_errstr(nt_status));
6532                                 d_printf(_("couldn't get domain's sid\n"));
6533                         }
6534                 }
6535
6536         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6537
6538         if (!found_domain) {
6539                 d_printf("none\n");
6540         }
6541
6542         /* close opened samr and domain policy handles */
6543         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6544         if (!NT_STATUS_IS_OK(nt_status)) {
6545                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6546         };
6547
6548         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6549         if (!NT_STATUS_IS_OK(nt_status)) {
6550                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6551         };
6552
6553         /* close samr pipe and connection to IPC$ */
6554         cli_shutdown(cli);
6555
6556         talloc_destroy(mem_ctx);
6557         return 0;
6558 }
6559
6560 /**
6561  * Entrypoint for 'net rpc trustdom' code.
6562  *
6563  * @param argc Standard argc.
6564  * @param argv Standard argv without initial components.
6565  *
6566  * @return Integer status (0 means success).
6567  */
6568
6569 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
6570 {
6571         struct functable func[] = {
6572                 {
6573                         "add",
6574                         rpc_trustdom_add,
6575                         NET_TRANSPORT_RPC,
6576                         N_("Add trusting domain's account"),
6577                         N_("net rpc trustdom add\n"
6578                            "    Add trusting domain's account")
6579                 },
6580                 {
6581                         "del",
6582                         rpc_trustdom_del,
6583                         NET_TRANSPORT_RPC,
6584                         N_("Remove trusting domain's account"),
6585                         N_("net rpc trustdom del\n"
6586                            "    Remove trusting domain's account")
6587                 },
6588                 {
6589                         "establish",
6590                         rpc_trustdom_establish,
6591                         NET_TRANSPORT_RPC,
6592                         N_("Establish outgoing trust relationship"),
6593                         N_("net rpc trustdom establish\n"
6594                            "    Establish outgoing trust relationship")
6595                 },
6596                 {
6597                         "revoke",
6598                         rpc_trustdom_revoke,
6599                         NET_TRANSPORT_RPC,
6600                         N_("Revoke outgoing trust relationship"),
6601                         N_("net rpc trustdom revoke\n"
6602                            "    Revoke outgoing trust relationship")
6603                 },
6604                 {
6605                         "list",
6606                         rpc_trustdom_list,
6607                         NET_TRANSPORT_RPC,
6608                         N_("List in- and outgoing domain trusts"),
6609                         N_("net rpc trustdom list\n"
6610                            "    List in- and outgoing domain trusts")
6611                 },
6612                 {
6613                         "vampire",
6614                         rpc_trustdom_vampire,
6615                         NET_TRANSPORT_RPC,
6616                         N_("Vampire trusts from remote server"),
6617                         N_("net rpc trustdom vampire\n"
6618                            "    Vampire trusts from remote server")
6619                 },
6620                 {NULL, NULL, 0, NULL, NULL}
6621         };
6622
6623         return net_run_function(c, argc, argv, "net rpc trustdom", func);
6624 }
6625
6626 /**
6627  * Check if a server will take rpc commands
6628  * @param flags Type of server to connect to (PDC, DMB, localhost)
6629  *              if the host is not explicitly specified
6630  * @return  bool (true means rpc supported)
6631  */
6632 bool net_rpc_check(struct net_context *c, unsigned flags)
6633 {
6634         struct cli_state *cli;
6635         bool ret = false;
6636         struct sockaddr_storage server_ss;
6637         char *server_name = NULL;
6638         NTSTATUS status;
6639
6640         /* flags (i.e. server type) may depend on command */
6641         if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
6642                 return false;
6643
6644         if ((cli = cli_initialise()) == NULL) {
6645                 return false;
6646         }
6647
6648         status = cli_connect(cli, server_name, &server_ss);
6649         if (!NT_STATUS_IS_OK(status))
6650                 goto done;
6651         if (!attempt_netbios_session_request(&cli, global_myname(),
6652                                              server_name, &server_ss))
6653                 goto done;
6654         status = cli_negprot(cli);
6655         if (!NT_STATUS_IS_OK(status))
6656                 goto done;
6657         if (cli->protocol < PROTOCOL_NT1)
6658                 goto done;
6659
6660         ret = true;
6661  done:
6662         cli_shutdown(cli);
6663         return ret;
6664 }
6665
6666 /* dump sam database via samsync rpc calls */
6667 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
6668         if (c->display_usage) {
6669                 d_printf(  "%s\n"
6670                            "net rpc samdump\n"
6671                            "    %s\n",
6672                          _("Usage:"),
6673                          _("Dump remote SAM database"));
6674                 return 0;
6675         }
6676
6677         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6678                                NET_FLAGS_ANONYMOUS,
6679                                rpc_samdump_internals, argc, argv);
6680 }
6681
6682 /* syncronise sam database via samsync rpc calls */
6683 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
6684 {
6685         struct functable func[] = {
6686                 {
6687                         "ldif",
6688                         rpc_vampire_ldif,
6689                         NET_TRANSPORT_RPC,
6690                         N_("Dump remote SAM database to ldif"),
6691                         N_("net rpc vampire ldif\n"
6692                            "    Dump remote SAM database to LDIF file or "
6693                            "stdout")
6694                 },
6695                 {
6696                         "keytab",
6697                         rpc_vampire_keytab,
6698                         NET_TRANSPORT_RPC,
6699                         N_("Dump remote SAM database to Kerberos Keytab"),
6700                         N_("net rpc vampire keytab\n"
6701                            "    Dump remote SAM database to Kerberos keytab "
6702                            "file")
6703                 },
6704                 {
6705                         "passdb",
6706                         rpc_vampire_passdb,
6707                         NET_TRANSPORT_RPC,
6708                         N_("Dump remote SAM database to passdb"),
6709                         N_("net rpc vampire passdb\n"
6710                            "    Dump remote SAM database to passdb")
6711                 },
6712
6713                 {NULL, NULL, 0, NULL, NULL}
6714         };
6715
6716         if (argc == 0) {
6717                 if (c->display_usage) {
6718                         d_printf(  "%s\n"
6719                                    "net rpc vampire\n"
6720                                    "    %s\n",
6721                                  _("Usage:"),
6722                                  _("Vampire remote SAM database"));
6723                         return 0;
6724                 }
6725
6726                 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6727                                        NET_FLAGS_ANONYMOUS,
6728                                        rpc_vampire_internals,
6729                                        argc, argv);
6730         }
6731
6732         return net_run_function(c, argc, argv, "net rpc vampire", func);
6733 }
6734
6735 /**
6736  * Migrate everything from a print server.
6737  *
6738  * @param c     A net_context structure.
6739  * @param argc  Standard main() style argc.
6740  * @param argv  Standard main() style argv. Initial components are already
6741  *              stripped.
6742  *
6743  * @return A shell status integer (0 for success).
6744  *
6745  * The order is important !
6746  * To successfully add drivers the print queues have to exist !
6747  * Applying ACLs should be the last step, because you're easily locked out.
6748  *
6749  **/
6750 static int rpc_printer_migrate_all(struct net_context *c, int argc,
6751                                    const char **argv)
6752 {
6753         int ret;
6754
6755         if (c->display_usage) {
6756                 d_printf(  "%s\n"
6757                            "net rpc printer migrate all\n"
6758                            "    %s\n",
6759                          _("Usage:"),
6760                          _("Migrate everything from a print server"));
6761                 return 0;
6762         }
6763
6764         if (!c->opt_host) {
6765                 d_printf(_("no server to migrate\n"));
6766                 return -1;
6767         }
6768
6769         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6770                               rpc_printer_migrate_printers_internals, argc,
6771                               argv);
6772         if (ret)
6773                 return ret;
6774
6775         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6776                               rpc_printer_migrate_drivers_internals, argc,
6777                               argv);
6778         if (ret)
6779                 return ret;
6780
6781         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6782                               rpc_printer_migrate_forms_internals, argc, argv);
6783         if (ret)
6784                 return ret;
6785
6786         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6787                               rpc_printer_migrate_settings_internals, argc,
6788                               argv);
6789         if (ret)
6790                 return ret;
6791
6792         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6793                                rpc_printer_migrate_security_internals, argc,
6794                                argv);
6795
6796 }
6797
6798 /**
6799  * Migrate print drivers from a print server.
6800  *
6801  * @param c     A net_context structure.
6802  * @param argc  Standard main() style argc.
6803  * @param argv  Standard main() style argv. Initial components are already
6804  *              stripped.
6805  *
6806  * @return A shell status integer (0 for success).
6807  **/
6808 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
6809                                        const char **argv)
6810 {
6811         if (c->display_usage) {
6812                 d_printf(  "%s\n"
6813                            "net rpc printer migrate drivers\n"
6814                            "     %s\n",
6815                          _("Usage:"),
6816                          _("Migrate print-drivers from a print-server"));
6817                 return 0;
6818         }
6819
6820         if (!c->opt_host) {
6821                 d_printf(_("no server to migrate\n"));
6822                 return -1;
6823         }
6824
6825         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6826                                rpc_printer_migrate_drivers_internals,
6827                                argc, argv);
6828 }
6829
6830 /**
6831  * Migrate print-forms from a print-server.
6832  *
6833  * @param c     A net_context structure.
6834  * @param argc  Standard main() style argc.
6835  * @param argv  Standard main() style argv. Initial components are already
6836  *              stripped.
6837  *
6838  * @return A shell status integer (0 for success).
6839  **/
6840 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
6841                                      const char **argv)
6842 {
6843         if (c->display_usage) {
6844                 d_printf(  "%s\n"
6845                            "net rpc printer migrate forms\n"
6846                            "    %s\n",
6847                          _("Usage:"),
6848                          _("Migrate print-forms from a print-server"));
6849                 return 0;
6850         }
6851
6852         if (!c->opt_host) {
6853                 d_printf(_("no server to migrate\n"));
6854                 return -1;
6855         }
6856
6857         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6858                                rpc_printer_migrate_forms_internals,
6859                                argc, argv);
6860 }
6861
6862 /**
6863  * Migrate printers from a print-server.
6864  *
6865  * @param c     A net_context structure.
6866  * @param argc  Standard main() style argc.
6867  * @param argv  Standard main() style argv. Initial components are already
6868  *              stripped.
6869  *
6870  * @return A shell status integer (0 for success).
6871  **/
6872 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
6873                                         const char **argv)
6874 {
6875         if (c->display_usage) {
6876                 d_printf(  "%s\n"
6877                            "net rpc printer migrate printers\n"
6878                            "    %s\n",
6879                          _("Usage:"),
6880                          _("Migrate printers from a print-server"));
6881                 return 0;
6882         }
6883
6884         if (!c->opt_host) {
6885                 d_printf(_("no server to migrate\n"));
6886                 return -1;
6887         }
6888
6889         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6890                                rpc_printer_migrate_printers_internals,
6891                                argc, argv);
6892 }
6893
6894 /**
6895  * Migrate printer-ACLs from a print-server
6896  *
6897  * @param c     A net_context structure.
6898  * @param argc  Standard main() style argc.
6899  * @param argv  Standard main() style argv. Initial components are already
6900  *              stripped.
6901  *
6902  * @return A shell status integer (0 for success).
6903  **/
6904 static int rpc_printer_migrate_security(struct net_context *c, int argc,
6905                                         const char **argv)
6906 {
6907         if (c->display_usage) {
6908                 d_printf(  "%s\n"
6909                            "net rpc printer migrate security\n"
6910                            "    %s\n",
6911                          _("Usage:"),
6912                          _("Migrate printer-ACLs from a print-server"));
6913                 return 0;
6914         }
6915
6916         if (!c->opt_host) {
6917                 d_printf(_("no server to migrate\n"));
6918                 return -1;
6919         }
6920
6921         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6922                                rpc_printer_migrate_security_internals,
6923                                argc, argv);
6924 }
6925
6926 /**
6927  * Migrate printer-settings from a print-server.
6928  *
6929  * @param c     A net_context structure.
6930  * @param argc  Standard main() style argc.
6931  * @param argv  Standard main() style argv. Initial components are already
6932  *              stripped.
6933  *
6934  * @return A shell status integer (0 for success).
6935  **/
6936 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
6937                                         const char **argv)
6938 {
6939         if (c->display_usage) {
6940                 d_printf(  "%s\n"
6941                            "net rpc printer migrate settings\n"
6942                             "    %s\n",
6943                           _("Usage:"),
6944                           _("Migrate printer-settings from a "
6945                             "print-server"));
6946                 return 0;
6947         }
6948
6949         if (!c->opt_host) {
6950                 d_printf(_("no server to migrate\n"));
6951                 return -1;
6952         }
6953
6954         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6955                                rpc_printer_migrate_settings_internals,
6956                                argc, argv);
6957 }
6958
6959 /**
6960  * 'net rpc printer' entrypoint.
6961  *
6962  * @param c     A net_context structure.
6963  * @param argc  Standard main() style argc.
6964  * @param argv  Standard main() style argv. Initial components are already
6965  *              stripped.
6966  **/
6967
6968 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
6969 {
6970
6971         /* ouch: when addriver and setdriver are called from within
6972            rpc_printer_migrate_drivers_internals, the printer-queue already
6973            *has* to exist */
6974
6975         struct functable func[] = {
6976                 {
6977                         "all",
6978                         rpc_printer_migrate_all,
6979                         NET_TRANSPORT_RPC,
6980                         N_("Migrate all from remote to local print server"),
6981                         N_("net rpc printer migrate all\n"
6982                            "    Migrate all from remote to local print server")
6983                 },
6984                 {
6985                         "drivers",
6986                         rpc_printer_migrate_drivers,
6987                         NET_TRANSPORT_RPC,
6988                         N_("Migrate drivers to local server"),
6989                         N_("net rpc printer migrate drivers\n"
6990                            "    Migrate drivers to local server")
6991                 },
6992                 {
6993                         "forms",
6994                         rpc_printer_migrate_forms,
6995                         NET_TRANSPORT_RPC,
6996                         N_("Migrate froms to local server"),
6997                         N_("net rpc printer migrate forms\n"
6998                            "    Migrate froms to local server")
6999                 },
7000                 {
7001                         "printers",
7002                         rpc_printer_migrate_printers,
7003                         NET_TRANSPORT_RPC,
7004                         N_("Migrate printers to local server"),
7005                         N_("net rpc printer migrate printers\n"
7006                            "    Migrate printers to local server")
7007                 },
7008                 {
7009                         "security",
7010                         rpc_printer_migrate_security,
7011                         NET_TRANSPORT_RPC,
7012                         N_("Mirgate printer ACLs to local server"),
7013                         N_("net rpc printer migrate security\n"
7014                            "    Mirgate printer ACLs to local server")
7015                 },
7016                 {
7017                         "settings",
7018                         rpc_printer_migrate_settings,
7019                         NET_TRANSPORT_RPC,
7020                         N_("Migrate printer settings to local server"),
7021                         N_("net rpc printer migrate settings\n"
7022                            "    Migrate printer settings to local server")
7023                 },
7024                 {NULL, NULL, 0, NULL, NULL}
7025         };
7026
7027         return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7028 }
7029
7030
7031 /**
7032  * List printers on a remote RPC server.
7033  *
7034  * @param c     A net_context structure.
7035  * @param argc  Standard main() style argc.
7036  * @param argv  Standard main() style argv. Initial components are already
7037  *              stripped.
7038  *
7039  * @return A shell status integer (0 for success).
7040  **/
7041 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7042 {
7043         if (c->display_usage) {
7044                 d_printf(  "%s\n"
7045                            "net rpc printer list\n"
7046                            "    %s\n",
7047                          _("Usage:"),
7048                          _("List printers on a remote RPC server"));
7049                 return 0;
7050         }
7051
7052         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7053                                rpc_printer_list_internals,
7054                                argc, argv);
7055 }
7056
7057 /**
7058  * List printer-drivers on a remote RPC server.
7059  *
7060  * @param c     A net_context structure.
7061  * @param argc  Standard main() style argc.
7062  * @param argv  Standard main() style argv. Initial components are already
7063  *              stripped.
7064  *
7065  * @return A shell status integer (0 for success).
7066  **/
7067 static int rpc_printer_driver_list(struct net_context *c, int argc,
7068                                    const char **argv)
7069 {
7070         if (c->display_usage) {
7071                 d_printf(  "%s\n"
7072                            "net rpc printer driver\n"
7073                            "    %s\n",
7074                          _("Usage:"),
7075                          _("List printer-drivers on a remote RPC server"));
7076                 return 0;
7077         }
7078
7079         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7080                                rpc_printer_driver_list_internals,
7081                                argc, argv);
7082 }
7083
7084 /**
7085  * Publish printer in ADS via MSRPC.
7086  *
7087  * @param c     A net_context structure.
7088  * @param argc  Standard main() style argc.
7089  * @param argv  Standard main() style argv. Initial components are already
7090  *              stripped.
7091  *
7092  * @return A shell status integer (0 for success).
7093  **/
7094 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7095                                        const char **argv)
7096 {
7097         if (c->display_usage) {
7098                 d_printf(  "%s\n"
7099                            "net rpc printer publish publish\n"
7100                            "     %s\n",
7101                          _("Usage:"),
7102                          _("Publish printer in ADS via MSRPC"));
7103                 return 0;
7104         }
7105
7106         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7107                                rpc_printer_publish_publish_internals,
7108                                argc, argv);
7109 }
7110
7111 /**
7112  * Update printer in ADS via MSRPC.
7113  *
7114  * @param c     A net_context structure.
7115  * @param argc  Standard main() style argc.
7116  * @param argv  Standard main() style argv. Initial components are already
7117  *              stripped.
7118  *
7119  * @return A shell status integer (0 for success).
7120  **/
7121 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7122 {
7123         if (c->display_usage) {
7124                 d_printf(  "%s\n"
7125                            "net rpc printer publish update\n"
7126                            "    %s\n",
7127                          _("Usage:"),
7128                          _("Update printer in ADS via MSRPC"));
7129                 return 0;
7130         }
7131
7132         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7133                                rpc_printer_publish_update_internals,
7134                                argc, argv);
7135 }
7136
7137 /**
7138  * UnPublish printer in ADS via MSRPC.
7139  *
7140  * @param c     A net_context structure.
7141  * @param argc  Standard main() style argc.
7142  * @param argv  Standard main() style argv. Initial components are already
7143  *              stripped.
7144  *
7145  * @return A shell status integer (0 for success).
7146  **/
7147 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7148                                          const char **argv)
7149 {
7150         if (c->display_usage) {
7151                 d_printf(  "%s\n"
7152                            "net rpc printer publish unpublish\n"
7153                            "    %s\n",
7154                          _("Usage:\n"),
7155                          _("UnPublish printer in ADS via MSRPC"));
7156                 return 0;
7157         }
7158
7159         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7160                                rpc_printer_publish_unpublish_internals,
7161                                argc, argv);
7162 }
7163
7164 /**
7165  * List published printers via MSRPC.
7166  *
7167  * @param c     A net_context structure.
7168  * @param argc  Standard main() style argc.
7169  * @param argv  Standard main() style argv. Initial components are already
7170  *              stripped.
7171  *
7172  * @return A shell status integer (0 for success).
7173  **/
7174 static int rpc_printer_publish_list(struct net_context *c, int argc,
7175                                     const char **argv)
7176 {
7177         if (c->display_usage) {
7178                 d_printf(  "%s\n"
7179                            "net rpc printer publish list\n"
7180                            "    %s\n",
7181                          _("Usage:"),
7182                          _("List published printers via MSRPC"));
7183                 return 0;
7184         }
7185
7186         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7187                                rpc_printer_publish_list_internals,
7188                                argc, argv);
7189 }
7190
7191
7192 /**
7193  * Publish printer in ADS.
7194  *
7195  * @param c     A net_context structure.
7196  * @param argc  Standard main() style argc.
7197  * @param argv  Standard main() style argv. Initial components are already
7198  *              stripped.
7199  *
7200  * @return A shell status integer (0 for success).
7201  **/
7202 static int rpc_printer_publish(struct net_context *c, int argc,
7203                                const char **argv)
7204 {
7205
7206         struct functable func[] = {
7207                 {
7208                         "publish",
7209                         rpc_printer_publish_publish,
7210                         NET_TRANSPORT_RPC,
7211                         N_("Publish printer in AD"),
7212                         N_("net rpc printer publish publish\n"
7213                            "    Publish printer in AD")
7214                 },
7215                 {
7216                         "update",
7217                         rpc_printer_publish_update,
7218                         NET_TRANSPORT_RPC,
7219                         N_("Update printer in AD"),
7220                         N_("net rpc printer publish update\n"
7221                            "    Update printer in AD")
7222                 },
7223                 {
7224                         "unpublish",
7225                         rpc_printer_publish_unpublish,
7226                         NET_TRANSPORT_RPC,
7227                         N_("Unpublish printer"),
7228                         N_("net rpc printer publish unpublish\n"
7229                            "    Unpublish printer")
7230                 },
7231                 {
7232                         "list",
7233                         rpc_printer_publish_list,
7234                         NET_TRANSPORT_RPC,
7235                         N_("List published printers"),
7236                         N_("net rpc printer publish list\n"
7237                            "    List published printers")
7238                 },
7239                 {NULL, NULL, 0, NULL, NULL}
7240         };
7241
7242         if (argc == 0) {
7243                 if (c->display_usage) {
7244                         d_printf(_("Usage:\n"));
7245                         d_printf(_("net rpc printer publish\n"
7246                                    "    List published printers\n"
7247                                    "    Alias of net rpc printer publish "
7248                                    "list\n"));
7249                         net_display_usage_from_functable(func);
7250                         return 0;
7251                 }
7252                 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7253                                rpc_printer_publish_list_internals,
7254                                argc, argv);
7255         }
7256
7257         return net_run_function(c, argc, argv, "net rpc printer publish",func);
7258
7259 }
7260
7261
7262 /**
7263  * Display rpc printer help page.
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 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
7271 {
7272         d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
7273                    "\tlists all printers on print-server\n\n"));
7274         d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
7275                    "\tlists all printer-drivers on print-server\n\n"));
7276         d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
7277                    "\tpublishes printer settings in Active Directory\n"
7278                    "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
7279         d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
7280                    "\n\tmigrates printers from remote to local server\n\n"));
7281         d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
7282                    "\n\tmigrates printer-settings from remote to local server\n\n"));
7283         d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
7284                    "\n\tmigrates printer-drivers from remote to local server\n\n"));
7285         d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
7286                    "\n\tmigrates printer-forms from remote to local server\n\n"));
7287         d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
7288                    "\n\tmigrates printer-ACLs from remote to local server\n\n"));
7289         d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
7290                    "\n\tmigrates drivers, forms, queues, settings and acls from\n"
7291                    "\tremote to local print-server\n\n"));
7292         net_common_methods_usage(c, argc, argv);
7293         net_common_flags_usage(c, argc, argv);
7294         d_printf(_(
7295          "\t-v or --verbose\t\t\tgive verbose output\n"
7296          "\t      --destination\t\tmigration target server (default: localhost)\n"));
7297
7298         return -1;
7299 }
7300
7301 /**
7302  * 'net rpc printer' entrypoint.
7303  *
7304  * @param c     A net_context structure.
7305  * @param argc  Standard main() style argc.
7306  * @param argv  Standard main() style argv. Initial components are already
7307  *              stripped.
7308  **/
7309 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7310 {
7311         struct functable func[] = {
7312                 {
7313                         "list",
7314                         rpc_printer_list,
7315                         NET_TRANSPORT_RPC,
7316                         N_("List all printers on print server"),
7317                         N_("net rpc printer list\n"
7318                            "    List all printers on print server")
7319                 },
7320                 {
7321                         "migrate",
7322                         rpc_printer_migrate,
7323                         NET_TRANSPORT_RPC,
7324                         N_("Migrate printer to local server"),
7325                         N_("net rpc printer migrate\n"
7326                            "    Migrate printer to local server")
7327                 },
7328                 {
7329                         "driver",
7330                         rpc_printer_driver_list,
7331                         NET_TRANSPORT_RPC,
7332                         N_("List printer drivers"),
7333                         N_("net rpc printer driver\n"
7334                            "    List printer drivers")
7335                 },
7336                 {
7337                         "publish",
7338                         rpc_printer_publish,
7339                         NET_TRANSPORT_RPC,
7340                         N_("Publish printer in AD"),
7341                         N_("net rpc printer publish\n"
7342                            "    Publish printer in AD")
7343                 },
7344                 {NULL, NULL, 0, NULL, NULL}
7345         };
7346
7347         if (argc == 0) {
7348                 if (c->display_usage) {
7349                         d_printf(_("Usage:\n"));
7350                         d_printf(_("net rpc printer\n"
7351                                    "    List printers\n"));
7352                         net_display_usage_from_functable(func);
7353                         return 0;
7354                 }
7355                 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7356                                rpc_printer_list_internals,
7357                                argc, argv);
7358         }
7359
7360         return net_run_function(c, argc, argv, "net rpc printer", func);
7361 }
7362
7363 /**
7364  * 'net rpc' entrypoint.
7365  *
7366  * @param c     A net_context structure.
7367  * @param argc  Standard main() style argc.
7368  * @param argv  Standard main() style argv. Initial components are already
7369  *              stripped.
7370  **/
7371
7372 int net_rpc(struct net_context *c, int argc, const char **argv)
7373 {
7374         NET_API_STATUS status;
7375
7376         struct functable func[] = {
7377                 {
7378                         "audit",
7379                         net_rpc_audit,
7380                         NET_TRANSPORT_RPC,
7381                         N_("Modify global audit settings"),
7382                         N_("net rpc audit\n"
7383                            "    Modify global audit settings")
7384                 },
7385                 {
7386                         "info",
7387                         net_rpc_info,
7388                         NET_TRANSPORT_RPC,
7389                         N_("Show basic info about a domain"),
7390                         N_("net rpc info\n"
7391                            "    Show basic info about a domain")
7392                 },
7393                 {
7394                         "join",
7395                         net_rpc_join,
7396                         NET_TRANSPORT_RPC,
7397                         N_("Join a domain"),
7398                         N_("net rpc join\n"
7399                            "    Join a domain")
7400                 },
7401                 {
7402                         "oldjoin",
7403                         net_rpc_oldjoin,
7404                         NET_TRANSPORT_RPC,
7405                         N_("Join a domain created in server manager"),
7406                         N_("net rpc oldjoin\n"
7407                            "    Join a domain created in server manager")
7408                 },
7409                 {
7410                         "testjoin",
7411                         net_rpc_testjoin,
7412                         NET_TRANSPORT_RPC,
7413                         N_("Test that a join is valid"),
7414                         N_("net rpc testjoin\n"
7415                            "    Test that a join is valid")
7416                 },
7417                 {
7418                         "user",
7419                         net_rpc_user,
7420                         NET_TRANSPORT_RPC,
7421                         N_("List/modify users"),
7422                         N_("net rpc user\n"
7423                            "    List/modify users")
7424                 },
7425                 {
7426                         "password",
7427                         rpc_user_password,
7428                         NET_TRANSPORT_RPC,
7429                         N_("Change a user password"),
7430                         N_("net rpc password\n"
7431                            "    Change a user password\n"
7432                            "    Alias for net rpc user password")
7433                 },
7434                 {
7435                         "group",
7436                         net_rpc_group,
7437                         NET_TRANSPORT_RPC,
7438                         N_("List/modify groups"),
7439                         N_("net rpc group\n"
7440                            "    List/modify groups")
7441                 },
7442                 {
7443                         "share",
7444                         net_rpc_share,
7445                         NET_TRANSPORT_RPC,
7446                         N_("List/modify shares"),
7447                         N_("net rpc share\n"
7448                            "    List/modify shares")
7449                 },
7450                 {
7451                         "file",
7452                         net_rpc_file,
7453                         NET_TRANSPORT_RPC,
7454                         N_("List open files"),
7455                         N_("net rpc file\n"
7456                            "    List open files")
7457                 },
7458                 {
7459                         "printer",
7460                         net_rpc_printer,
7461                         NET_TRANSPORT_RPC,
7462                         N_("List/modify printers"),
7463                         N_("net rpc printer\n"
7464                            "    List/modify printers")
7465                 },
7466                 {
7467                         "changetrustpw",
7468                         net_rpc_changetrustpw,
7469                         NET_TRANSPORT_RPC,
7470                         N_("Change trust account password"),
7471                         N_("net rpc changetrustpw\n"
7472                            "    Change trust account password")
7473                 },
7474                 {
7475                         "trustdom",
7476                         rpc_trustdom,
7477                         NET_TRANSPORT_RPC,
7478                         N_("Modify domain trusts"),
7479                         N_("net rpc trustdom\n"
7480                            "    Modify domain trusts")
7481                 },
7482                 {
7483                         "abortshutdown",
7484                         rpc_shutdown_abort,
7485                         NET_TRANSPORT_RPC,
7486                         N_("Abort a remote shutdown"),
7487                         N_("net rpc abortshutdown\n"
7488                            "    Abort a remote shutdown")
7489                 },
7490                 {
7491                         "shutdown",
7492                         rpc_shutdown,
7493                         NET_TRANSPORT_RPC,
7494                         N_("Shutdown a remote server"),
7495                         N_("net rpc shutdown\n"
7496                            "    Shutdown a remote server")
7497                 },
7498                 {
7499                         "samdump",
7500                         rpc_samdump,
7501                         NET_TRANSPORT_RPC,
7502                         N_("Dump SAM data of remote NT PDC"),
7503                         N_("net rpc samdump\n"
7504                            "    Dump SAM data of remote NT PDC")
7505                 },
7506                 {
7507                         "vampire",
7508                         rpc_vampire,
7509                         NET_TRANSPORT_RPC,
7510                         N_("Sync a remote NT PDC's data into local passdb"),
7511                         N_("net rpc vampire\n"
7512                            "    Sync a remote NT PDC's data into local passdb")
7513                 },
7514                 {
7515                         "getsid",
7516                         net_rpc_getsid,
7517                         NET_TRANSPORT_RPC,
7518                         N_("Fetch the domain sid into local secrets.tdb"),
7519                         N_("net rpc getsid\n"
7520                            "    Fetch the domain sid into local secrets.tdb")
7521                 },
7522                 {
7523                         "rights",
7524                         net_rpc_rights,
7525                         NET_TRANSPORT_RPC,
7526                         N_("Manage privileges assigned to SID"),
7527                         N_("net rpc rights\n"
7528                            "    Manage privileges assigned to SID")
7529                 },
7530                 {
7531                         "service",
7532                         net_rpc_service,
7533                         NET_TRANSPORT_RPC,
7534                         N_("Start/stop/query remote services"),
7535                         N_("net rpc service\n"
7536                            "    Start/stop/query remote services")
7537                 },
7538                 {
7539                         "registry",
7540                         net_rpc_registry,
7541                         NET_TRANSPORT_RPC,
7542                         N_("Manage registry hives"),
7543                         N_("net rpc registry\n"
7544                            "    Manage registry hives")
7545                 },
7546                 {
7547                         "shell",
7548                         net_rpc_shell,
7549                         NET_TRANSPORT_RPC,
7550                         N_("Open interactive shell on remote server"),
7551                         N_("net rpc shell\n"
7552                            "    Open interactive shell on remote server")
7553                 },
7554                 {NULL, NULL, 0, NULL, NULL}
7555         };
7556
7557         status = libnetapi_net_init(&c->netapi_ctx);
7558         if (status != 0) {
7559                 return -1;
7560         }
7561         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
7562         libnetapi_set_password(c->netapi_ctx, c->opt_password);
7563         if (c->opt_kerberos) {
7564                 libnetapi_set_use_kerberos(c->netapi_ctx);
7565         }
7566         if (c->opt_ccache) {
7567                 libnetapi_set_use_ccache(c->netapi_ctx);
7568         }
7569
7570         return net_run_function(c, argc, argv, "net rpc", func);
7571 }