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