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