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