s3-net: prefer dcerpc_samr_X functions in rpc_trustdom_list.
[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 status, result;
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         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5763
5764         if (argc != 2) {
5765                 d_printf("%s\n%s",
5766                          _("Usage:"),
5767                          _(" net rpc trustdom add <domain_name> "
5768                            "<trust password>\n"));
5769                 return NT_STATUS_INVALID_PARAMETER;
5770         }
5771
5772         /*
5773          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5774          */
5775
5776         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5777                 return NT_STATUS_NO_MEMORY;
5778         }
5779
5780         strupper_m(acct_name);
5781
5782         init_lsa_String(&lsa_acct_name, acct_name);
5783
5784         /* Get samr policy handle */
5785         status = dcerpc_samr_Connect2(b, mem_ctx,
5786                                       pipe_hnd->desthost,
5787                                       MAXIMUM_ALLOWED_ACCESS,
5788                                       &connect_pol,
5789                                       &result);
5790         if (!NT_STATUS_IS_OK(status)) {
5791                 goto done;
5792         }
5793         if (!NT_STATUS_IS_OK(result)) {
5794                 status = result;
5795                 goto done;
5796         }
5797
5798         /* Get domain policy handle */
5799         status = dcerpc_samr_OpenDomain(b, mem_ctx,
5800                                         &connect_pol,
5801                                         MAXIMUM_ALLOWED_ACCESS,
5802                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5803                                         &domain_pol,
5804                                         &result);
5805         if (!NT_STATUS_IS_OK(status)) {
5806                 goto done;
5807         }
5808         if (!NT_STATUS_IS_OK(result)) {
5809                 status = result;
5810                 goto done;
5811         }
5812
5813         /* This call can take a long time - allow the server to time out.
5814          * 35 seconds should do it. */
5815
5816         orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5817
5818         /* Create trusting domain's account */
5819         acb_info = ACB_NORMAL;
5820         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5821                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5822                      SAMR_USER_ACCESS_SET_PASSWORD |
5823                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
5824                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
5825
5826         status = dcerpc_samr_CreateUser2(b, mem_ctx,
5827                                          &domain_pol,
5828                                          &lsa_acct_name,
5829                                          acb_info,
5830                                          acct_flags,
5831                                          &user_pol,
5832                                          &access_granted,
5833                                          &user_rid,
5834                                          &result);
5835         if (!NT_STATUS_IS_OK(status)) {
5836                 goto done;
5837         }
5838         /* And restore our original timeout. */
5839         rpccli_set_timeout(pipe_hnd, orig_timeout);
5840
5841         if (!NT_STATUS_IS_OK(result)) {
5842                 status = result;
5843                 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
5844                         acct_name, nt_errstr(result));
5845                 goto done;
5846         }
5847
5848         {
5849                 struct samr_CryptPassword crypt_pwd;
5850
5851                 ZERO_STRUCT(info.info23);
5852
5853                 init_samr_CryptPassword(argv[1],
5854                                         &cli->user_session_key,
5855                                         &crypt_pwd);
5856
5857                 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
5858                                                   SAMR_FIELD_NT_PASSWORD_PRESENT;
5859                 info.info23.info.acct_flags = ACB_DOMTRUST;
5860                 info.info23.password = crypt_pwd;
5861
5862                 status = dcerpc_samr_SetUserInfo2(b, mem_ctx,
5863                                                   &user_pol,
5864                                                   23,
5865                                                   &info,
5866                                                   &result);
5867                 if (!NT_STATUS_IS_OK(status)) {
5868                         goto done;
5869                 }
5870
5871                 if (!NT_STATUS_IS_OK(result)) {
5872                         status = result;
5873                         DEBUG(0,("Could not set trust account password: %s\n",
5874                                  nt_errstr(result)));
5875                         goto done;
5876                 }
5877         }
5878
5879  done:
5880         SAFE_FREE(acct_name);
5881         return status;
5882 }
5883
5884 /**
5885  * Create interdomain trust account for a remote domain.
5886  *
5887  * @param argc Standard argc.
5888  * @param argv Standard argv without initial components.
5889  *
5890  * @return Integer status (0 means success).
5891  **/
5892
5893 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5894 {
5895         if (argc > 0 && !c->display_usage) {
5896                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5897                                        rpc_trustdom_add_internals, argc, argv);
5898         } else {
5899                 d_printf("%s\n%s",
5900                          _("Usage:"),
5901                          _("net rpc trustdom add <domain_name> <trust "
5902                            "password>\n"));
5903                 return -1;
5904         }
5905 }
5906
5907
5908 /**
5909  * Remove interdomain trust account from the RPC server.
5910  * All parameters (except for argc and argv) are passed by run_rpc_command
5911  * function.
5912  *
5913  * @param c     A net_context structure.
5914  * @param domain_sid The domain sid acquired from the server.
5915  * @param cli A cli_state connected to the server.
5916  * @param mem_ctx Talloc context, destroyed on completion of the function.
5917  * @param argc  Standard main() style argc.
5918  * @param argv  Standard main() style argv. Initial components are already
5919  *              stripped.
5920  *
5921  * @return normal NTSTATUS return code.
5922  */
5923
5924 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
5925                                         const struct dom_sid *domain_sid,
5926                                         const char *domain_name,
5927                                         struct cli_state *cli,
5928                                         struct rpc_pipe_client *pipe_hnd,
5929                                         TALLOC_CTX *mem_ctx,
5930                                         int argc,
5931                                         const char **argv)
5932 {
5933         struct policy_handle connect_pol, domain_pol, user_pol;
5934         NTSTATUS status, result;
5935         char *acct_name;
5936         struct dom_sid trust_acct_sid;
5937         struct samr_Ids user_rids, name_types;
5938         struct lsa_String lsa_acct_name;
5939         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
5940
5941         if (argc != 1) {
5942                 d_printf("%s\n%s",
5943                          _("Usage:"),
5944                          _(" net rpc trustdom del <domain_name>\n"));
5945                 return NT_STATUS_INVALID_PARAMETER;
5946         }
5947
5948         /*
5949          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5950          */
5951         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5952
5953         if (acct_name == NULL)
5954                 return NT_STATUS_NO_MEMORY;
5955
5956         strupper_m(acct_name);
5957
5958         /* Get samr policy handle */
5959         status = dcerpc_samr_Connect2(b, mem_ctx,
5960                                       pipe_hnd->desthost,
5961                                       MAXIMUM_ALLOWED_ACCESS,
5962                                       &connect_pol,
5963                                       &result);
5964         if (!NT_STATUS_IS_OK(status)) {
5965                 goto done;
5966         }
5967         if (!NT_STATUS_IS_OK(result)) {
5968                 status = result;
5969                 goto done;
5970         }
5971
5972         /* Get domain policy handle */
5973         status = dcerpc_samr_OpenDomain(b, mem_ctx,
5974                                         &connect_pol,
5975                                         MAXIMUM_ALLOWED_ACCESS,
5976                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5977                                         &domain_pol,
5978                                         &result);
5979         if (!NT_STATUS_IS_OK(status)) {
5980                 goto done;
5981         }
5982         if (!NT_STATUS_IS_OK(result)) {
5983                 status = result;
5984                 goto done;
5985         }
5986
5987         init_lsa_String(&lsa_acct_name, acct_name);
5988
5989         status = dcerpc_samr_LookupNames(b, mem_ctx,
5990                                          &domain_pol,
5991                                          1,
5992                                          &lsa_acct_name,
5993                                          &user_rids,
5994                                          &name_types,
5995                                          &result);
5996         if (!NT_STATUS_IS_OK(status)) {
5997                 d_printf(_("net rpc trustdom del: LookupNames on user %s "
5998                            "failed %s\n"),
5999                         acct_name, nt_errstr(status));
6000                 goto done;
6001         }
6002         if (!NT_STATUS_IS_OK(result)) {
6003                 status = result;
6004                 d_printf(_("net rpc trustdom del: LookupNames on user %s "
6005                            "failed %s\n"),
6006                         acct_name, nt_errstr(result) );
6007                 goto done;
6008         }
6009
6010         status = dcerpc_samr_OpenUser(b, mem_ctx,
6011                                       &domain_pol,
6012                                       MAXIMUM_ALLOWED_ACCESS,
6013                                       user_rids.ids[0],
6014                                       &user_pol,
6015                                       &result);
6016         if (!NT_STATUS_IS_OK(status)) {
6017                 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6018                            "%s\n"),
6019                         acct_name, nt_errstr(status) );
6020                 goto done;
6021         }
6022
6023         if (!NT_STATUS_IS_OK(result)) {
6024                 status = result;
6025                 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
6026                            "%s\n"),
6027                         acct_name, nt_errstr(result) );
6028                 goto done;
6029         }
6030
6031         /* append the rid to the domain sid */
6032         if (!sid_compose(&trust_acct_sid, domain_sid, user_rids.ids[0])) {
6033                 goto done;
6034         }
6035
6036         /* remove the sid */
6037
6038         status = dcerpc_samr_RemoveMemberFromForeignDomain(b, mem_ctx,
6039                                                            &user_pol,
6040                                                            &trust_acct_sid,
6041                                                            &result);
6042         if (!NT_STATUS_IS_OK(status)) {
6043                 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6044                            " on user %s failed %s\n"),
6045                         acct_name, nt_errstr(status));
6046                 goto done;
6047         }
6048         if (!NT_STATUS_IS_OK(result)) {
6049                 status = result;
6050                 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
6051                            " on user %s failed %s\n"),
6052                         acct_name, nt_errstr(result) );
6053                 goto done;
6054         }
6055
6056
6057         /* Delete user */
6058
6059         status = dcerpc_samr_DeleteUser(b, mem_ctx,
6060                                         &user_pol,
6061                                         &result);
6062         if (!NT_STATUS_IS_OK(status)) {
6063                 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6064                            "%s\n"),
6065                         acct_name, nt_errstr(status));
6066                 goto done;
6067         }
6068
6069         if (!NT_STATUS_IS_OK(result)) {
6070                 result = status;
6071                 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
6072                            "%s\n"),
6073                         acct_name, nt_errstr(result) );
6074                 goto done;
6075         }
6076
6077         if (!NT_STATUS_IS_OK(result)) {
6078                 d_printf(_("Could not set trust account password: %s\n"),
6079                    nt_errstr(result));
6080                 goto done;
6081         }
6082
6083  done:
6084         return status;
6085 }
6086
6087 /**
6088  * Delete interdomain trust account for a remote domain.
6089  *
6090  * @param argc Standard argc.
6091  * @param argv Standard argv without initial components.
6092  *
6093  * @return Integer status (0 means success).
6094  **/
6095
6096 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
6097 {
6098         if (argc > 0 && !c->display_usage) {
6099                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
6100                                        rpc_trustdom_del_internals, argc, argv);
6101         } else {
6102                 d_printf("%s\n%s",
6103                          _("Usage:"),
6104                          _("net rpc trustdom del <domain>\n"));
6105                 return -1;
6106         }
6107 }
6108
6109 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
6110                                      struct cli_state *cli,
6111                                      TALLOC_CTX *mem_ctx,
6112                                      const char *domain_name)
6113 {
6114         char *dc_name = NULL;
6115         const char *buffer = NULL;
6116         struct rpc_pipe_client *netr;
6117         NTSTATUS status;
6118         WERROR result;
6119         struct dcerpc_binding_handle *b;
6120
6121         /* Use NetServerEnum2 */
6122
6123         if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
6124                 SAFE_FREE(dc_name);
6125                 return NT_STATUS_OK;
6126         }
6127
6128         DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
6129                  for domain %s\n", domain_name));
6130
6131         /* Try netr_GetDcName */
6132
6133         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
6134                                           &netr);
6135         if (!NT_STATUS_IS_OK(status)) {
6136                 return status;
6137         }
6138
6139         b = netr->binding_handle;
6140
6141         status = dcerpc_netr_GetDcName(b, mem_ctx,
6142                                        cli->desthost,
6143                                        domain_name,
6144                                        &buffer,
6145                                        &result);
6146         TALLOC_FREE(netr);
6147
6148         if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
6149                 return status;
6150         }
6151
6152         DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
6153                  for domain %s\n", domain_name));
6154
6155         if (!NT_STATUS_IS_OK(status)) {
6156                 return status;
6157         }
6158
6159         return werror_to_ntstatus(result);
6160 }
6161
6162 /**
6163  * Establish trust relationship to a trusting domain.
6164  * Interdomain account must already be created on remote PDC.
6165  *
6166  * @param c    A net_context structure.
6167  * @param argc Standard argc.
6168  * @param argv Standard argv without initial components.
6169  *
6170  * @return Integer status (0 means success).
6171  **/
6172
6173 static int rpc_trustdom_establish(struct net_context *c, int argc,
6174                                   const char **argv)
6175 {
6176         struct cli_state *cli = NULL;
6177         struct sockaddr_storage server_ss;
6178         struct rpc_pipe_client *pipe_hnd = NULL;
6179         struct policy_handle connect_hnd;
6180         TALLOC_CTX *mem_ctx;
6181         NTSTATUS nt_status;
6182         struct dom_sid *domain_sid;
6183
6184         char* domain_name;
6185         char* acct_name;
6186         fstring pdc_name;
6187         union lsa_PolicyInformation *info = NULL;
6188
6189         /*
6190          * Connect to \\server\ipc$ as 'our domain' account with password
6191          */
6192
6193         if (argc != 1 || c->display_usage) {
6194                 d_printf("%s\n%s",
6195                          _("Usage:"),
6196                          _("net rpc trustdom establish <domain_name>\n"));
6197                 return -1;
6198         }
6199
6200         domain_name = smb_xstrdup(argv[0]);
6201         strupper_m(domain_name);
6202
6203         /* account name used at first is our domain's name with '$' */
6204         if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
6205                 return -1;
6206         }
6207         strupper_m(acct_name);
6208
6209         /*
6210          * opt_workgroup will be used by connection functions further,
6211          * hence it should be set to remote domain name instead of ours
6212          */
6213         if (c->opt_workgroup) {
6214                 c->opt_workgroup = smb_xstrdup(domain_name);
6215         };
6216
6217         c->opt_user_name = acct_name;
6218
6219         /* find the domain controller */
6220         if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
6221                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
6222                 return -1;
6223         }
6224
6225         /* connect to ipc$ as username/password */
6226         nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
6227         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
6228
6229                 /* Is it trusting domain account for sure ? */
6230                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
6231                         nt_errstr(nt_status)));
6232                 return -1;
6233         }
6234
6235         /* store who we connected to */
6236
6237         saf_store( domain_name, pdc_name );
6238
6239         /*
6240          * Connect to \\server\ipc$ again (this time anonymously)
6241          */
6242
6243         nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
6244                                              (char*)pdc_name);
6245
6246         if (NT_STATUS_IS_ERR(nt_status)) {
6247                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
6248                         domain_name, nt_errstr(nt_status)));
6249                 return -1;
6250         }
6251
6252         if (!(mem_ctx = talloc_init("establishing trust relationship to "
6253                                     "domain %s", domain_name))) {
6254                 DEBUG(0, ("talloc_init() failed\n"));
6255                 cli_shutdown(cli);
6256                 return -1;
6257         }
6258
6259         /* Make sure we're talking to a proper server */
6260
6261         nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
6262         if (!NT_STATUS_IS_OK(nt_status)) {
6263                 cli_shutdown(cli);
6264                 talloc_destroy(mem_ctx);
6265                 return -1;
6266         }
6267
6268         /*
6269          * Call LsaOpenPolicy and LsaQueryInfo
6270          */
6271
6272         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6273                                              &pipe_hnd);
6274         if (!NT_STATUS_IS_OK(nt_status)) {
6275                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
6276                 cli_shutdown(cli);
6277                 talloc_destroy(mem_ctx);
6278                 return -1;
6279         }
6280
6281         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
6282                                          &connect_hnd);
6283         if (NT_STATUS_IS_ERR(nt_status)) {
6284                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6285                         nt_errstr(nt_status)));
6286                 cli_shutdown(cli);
6287                 talloc_destroy(mem_ctx);
6288                 return -1;
6289         }
6290
6291         /* Querying info level 5 */
6292
6293         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6294                                                &connect_hnd,
6295                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6296                                                &info);
6297         if (NT_STATUS_IS_ERR(nt_status)) {
6298                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6299                         nt_errstr(nt_status)));
6300                 cli_shutdown(cli);
6301                 talloc_destroy(mem_ctx);
6302                 return -1;
6303         }
6304
6305         domain_sid = info->account_domain.sid;
6306
6307         /* There should be actually query info level 3 (following nt serv behaviour),
6308            but I still don't know if it's _really_ necessary */
6309
6310         /*
6311          * Store the password in secrets db
6312          */
6313
6314         if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6315                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6316                 cli_shutdown(cli);
6317                 talloc_destroy(mem_ctx);
6318                 return -1;
6319         }
6320
6321         /*
6322          * Close the pipes and clean up
6323          */
6324
6325         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6326         if (NT_STATUS_IS_ERR(nt_status)) {
6327                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6328                         nt_errstr(nt_status)));
6329                 cli_shutdown(cli);
6330                 talloc_destroy(mem_ctx);
6331                 return -1;
6332         }
6333
6334         cli_shutdown(cli);
6335
6336         talloc_destroy(mem_ctx);
6337
6338         d_printf(_("Trust to domain %s established\n"), domain_name);
6339         return 0;
6340 }
6341
6342 /**
6343  * Revoke trust relationship to the remote domain.
6344  *
6345  * @param c    A net_context structure.
6346  * @param argc Standard argc.
6347  * @param argv Standard argv without initial components.
6348  *
6349  * @return Integer status (0 means success).
6350  **/
6351
6352 static int rpc_trustdom_revoke(struct net_context *c, int argc,
6353                                const char **argv)
6354 {
6355         char* domain_name;
6356         int rc = -1;
6357
6358         if (argc < 1 || c->display_usage) {
6359                 d_printf("%s\n%s",
6360                          _("Usage:"),
6361                          _("net rpc trustdom revoke <domain_name>\n"
6362                            "  Revoke trust relationship\n"
6363                            "    domain_name\tName of domain to revoke trust\n"));
6364                 return -1;
6365         }
6366
6367         /* generate upper cased domain name */
6368         domain_name = smb_xstrdup(argv[0]);
6369         strupper_m(domain_name);
6370
6371         /* delete password of the trust */
6372         if (!pdb_del_trusteddom_pw(domain_name)) {
6373                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6374                           domain_name));
6375                 goto done;
6376         };
6377
6378         rc = 0;
6379 done:
6380         SAFE_FREE(domain_name);
6381         return rc;
6382 }
6383
6384 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6385                                         const struct dom_sid *domain_sid,
6386                                         const char *domain_name,
6387                                         struct cli_state *cli,
6388                                         struct rpc_pipe_client *pipe_hnd,
6389                                         TALLOC_CTX *mem_ctx,
6390                                         int argc,
6391                                         const char **argv)
6392 {
6393         fstring str_sid;
6394         if (!sid_to_fstring(str_sid, domain_sid)) {
6395                 return NT_STATUS_UNSUCCESSFUL;
6396         }
6397         d_printf("%s\n", str_sid);
6398         return NT_STATUS_OK;
6399 }
6400
6401 static void print_trusted_domain(struct dom_sid *dom_sid, const char *trusted_dom_name)
6402 {
6403         fstring ascii_sid;
6404
6405         /* convert sid into ascii string */
6406         sid_to_fstring(ascii_sid, dom_sid);
6407
6408         d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
6409 }
6410
6411 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6412                                       TALLOC_CTX *mem_ctx,
6413                                       struct policy_handle *pol,
6414                                       struct dom_sid dom_sid,
6415                                       const char *trusted_dom_name)
6416 {
6417         NTSTATUS nt_status;
6418         union lsa_TrustedDomainInfo *info = NULL;
6419         char *cleartextpwd = NULL;
6420         uint8_t session_key[16];
6421         DATA_BLOB session_key_blob;
6422         DATA_BLOB data = data_blob_null;
6423
6424         nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
6425                                                            pol,
6426                                                            &dom_sid,
6427                                                            LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6428                                                            &info);
6429         if (NT_STATUS_IS_ERR(nt_status)) {
6430                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6431                 nt_errstr(nt_status)));
6432                 goto done;
6433         }
6434
6435         data = data_blob(info->password.password->data,
6436                          info->password.password->length);
6437
6438         if (!rpccli_get_pwd_hash(pipe_hnd, session_key)) {
6439                 DEBUG(0, ("Could not retrieve password hash\n"));
6440                 goto done;
6441         }
6442
6443         session_key_blob = data_blob_const(session_key, sizeof(session_key));
6444         cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key_blob);
6445
6446         if (cleartextpwd == NULL) {
6447                 DEBUG(0,("retrieved NULL password\n"));
6448                 nt_status = NT_STATUS_UNSUCCESSFUL;
6449                 goto done;
6450         }
6451
6452         if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6453                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6454                 nt_status = NT_STATUS_UNSUCCESSFUL;
6455                 goto done;
6456         }
6457
6458 #ifdef DEBUG_PASSWORD
6459         DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
6460                    "password: [%s]\n", trusted_dom_name,
6461                    sid_string_dbg(&dom_sid), cleartextpwd));
6462 #endif
6463
6464 done:
6465         SAFE_FREE(cleartextpwd);
6466         data_blob_free(&data);
6467
6468         return nt_status;
6469 }
6470
6471 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6472                                 const char **argv)
6473 {
6474         /* common variables */
6475         TALLOC_CTX* mem_ctx;
6476         struct cli_state *cli = NULL;
6477         struct rpc_pipe_client *pipe_hnd = NULL;
6478         NTSTATUS nt_status;
6479         const char *domain_name = NULL;
6480         struct dom_sid *queried_dom_sid;
6481         struct policy_handle connect_hnd;
6482         union lsa_PolicyInformation *info = NULL;
6483
6484         /* trusted domains listing variables */
6485         unsigned int enum_ctx = 0;
6486         int i;
6487         struct lsa_DomainList dom_list;
6488         fstring pdc_name;
6489
6490         if (c->display_usage) {
6491                 d_printf(  "%s\n"
6492                            "net rpc trustdom vampire\n"
6493                            "  %s\n",
6494                          _("Usage:"),
6495                          _("Vampire trust relationship from remote server"));
6496                 return 0;
6497         }
6498
6499         /*
6500          * Listing trusted domains (stored in secrets.tdb, if local)
6501          */
6502
6503         mem_ctx = talloc_init("trust relationships vampire");
6504
6505         /*
6506          * set domain and pdc name to local samba server (default)
6507          * or to remote one given in command line
6508          */
6509
6510         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6511                 domain_name = c->opt_workgroup;
6512                 c->opt_target_workgroup = c->opt_workgroup;
6513         } else {
6514                 fstrcpy(pdc_name, global_myname());
6515                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6516                 c->opt_target_workgroup = domain_name;
6517         };
6518
6519         /* open \PIPE\lsarpc and open policy handle */
6520         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6521         if (!NT_STATUS_IS_OK(nt_status)) {
6522                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6523                           nt_errstr(nt_status)));
6524                 talloc_destroy(mem_ctx);
6525                 return -1;
6526         };
6527
6528         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6529                                              &pipe_hnd);
6530         if (!NT_STATUS_IS_OK(nt_status)) {
6531                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6532                         nt_errstr(nt_status) ));
6533                 cli_shutdown(cli);
6534                 talloc_destroy(mem_ctx);
6535                 return -1;
6536         };
6537
6538         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6539                                         &connect_hnd);
6540         if (NT_STATUS_IS_ERR(nt_status)) {
6541                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6542                         nt_errstr(nt_status)));
6543                 cli_shutdown(cli);
6544                 talloc_destroy(mem_ctx);
6545                 return -1;
6546         };
6547
6548         /* query info level 5 to obtain sid of a domain being queried */
6549         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6550                                                &connect_hnd,
6551                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6552                                                &info);
6553
6554         if (NT_STATUS_IS_ERR(nt_status)) {
6555                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6556                         nt_errstr(nt_status)));
6557                 cli_shutdown(cli);
6558                 talloc_destroy(mem_ctx);
6559                 return -1;
6560         }
6561
6562         queried_dom_sid = info->account_domain.sid;
6563
6564         /*
6565          * Keep calling LsaEnumTrustdom over opened pipe until
6566          * the end of enumeration is reached
6567          */
6568
6569         d_printf(_("Vampire trusted domains:\n\n"));
6570
6571         do {
6572                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6573                                                     &connect_hnd,
6574                                                     &enum_ctx,
6575                                                     &dom_list,
6576                                                     (uint32_t)-1);
6577                 if (NT_STATUS_IS_ERR(nt_status)) {
6578                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6579                                 nt_errstr(nt_status)));
6580                         cli_shutdown(cli);
6581                         talloc_destroy(mem_ctx);
6582                         return -1;
6583                 };
6584
6585                 for (i = 0; i < dom_list.count; i++) {
6586
6587                         print_trusted_domain(dom_list.domains[i].sid,
6588                                              dom_list.domains[i].name.string);
6589
6590                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
6591                                                            *dom_list.domains[i].sid,
6592                                                            dom_list.domains[i].name.string);
6593                         if (!NT_STATUS_IS_OK(nt_status)) {
6594                                 cli_shutdown(cli);
6595                                 talloc_destroy(mem_ctx);
6596                                 return -1;
6597                         }
6598                 };
6599
6600                 /*
6601                  * in case of no trusted domains say something rather
6602                  * than just display blank line
6603                  */
6604                 if (!dom_list.count) d_printf(_("none\n"));
6605
6606         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6607
6608         /* close this connection before doing next one */
6609         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6610         if (NT_STATUS_IS_ERR(nt_status)) {
6611                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6612                         nt_errstr(nt_status)));
6613                 cli_shutdown(cli);
6614                 talloc_destroy(mem_ctx);
6615                 return -1;
6616         };
6617
6618         /* close lsarpc pipe and connection to IPC$ */
6619         cli_shutdown(cli);
6620
6621         talloc_destroy(mem_ctx);
6622         return 0;
6623 }
6624
6625 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6626 {
6627         /* common variables */
6628         TALLOC_CTX* mem_ctx;
6629         struct cli_state *cli = NULL, *remote_cli = NULL;
6630         struct rpc_pipe_client *pipe_hnd = NULL;
6631         NTSTATUS nt_status, result;
6632         const char *domain_name = NULL;
6633         struct dom_sid *queried_dom_sid;
6634         int ascii_dom_name_len;
6635         struct policy_handle connect_hnd;
6636         union lsa_PolicyInformation *info = NULL;
6637         struct dcerpc_binding_handle *b = NULL;
6638
6639         /* trusted domains listing variables */
6640         unsigned int num_domains, enum_ctx = 0;
6641         int i;
6642         struct lsa_DomainList dom_list;
6643         fstring pdc_name;
6644         bool found_domain;
6645
6646         /* trusting domains listing variables */
6647         struct policy_handle domain_hnd;
6648         struct samr_SamArray *trusts = NULL;
6649
6650         if (c->display_usage) {
6651                 d_printf(  "%s\n"
6652                            "net rpc trustdom list\n"
6653                            "    %s\n",
6654                          _("Usage:"),
6655                          _("List incoming and outgoing trust relationships"));
6656                 return 0;
6657         }
6658
6659         /*
6660          * Listing trusted domains (stored in secrets.tdb, if local)
6661          */
6662
6663         mem_ctx = talloc_init("trust relationships listing");
6664
6665         /*
6666          * set domain and pdc name to local samba server (default)
6667          * or to remote one given in command line
6668          */
6669
6670         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6671                 domain_name = c->opt_workgroup;
6672                 c->opt_target_workgroup = c->opt_workgroup;
6673         } else {
6674                 fstrcpy(pdc_name, global_myname());
6675                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6676                 c->opt_target_workgroup = domain_name;
6677         };
6678
6679         /* open \PIPE\lsarpc and open policy handle */
6680         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6681         if (!NT_STATUS_IS_OK(nt_status)) {
6682                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6683                           nt_errstr(nt_status)));
6684                 talloc_destroy(mem_ctx);
6685                 return -1;
6686         };
6687
6688         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6689                                              &pipe_hnd);
6690         if (!NT_STATUS_IS_OK(nt_status)) {
6691                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6692                         nt_errstr(nt_status) ));
6693                 cli_shutdown(cli);
6694                 talloc_destroy(mem_ctx);
6695                 return -1;
6696         };
6697
6698         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6699                                         &connect_hnd);
6700         if (NT_STATUS_IS_ERR(nt_status)) {
6701                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6702                         nt_errstr(nt_status)));
6703                 cli_shutdown(cli);
6704                 talloc_destroy(mem_ctx);
6705                 return -1;
6706         };
6707         
6708         /* query info level 5 to obtain sid of a domain being queried */
6709         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6710                                                &connect_hnd,
6711                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6712                                                &info);
6713
6714         if (NT_STATUS_IS_ERR(nt_status)) {
6715                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6716                         nt_errstr(nt_status)));
6717                 cli_shutdown(cli);
6718                 talloc_destroy(mem_ctx);
6719                 return -1;
6720         }
6721
6722         queried_dom_sid = info->account_domain.sid;
6723
6724         /*
6725          * Keep calling LsaEnumTrustdom over opened pipe until
6726          * the end of enumeration is reached
6727          */
6728
6729         d_printf(_("Trusted domains list:\n\n"));
6730
6731         found_domain = false;
6732
6733         do {
6734                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6735                                                     &connect_hnd,
6736                                                     &enum_ctx,
6737                                                     &dom_list,
6738                                                     (uint32_t)-1);
6739                 if (NT_STATUS_IS_ERR(nt_status)) {
6740                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6741                                 nt_errstr(nt_status)));
6742                         cli_shutdown(cli);
6743                         talloc_destroy(mem_ctx);
6744                         return -1;
6745                 };
6746
6747                 for (i = 0; i < dom_list.count; i++) {
6748                         print_trusted_domain(dom_list.domains[i].sid,
6749                                              dom_list.domains[i].name.string);
6750                         found_domain = true;
6751                 };
6752
6753
6754         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6755
6756         /*
6757          * in case of no trusted domains say something rather
6758          * than just display blank line
6759          */
6760         if (!found_domain) {
6761                 d_printf(_("none\n"));
6762         }
6763
6764         /* close this connection before doing next one */
6765         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6766         if (NT_STATUS_IS_ERR(nt_status)) {
6767                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6768                         nt_errstr(nt_status)));
6769                 cli_shutdown(cli);
6770                 talloc_destroy(mem_ctx);
6771                 return -1;
6772         };
6773         
6774         TALLOC_FREE(pipe_hnd);
6775
6776         /*
6777          * Listing trusting domains (stored in passdb backend, if local)
6778          */
6779         
6780         d_printf(_("\nTrusting domains list:\n\n"));
6781
6782         /*
6783          * Open \PIPE\samr and get needed policy handles
6784          */
6785         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6786                                              &pipe_hnd);
6787         if (!NT_STATUS_IS_OK(nt_status)) {
6788                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6789                 cli_shutdown(cli);
6790                 talloc_destroy(mem_ctx);
6791                 return -1;
6792         };
6793
6794         b = pipe_hnd->binding_handle;
6795
6796         /* SamrConnect2 */
6797         nt_status = dcerpc_samr_Connect2(b, mem_ctx,
6798                                          pipe_hnd->desthost,
6799                                          SAMR_ACCESS_LOOKUP_DOMAIN,
6800                                          &connect_hnd,
6801                                          &result);
6802         if (!NT_STATUS_IS_OK(nt_status)) {
6803                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6804                         nt_errstr(nt_status)));
6805                 cli_shutdown(cli);
6806                 talloc_destroy(mem_ctx);
6807                 return -1;
6808         };
6809         if (!NT_STATUS_IS_OK(result)) {
6810                 nt_status = result;
6811                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6812                         nt_errstr(result)));
6813                 cli_shutdown(cli);
6814                 talloc_destroy(mem_ctx);
6815                 return -1;
6816         };
6817
6818         /* SamrOpenDomain - we have to open domain policy handle in order to be
6819            able to enumerate accounts*/
6820         nt_status = dcerpc_samr_OpenDomain(b, mem_ctx,
6821                                            &connect_hnd,
6822                                            SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6823                                            queried_dom_sid,
6824                                            &domain_hnd,
6825                                            &result);
6826         if (!NT_STATUS_IS_OK(nt_status)) {
6827                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6828                         nt_errstr(nt_status)));
6829                 cli_shutdown(cli);
6830                 talloc_destroy(mem_ctx);
6831                 return -1;
6832         };
6833         if (!NT_STATUS_IS_OK(result)) {
6834                 nt_status = result;
6835                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6836                         nt_errstr(result)));
6837                 cli_shutdown(cli);
6838                 talloc_destroy(mem_ctx);
6839                 return -1;
6840         };
6841
6842         /*
6843          * perform actual enumeration
6844          */
6845
6846         found_domain = false;
6847
6848         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6849         do {
6850
6851                 nt_status = dcerpc_samr_EnumDomainUsers(b, mem_ctx,
6852                                                         &domain_hnd,
6853                                                         &enum_ctx,
6854                                                         ACB_DOMTRUST,
6855                                                         &trusts,
6856                                                         0xffff,
6857                                                         &num_domains,
6858                                                         &result);
6859                 if (NT_STATUS_IS_ERR(nt_status)) {
6860                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6861                                 nt_errstr(nt_status)));
6862                         cli_shutdown(cli);
6863                         talloc_destroy(mem_ctx);
6864                         return -1;
6865                 };
6866                 if (NT_STATUS_IS_ERR(result)) {
6867                         nt_status = result;
6868                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6869                                 nt_errstr(result)));
6870                         cli_shutdown(cli);
6871                         talloc_destroy(mem_ctx);
6872                         return -1;
6873                 };
6874
6875                 for (i = 0; i < num_domains; i++) {
6876
6877                         char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6878
6879                         found_domain = true;
6880
6881                         /*
6882                          * get each single domain's sid (do we _really_ need this ?):
6883                          *  1) connect to domain's pdc
6884                          *  2) query the pdc for domain's sid
6885                          */
6886
6887                         /* get rid of '$' tail */
6888                         ascii_dom_name_len = strlen(str);
6889                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6890                                 str[ascii_dom_name_len - 1] = '\0';
6891
6892                         /* set opt_* variables to remote domain */
6893                         strupper_m(str);
6894                         c->opt_workgroup = talloc_strdup(mem_ctx, str);
6895                         c->opt_target_workgroup = c->opt_workgroup;
6896
6897                         d_printf("%-20s", str);
6898
6899                         /* connect to remote domain controller */
6900                         nt_status = net_make_ipc_connection(c,
6901                                         NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6902                                         &remote_cli);
6903                         if (NT_STATUS_IS_OK(nt_status)) {
6904                                 /* query for domain's sid */
6905                                 if (run_rpc_command(
6906                                             c, remote_cli,
6907                                             &ndr_table_lsarpc.syntax_id, 0,
6908                                             rpc_query_domain_sid, argc,
6909                                             argv))
6910                                         d_printf(_("strange - couldn't get domain's sid\n"));
6911
6912                                 cli_shutdown(remote_cli);
6913
6914                         } else {
6915                                 d_fprintf(stderr, _("domain controller is not "
6916                                           "responding: %s\n"),
6917                                           nt_errstr(nt_status));
6918                                 d_printf(_("couldn't get domain's sid\n"));
6919                         }
6920                 }
6921
6922         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
6923
6924         if (!found_domain) {
6925                 d_printf("none\n");
6926         }
6927
6928         /* close opened samr and domain policy handles */
6929         nt_status = dcerpc_samr_Close(b, mem_ctx, &domain_hnd, &result);
6930         if (!NT_STATUS_IS_OK(nt_status)) {
6931                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6932         };
6933
6934         nt_status = dcerpc_samr_Close(b, mem_ctx, &connect_hnd, &result);
6935         if (!NT_STATUS_IS_OK(nt_status)) {
6936                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6937         };
6938
6939         /* close samr pipe and connection to IPC$ */
6940         cli_shutdown(cli);
6941
6942         talloc_destroy(mem_ctx);
6943         return 0;
6944 }
6945
6946 /**
6947  * Entrypoint for 'net rpc trustdom' code.
6948  *
6949  * @param argc Standard argc.
6950  * @param argv Standard argv without initial components.
6951  *
6952  * @return Integer status (0 means success).
6953  */
6954
6955 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
6956 {
6957         struct functable func[] = {
6958                 {
6959                         "add",
6960                         rpc_trustdom_add,
6961                         NET_TRANSPORT_RPC,
6962                         N_("Add trusting domain's account"),
6963                         N_("net rpc trustdom add\n"
6964                            "    Add trusting domain's account")
6965                 },
6966                 {
6967                         "del",
6968                         rpc_trustdom_del,
6969                         NET_TRANSPORT_RPC,
6970                         N_("Remove trusting domain's account"),
6971                         N_("net rpc trustdom del\n"
6972                            "    Remove trusting domain's account")
6973                 },
6974                 {
6975                         "establish",
6976                         rpc_trustdom_establish,
6977                         NET_TRANSPORT_RPC,
6978                         N_("Establish outgoing trust relationship"),
6979                         N_("net rpc trustdom establish\n"
6980                            "    Establish outgoing trust relationship")
6981                 },
6982                 {
6983                         "revoke",
6984                         rpc_trustdom_revoke,
6985                         NET_TRANSPORT_RPC,
6986                         N_("Revoke outgoing trust relationship"),
6987                         N_("net rpc trustdom revoke\n"
6988                            "    Revoke outgoing trust relationship")
6989                 },
6990                 {
6991                         "list",
6992                         rpc_trustdom_list,
6993                         NET_TRANSPORT_RPC,
6994                         N_("List in- and outgoing domain trusts"),
6995                         N_("net rpc trustdom list\n"
6996                            "    List in- and outgoing domain trusts")
6997                 },
6998                 {
6999                         "vampire",
7000                         rpc_trustdom_vampire,
7001                         NET_TRANSPORT_RPC,
7002                         N_("Vampire trusts from remote server"),
7003                         N_("net rpc trustdom vampire\n"
7004                            "    Vampire trusts from remote server")
7005                 },
7006                 {NULL, NULL, 0, NULL, NULL}
7007         };
7008
7009         return net_run_function(c, argc, argv, "net rpc trustdom", func);
7010 }
7011
7012 /**
7013  * Check if a server will take rpc commands
7014  * @param flags Type of server to connect to (PDC, DMB, localhost)
7015  *              if the host is not explicitly specified
7016  * @return  bool (true means rpc supported)
7017  */
7018 bool net_rpc_check(struct net_context *c, unsigned flags)
7019 {
7020         struct cli_state *cli;
7021         bool ret = false;
7022         struct sockaddr_storage server_ss;
7023         char *server_name = NULL;
7024         NTSTATUS status;
7025
7026         /* flags (i.e. server type) may depend on command */
7027         if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
7028                 return false;
7029
7030         if ((cli = cli_initialise()) == NULL) {
7031                 return false;
7032         }
7033
7034         status = cli_connect(cli, server_name, &server_ss);
7035         if (!NT_STATUS_IS_OK(status))
7036                 goto done;
7037         if (!attempt_netbios_session_request(&cli, global_myname(),
7038                                              server_name, &server_ss))
7039                 goto done;
7040         status = cli_negprot(cli);
7041         if (!NT_STATUS_IS_OK(status))
7042                 goto done;
7043         if (cli->protocol < PROTOCOL_NT1)
7044                 goto done;
7045
7046         ret = true;
7047  done:
7048         cli_shutdown(cli);
7049         return ret;
7050 }
7051
7052 /* dump sam database via samsync rpc calls */
7053 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
7054         if (c->display_usage) {
7055                 d_printf(  "%s\n"
7056                            "net rpc samdump\n"
7057                            "    %s\n",
7058                          _("Usage:"),
7059                          _("Dump remote SAM database"));
7060                 return 0;
7061         }
7062
7063         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
7064                                NET_FLAGS_ANONYMOUS,
7065                                rpc_samdump_internals, argc, argv);
7066 }
7067
7068 /* syncronise sam database via samsync rpc calls */
7069 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
7070 {
7071         struct functable func[] = {
7072                 {
7073                         "ldif",
7074                         rpc_vampire_ldif,
7075                         NET_TRANSPORT_RPC,
7076                         N_("Dump remote SAM database to ldif"),
7077                         N_("net rpc vampire ldif\n"
7078                            "    Dump remote SAM database to LDIF file or "
7079                            "stdout")
7080                 },
7081                 {
7082                         "keytab",
7083                         rpc_vampire_keytab,
7084                         NET_TRANSPORT_RPC,
7085                         N_("Dump remote SAM database to Kerberos Keytab"),
7086                         N_("net rpc vampire keytab\n"
7087                            "    Dump remote SAM database to Kerberos keytab "
7088                            "file")
7089                 },
7090                 {
7091                         "passdb",
7092                         rpc_vampire_passdb,
7093                         NET_TRANSPORT_RPC,
7094                         N_("Dump remote SAM database to passdb"),
7095                         N_("net rpc vampire passdb\n"
7096                            "    Dump remote SAM database to passdb")
7097                 },
7098
7099                 {NULL, NULL, 0, NULL, NULL}
7100         };
7101
7102         if (argc == 0) {
7103                 if (c->display_usage) {
7104                         d_printf(  "%s\n"
7105                                    "net rpc vampire\n"
7106                                    "    %s\n",
7107                                  _("Usage:"),
7108                                  _("Vampire remote SAM database"));
7109                         return 0;
7110                 }
7111
7112                 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
7113                                        NET_FLAGS_ANONYMOUS,
7114                                        rpc_vampire_internals,
7115                                        argc, argv);
7116         }
7117
7118         return net_run_function(c, argc, argv, "net rpc vampire", func);
7119 }
7120
7121 /**
7122  * Migrate everything from a print server.
7123  *
7124  * @param c     A net_context structure.
7125  * @param argc  Standard main() style argc.
7126  * @param argv  Standard main() style argv. Initial components are already
7127  *              stripped.
7128  *
7129  * @return A shell status integer (0 for success).
7130  *
7131  * The order is important !
7132  * To successfully add drivers the print queues have to exist !
7133  * Applying ACLs should be the last step, because you're easily locked out.
7134  *
7135  **/
7136 static int rpc_printer_migrate_all(struct net_context *c, int argc,
7137                                    const char **argv)
7138 {
7139         int ret;
7140
7141         if (c->display_usage) {
7142                 d_printf(  "%s\n"
7143                            "net rpc printer migrate all\n"
7144                            "    %s\n",
7145                          _("Usage:"),
7146                          _("Migrate everything from a print server"));
7147                 return 0;
7148         }
7149
7150         if (!c->opt_host) {
7151                 d_printf(_("no server to migrate\n"));
7152                 return -1;
7153         }
7154
7155         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7156                               rpc_printer_migrate_printers_internals, argc,
7157                               argv);
7158         if (ret)
7159                 return ret;
7160
7161         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7162                               rpc_printer_migrate_drivers_internals, argc,
7163                               argv);
7164         if (ret)
7165                 return ret;
7166
7167         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7168                               rpc_printer_migrate_forms_internals, argc, argv);
7169         if (ret)
7170                 return ret;
7171
7172         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7173                               rpc_printer_migrate_settings_internals, argc,
7174                               argv);
7175         if (ret)
7176                 return ret;
7177
7178         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7179                                rpc_printer_migrate_security_internals, argc,
7180                                argv);
7181
7182 }
7183
7184 /**
7185  * Migrate print drivers from a print server.
7186  *
7187  * @param c     A net_context structure.
7188  * @param argc  Standard main() style argc.
7189  * @param argv  Standard main() style argv. Initial components are already
7190  *              stripped.
7191  *
7192  * @return A shell status integer (0 for success).
7193  **/
7194 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
7195                                        const char **argv)
7196 {
7197         if (c->display_usage) {
7198                 d_printf(  "%s\n"
7199                            "net rpc printer migrate drivers\n"
7200                            "     %s\n",
7201                          _("Usage:"),
7202                          _("Migrate print-drivers from a print-server"));
7203                 return 0;
7204         }
7205
7206         if (!c->opt_host) {
7207                 d_printf(_("no server to migrate\n"));
7208                 return -1;
7209         }
7210
7211         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7212                                rpc_printer_migrate_drivers_internals,
7213                                argc, argv);
7214 }
7215
7216 /**
7217  * Migrate print-forms from a print-server.
7218  *
7219  * @param c     A net_context structure.
7220  * @param argc  Standard main() style argc.
7221  * @param argv  Standard main() style argv. Initial components are already
7222  *              stripped.
7223  *
7224  * @return A shell status integer (0 for success).
7225  **/
7226 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
7227                                      const char **argv)
7228 {
7229         if (c->display_usage) {
7230                 d_printf(  "%s\n"
7231                            "net rpc printer migrate forms\n"
7232                            "    %s\n",
7233                          _("Usage:"),
7234                          _("Migrate print-forms from a print-server"));
7235                 return 0;
7236         }
7237
7238         if (!c->opt_host) {
7239                 d_printf(_("no server to migrate\n"));
7240                 return -1;
7241         }
7242
7243         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7244                                rpc_printer_migrate_forms_internals,
7245                                argc, argv);
7246 }
7247
7248 /**
7249  * Migrate printers from a print-server.
7250  *
7251  * @param c     A net_context structure.
7252  * @param argc  Standard main() style argc.
7253  * @param argv  Standard main() style argv. Initial components are already
7254  *              stripped.
7255  *
7256  * @return A shell status integer (0 for success).
7257  **/
7258 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
7259                                         const char **argv)
7260 {
7261         if (c->display_usage) {
7262                 d_printf(  "%s\n"
7263                            "net rpc printer migrate printers\n"
7264                            "    %s\n",
7265                          _("Usage:"),
7266                          _("Migrate printers from a print-server"));
7267                 return 0;
7268         }
7269
7270         if (!c->opt_host) {
7271                 d_printf(_("no server to migrate\n"));
7272                 return -1;
7273         }
7274
7275         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7276                                rpc_printer_migrate_printers_internals,
7277                                argc, argv);
7278 }
7279
7280 /**
7281  * Migrate printer-ACLs from a print-server
7282  *
7283  * @param c     A net_context structure.
7284  * @param argc  Standard main() style argc.
7285  * @param argv  Standard main() style argv. Initial components are already
7286  *              stripped.
7287  *
7288  * @return A shell status integer (0 for success).
7289  **/
7290 static int rpc_printer_migrate_security(struct net_context *c, int argc,
7291                                         const char **argv)
7292 {
7293         if (c->display_usage) {
7294                 d_printf(  "%s\n"
7295                            "net rpc printer migrate security\n"
7296                            "    %s\n",
7297                          _("Usage:"),
7298                          _("Migrate printer-ACLs from a print-server"));
7299                 return 0;
7300         }
7301
7302         if (!c->opt_host) {
7303                 d_printf(_("no server to migrate\n"));
7304                 return -1;
7305         }
7306
7307         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7308                                rpc_printer_migrate_security_internals,
7309                                argc, argv);
7310 }
7311
7312 /**
7313  * Migrate printer-settings from a print-server.
7314  *
7315  * @param c     A net_context structure.
7316  * @param argc  Standard main() style argc.
7317  * @param argv  Standard main() style argv. Initial components are already
7318  *              stripped.
7319  *
7320  * @return A shell status integer (0 for success).
7321  **/
7322 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
7323                                         const char **argv)
7324 {
7325         if (c->display_usage) {
7326                 d_printf(  "%s\n"
7327                            "net rpc printer migrate settings\n"
7328                             "    %s\n",
7329                           _("Usage:"),
7330                           _("Migrate printer-settings from a "
7331                             "print-server"));
7332                 return 0;
7333         }
7334
7335         if (!c->opt_host) {
7336                 d_printf(_("no server to migrate\n"));
7337                 return -1;
7338         }
7339
7340         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7341                                rpc_printer_migrate_settings_internals,
7342                                argc, argv);
7343 }
7344
7345 /**
7346  * 'net rpc printer' entrypoint.
7347  *
7348  * @param c     A net_context structure.
7349  * @param argc  Standard main() style argc.
7350  * @param argv  Standard main() style argv. Initial components are already
7351  *              stripped.
7352  **/
7353
7354 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
7355 {
7356
7357         /* ouch: when addriver and setdriver are called from within
7358            rpc_printer_migrate_drivers_internals, the printer-queue already
7359            *has* to exist */
7360
7361         struct functable func[] = {
7362                 {
7363                         "all",
7364                         rpc_printer_migrate_all,
7365                         NET_TRANSPORT_RPC,
7366                         N_("Migrate all from remote to local print server"),
7367                         N_("net rpc printer migrate all\n"
7368                            "    Migrate all from remote to local print server")
7369                 },
7370                 {
7371                         "drivers",
7372                         rpc_printer_migrate_drivers,
7373                         NET_TRANSPORT_RPC,
7374                         N_("Migrate drivers to local server"),
7375                         N_("net rpc printer migrate drivers\n"
7376                            "    Migrate drivers to local server")
7377                 },
7378                 {
7379                         "forms",
7380                         rpc_printer_migrate_forms,
7381                         NET_TRANSPORT_RPC,
7382                         N_("Migrate froms to local server"),
7383                         N_("net rpc printer migrate forms\n"
7384                            "    Migrate froms to local server")
7385                 },
7386                 {
7387                         "printers",
7388                         rpc_printer_migrate_printers,
7389                         NET_TRANSPORT_RPC,
7390                         N_("Migrate printers to local server"),
7391                         N_("net rpc printer migrate printers\n"
7392                            "    Migrate printers to local server")
7393                 },
7394                 {
7395                         "security",
7396                         rpc_printer_migrate_security,
7397                         NET_TRANSPORT_RPC,
7398                         N_("Mirgate printer ACLs to local server"),
7399                         N_("net rpc printer migrate security\n"
7400                            "    Mirgate printer ACLs to local server")
7401                 },
7402                 {
7403                         "settings",
7404                         rpc_printer_migrate_settings,
7405                         NET_TRANSPORT_RPC,
7406                         N_("Migrate printer settings to local server"),
7407                         N_("net rpc printer migrate settings\n"
7408                            "    Migrate printer settings to local server")
7409                 },
7410                 {NULL, NULL, 0, NULL, NULL}
7411         };
7412
7413         return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7414 }
7415
7416
7417 /**
7418  * List printers on a remote RPC server.
7419  *
7420  * @param c     A net_context structure.
7421  * @param argc  Standard main() style argc.
7422  * @param argv  Standard main() style argv. Initial components are already
7423  *              stripped.
7424  *
7425  * @return A shell status integer (0 for success).
7426  **/
7427 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7428 {
7429         if (c->display_usage) {
7430                 d_printf(  "%s\n"
7431                            "net rpc printer list\n"
7432                            "    %s\n",
7433                          _("Usage:"),
7434                          _("List printers on a remote RPC server"));
7435                 return 0;
7436         }
7437
7438         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7439                                rpc_printer_list_internals,
7440                                argc, argv);
7441 }
7442
7443 /**
7444  * List printer-drivers on a remote RPC server.
7445  *
7446  * @param c     A net_context structure.
7447  * @param argc  Standard main() style argc.
7448  * @param argv  Standard main() style argv. Initial components are already
7449  *              stripped.
7450  *
7451  * @return A shell status integer (0 for success).
7452  **/
7453 static int rpc_printer_driver_list(struct net_context *c, int argc,
7454                                    const char **argv)
7455 {
7456         if (c->display_usage) {
7457                 d_printf(  "%s\n"
7458                            "net rpc printer driver\n"
7459                            "    %s\n",
7460                          _("Usage:"),
7461                          _("List printer-drivers on a remote RPC server"));
7462                 return 0;
7463         }
7464
7465         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7466                                rpc_printer_driver_list_internals,
7467                                argc, argv);
7468 }
7469
7470 /**
7471  * Publish printer in ADS via MSRPC.
7472  *
7473  * @param c     A net_context structure.
7474  * @param argc  Standard main() style argc.
7475  * @param argv  Standard main() style argv. Initial components are already
7476  *              stripped.
7477  *
7478  * @return A shell status integer (0 for success).
7479  **/
7480 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7481                                        const char **argv)
7482 {
7483         if (c->display_usage) {
7484                 d_printf(  "%s\n"
7485                            "net rpc printer publish publish\n"
7486                            "     %s\n",
7487                          _("Usage:"),
7488                          _("Publish printer in ADS via MSRPC"));
7489                 return 0;
7490         }
7491
7492         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7493                                rpc_printer_publish_publish_internals,
7494                                argc, argv);
7495 }
7496
7497 /**
7498  * Update printer in ADS via MSRPC.
7499  *
7500  * @param c     A net_context structure.
7501  * @param argc  Standard main() style argc.
7502  * @param argv  Standard main() style argv. Initial components are already
7503  *              stripped.
7504  *
7505  * @return A shell status integer (0 for success).
7506  **/
7507 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7508 {
7509         if (c->display_usage) {
7510                 d_printf(  "%s\n"
7511                            "net rpc printer publish update\n"
7512                            "    %s\n",
7513                          _("Usage:"),
7514                          _("Update printer in ADS via MSRPC"));
7515                 return 0;
7516         }
7517
7518         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7519                                rpc_printer_publish_update_internals,
7520                                argc, argv);
7521 }
7522
7523 /**
7524  * UnPublish printer in ADS via MSRPC.
7525  *
7526  * @param c     A net_context structure.
7527  * @param argc  Standard main() style argc.
7528  * @param argv  Standard main() style argv. Initial components are already
7529  *              stripped.
7530  *
7531  * @return A shell status integer (0 for success).
7532  **/
7533 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7534                                          const char **argv)
7535 {
7536         if (c->display_usage) {
7537                 d_printf(  "%s\n"
7538                            "net rpc printer publish unpublish\n"
7539                            "    %s\n",
7540                          _("Usage:\n"),
7541                          _("UnPublish printer in ADS via MSRPC"));
7542                 return 0;
7543         }
7544
7545         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7546                                rpc_printer_publish_unpublish_internals,
7547                                argc, argv);
7548 }
7549
7550 /**
7551  * List published printers via MSRPC.
7552  *
7553  * @param c     A net_context structure.
7554  * @param argc  Standard main() style argc.
7555  * @param argv  Standard main() style argv. Initial components are already
7556  *              stripped.
7557  *
7558  * @return A shell status integer (0 for success).
7559  **/
7560 static int rpc_printer_publish_list(struct net_context *c, int argc,
7561                                     const char **argv)
7562 {
7563         if (c->display_usage) {
7564                 d_printf(  "%s\n"
7565                            "net rpc printer publish list\n"
7566                            "    %s\n",
7567                          _("Usage:"),
7568                          _("List published printers via MSRPC"));
7569                 return 0;
7570         }
7571
7572         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7573                                rpc_printer_publish_list_internals,
7574                                argc, argv);
7575 }
7576
7577
7578 /**
7579  * Publish printer in ADS.
7580  *
7581  * @param c     A net_context structure.
7582  * @param argc  Standard main() style argc.
7583  * @param argv  Standard main() style argv. Initial components are already
7584  *              stripped.
7585  *
7586  * @return A shell status integer (0 for success).
7587  **/
7588 static int rpc_printer_publish(struct net_context *c, int argc,
7589                                const char **argv)
7590 {
7591
7592         struct functable func[] = {
7593                 {
7594                         "publish",
7595                         rpc_printer_publish_publish,
7596                         NET_TRANSPORT_RPC,
7597                         N_("Publish printer in AD"),
7598                         N_("net rpc printer publish publish\n"
7599                            "    Publish printer in AD")
7600                 },
7601                 {
7602                         "update",
7603                         rpc_printer_publish_update,
7604                         NET_TRANSPORT_RPC,
7605                         N_("Update printer in AD"),
7606                         N_("net rpc printer publish update\n"
7607                            "    Update printer in AD")
7608                 },
7609                 {
7610                         "unpublish",
7611                         rpc_printer_publish_unpublish,
7612                         NET_TRANSPORT_RPC,
7613                         N_("Unpublish printer"),
7614                         N_("net rpc printer publish unpublish\n"
7615                            "    Unpublish printer")
7616                 },
7617                 {
7618                         "list",
7619                         rpc_printer_publish_list,
7620                         NET_TRANSPORT_RPC,
7621                         N_("List published printers"),
7622                         N_("net rpc printer publish list\n"
7623                            "    List published printers")
7624                 },
7625                 {NULL, NULL, 0, NULL, NULL}
7626         };
7627
7628         if (argc == 0) {
7629                 if (c->display_usage) {
7630                         d_printf(_("Usage:\n"));
7631                         d_printf(_("net rpc printer publish\n"
7632                                    "    List published printers\n"
7633                                    "    Alias of net rpc printer publish "
7634                                    "list\n"));
7635                         net_display_usage_from_functable(func);
7636                         return 0;
7637                 }
7638                 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7639                                rpc_printer_publish_list_internals,
7640                                argc, argv);
7641         }
7642
7643         return net_run_function(c, argc, argv, "net rpc printer publish",func);
7644
7645 }
7646
7647
7648 /**
7649  * Display rpc printer help page.
7650  *
7651  * @param c     A net_context structure.
7652  * @param argc  Standard main() style argc.
7653  * @param argv  Standard main() style argv. Initial components are already
7654  *              stripped.
7655  **/
7656 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
7657 {
7658         d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
7659                    "\tlists all printers on print-server\n\n"));
7660         d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
7661                    "\tlists all printer-drivers on print-server\n\n"));
7662         d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
7663                    "\tpublishes printer settings in Active Directory\n"
7664                    "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
7665         d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
7666                    "\n\tmigrates printers from remote to local server\n\n"));
7667         d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
7668                    "\n\tmigrates printer-settings from remote to local server\n\n"));
7669         d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
7670                    "\n\tmigrates printer-drivers from remote to local server\n\n"));
7671         d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
7672                    "\n\tmigrates printer-forms from remote to local server\n\n"));
7673         d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
7674                    "\n\tmigrates printer-ACLs from remote to local server\n\n"));
7675         d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
7676                    "\n\tmigrates drivers, forms, queues, settings and acls from\n"
7677                    "\tremote to local print-server\n\n"));
7678         net_common_methods_usage(c, argc, argv);
7679         net_common_flags_usage(c, argc, argv);
7680         d_printf(_(
7681          "\t-v or --verbose\t\t\tgive verbose output\n"
7682          "\t      --destination\t\tmigration target server (default: localhost)\n"));
7683
7684         return -1;
7685 }
7686
7687 /**
7688  * 'net rpc printer' entrypoint.
7689  *
7690  * @param c     A net_context structure.
7691  * @param argc  Standard main() style argc.
7692  * @param argv  Standard main() style argv. Initial components are already
7693  *              stripped.
7694  **/
7695 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7696 {
7697         struct functable func[] = {
7698                 {
7699                         "list",
7700                         rpc_printer_list,
7701                         NET_TRANSPORT_RPC,
7702                         N_("List all printers on print server"),
7703                         N_("net rpc printer list\n"
7704                            "    List all printers on print server")
7705                 },
7706                 {
7707                         "migrate",
7708                         rpc_printer_migrate,
7709                         NET_TRANSPORT_RPC,
7710                         N_("Migrate printer to local server"),
7711                         N_("net rpc printer migrate\n"
7712                            "    Migrate printer to local server")
7713                 },
7714                 {
7715                         "driver",
7716                         rpc_printer_driver_list,
7717                         NET_TRANSPORT_RPC,
7718                         N_("List printer drivers"),
7719                         N_("net rpc printer driver\n"
7720                            "    List printer drivers")
7721                 },
7722                 {
7723                         "publish",
7724                         rpc_printer_publish,
7725                         NET_TRANSPORT_RPC,
7726                         N_("Publish printer in AD"),
7727                         N_("net rpc printer publish\n"
7728                            "    Publish printer in AD")
7729                 },
7730                 {NULL, NULL, 0, NULL, NULL}
7731         };
7732
7733         if (argc == 0) {
7734                 if (c->display_usage) {
7735                         d_printf(_("Usage:\n"));
7736                         d_printf(_("net rpc printer\n"
7737                                    "    List printers\n"));
7738                         net_display_usage_from_functable(func);
7739                         return 0;
7740                 }
7741                 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7742                                rpc_printer_list_internals,
7743                                argc, argv);
7744         }
7745
7746         return net_run_function(c, argc, argv, "net rpc printer", func);
7747 }
7748
7749 /**
7750  * 'net rpc' entrypoint.
7751  *
7752  * @param c     A net_context structure.
7753  * @param argc  Standard main() style argc.
7754  * @param argv  Standard main() style argv. Initial components are already
7755  *              stripped.
7756  **/
7757
7758 int net_rpc(struct net_context *c, int argc, const char **argv)
7759 {
7760         NET_API_STATUS status;
7761
7762         struct functable func[] = {
7763                 {
7764                         "audit",
7765                         net_rpc_audit,
7766                         NET_TRANSPORT_RPC,
7767                         N_("Modify global audit settings"),
7768                         N_("net rpc audit\n"
7769                            "    Modify global audit settings")
7770                 },
7771                 {
7772                         "info",
7773                         net_rpc_info,
7774                         NET_TRANSPORT_RPC,
7775                         N_("Show basic info about a domain"),
7776                         N_("net rpc info\n"
7777                            "    Show basic info about a domain")
7778                 },
7779                 {
7780                         "join",
7781                         net_rpc_join,
7782                         NET_TRANSPORT_RPC,
7783                         N_("Join a domain"),
7784                         N_("net rpc join\n"
7785                            "    Join a domain")
7786                 },
7787                 {
7788                         "oldjoin",
7789                         net_rpc_oldjoin,
7790                         NET_TRANSPORT_RPC,
7791                         N_("Join a domain created in server manager"),
7792                         N_("net rpc oldjoin\n"
7793                            "    Join a domain created in server manager")
7794                 },
7795                 {
7796                         "testjoin",
7797                         net_rpc_testjoin,
7798                         NET_TRANSPORT_RPC,
7799                         N_("Test that a join is valid"),
7800                         N_("net rpc testjoin\n"
7801                            "    Test that a join is valid")
7802                 },
7803                 {
7804                         "user",
7805                         net_rpc_user,
7806                         NET_TRANSPORT_RPC,
7807                         N_("List/modify users"),
7808                         N_("net rpc user\n"
7809                            "    List/modify users")
7810                 },
7811                 {
7812                         "password",
7813                         rpc_user_password,
7814                         NET_TRANSPORT_RPC,
7815                         N_("Change a user password"),
7816                         N_("net rpc password\n"
7817                            "    Change a user password\n"
7818                            "    Alias for net rpc user password")
7819                 },
7820                 {
7821                         "group",
7822                         net_rpc_group,
7823                         NET_TRANSPORT_RPC,
7824                         N_("List/modify groups"),
7825                         N_("net rpc group\n"
7826                            "    List/modify groups")
7827                 },
7828                 {
7829                         "share",
7830                         net_rpc_share,
7831                         NET_TRANSPORT_RPC,
7832                         N_("List/modify shares"),
7833                         N_("net rpc share\n"
7834                            "    List/modify shares")
7835                 },
7836                 {
7837                         "file",
7838                         net_rpc_file,
7839                         NET_TRANSPORT_RPC,
7840                         N_("List open files"),
7841                         N_("net rpc file\n"
7842                            "    List open files")
7843                 },
7844                 {
7845                         "printer",
7846                         net_rpc_printer,
7847                         NET_TRANSPORT_RPC,
7848                         N_("List/modify printers"),
7849                         N_("net rpc printer\n"
7850                            "    List/modify printers")
7851                 },
7852                 {
7853                         "changetrustpw",
7854                         net_rpc_changetrustpw,
7855                         NET_TRANSPORT_RPC,
7856                         N_("Change trust account password"),
7857                         N_("net rpc changetrustpw\n"
7858                            "    Change trust account password")
7859                 },
7860                 {
7861                         "trustdom",
7862                         rpc_trustdom,
7863                         NET_TRANSPORT_RPC,
7864                         N_("Modify domain trusts"),
7865                         N_("net rpc trustdom\n"
7866                            "    Modify domain trusts")
7867                 },
7868                 {
7869                         "abortshutdown",
7870                         rpc_shutdown_abort,
7871                         NET_TRANSPORT_RPC,
7872                         N_("Abort a remote shutdown"),
7873                         N_("net rpc abortshutdown\n"
7874                            "    Abort a remote shutdown")
7875                 },
7876                 {
7877                         "shutdown",
7878                         rpc_shutdown,
7879                         NET_TRANSPORT_RPC,
7880                         N_("Shutdown a remote server"),
7881                         N_("net rpc shutdown\n"
7882                            "    Shutdown a remote server")
7883                 },
7884                 {
7885                         "samdump",
7886                         rpc_samdump,
7887                         NET_TRANSPORT_RPC,
7888                         N_("Dump SAM data of remote NT PDC"),
7889                         N_("net rpc samdump\n"
7890                            "    Dump SAM data of remote NT PDC")
7891                 },
7892                 {
7893                         "vampire",
7894                         rpc_vampire,
7895                         NET_TRANSPORT_RPC,
7896                         N_("Sync a remote NT PDC's data into local passdb"),
7897                         N_("net rpc vampire\n"
7898                            "    Sync a remote NT PDC's data into local passdb")
7899                 },
7900                 {
7901                         "getsid",
7902                         net_rpc_getsid,
7903                         NET_TRANSPORT_RPC,
7904                         N_("Fetch the domain sid into local secrets.tdb"),
7905                         N_("net rpc getsid\n"
7906                            "    Fetch the domain sid into local secrets.tdb")
7907                 },
7908                 {
7909                         "rights",
7910                         net_rpc_rights,
7911                         NET_TRANSPORT_RPC,
7912                         N_("Manage privileges assigned to SID"),
7913                         N_("net rpc rights\n"
7914                            "    Manage privileges assigned to SID")
7915                 },
7916                 {
7917                         "service",
7918                         net_rpc_service,
7919                         NET_TRANSPORT_RPC,
7920                         N_("Start/stop/query remote services"),
7921                         N_("net rpc service\n"
7922                            "    Start/stop/query remote services")
7923                 },
7924                 {
7925                         "registry",
7926                         net_rpc_registry,
7927                         NET_TRANSPORT_RPC,
7928                         N_("Manage registry hives"),
7929                         N_("net rpc registry\n"
7930                            "    Manage registry hives")
7931                 },
7932                 {
7933                         "shell",
7934                         net_rpc_shell,
7935                         NET_TRANSPORT_RPC,
7936                         N_("Open interactive shell on remote server"),
7937                         N_("net rpc shell\n"
7938                            "    Open interactive shell on remote server")
7939                 },
7940                 {NULL, NULL, 0, NULL, NULL}
7941         };
7942
7943         status = libnetapi_net_init(&c->netapi_ctx);
7944         if (status != 0) {
7945                 return -1;
7946         }
7947         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
7948         libnetapi_set_password(c->netapi_ctx, c->opt_password);
7949         if (c->opt_kerberos) {
7950                 libnetapi_set_use_kerberos(c->netapi_ctx);
7951         }
7952         if (c->opt_ccache) {
7953                 libnetapi_set_use_ccache(c->netapi_ctx);
7954         }
7955
7956         return net_run_function(c, argc, argv, "net rpc", func);
7957 }