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