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