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