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