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