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