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