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