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