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