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