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