5b3b1e34d748d69ba628d14012bd9e9a2bb5e345
[ira/wip.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         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
3078                 d_printf(_("skipping   [%s]: not a file share.\n"), netname);
3079                 return false;
3080         }
3081
3082         if (!cli_tdis(cli))
3083                 return false;
3084
3085         return true;
3086 }
3087
3088 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3089                                const char *netname, uint32 type)
3090 {
3091         /* only support disk shares */
3092         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3093                 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3094                        type);
3095                 return false;
3096         }
3097
3098         /* skip builtin shares */
3099         /* FIXME: should print$ be added too ? */
3100         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3101             strequal(netname,"global"))
3102                 return false;
3103
3104         if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3105                 printf(_("excluding  [%s]\n"), netname);
3106                 return false;
3107         }
3108
3109         return check_share_availability(cli, netname);
3110 }
3111
3112 /**
3113  * Migrate shares from a remote RPC server to the local RPC server.
3114  *
3115  * All parameters are provided by the run_rpc_command function, except for
3116  * argc, argv which are passed through.
3117  *
3118  * @param domain_sid The domain sid acquired from the remote server.
3119  * @param cli A cli_state connected to the server.
3120  * @param mem_ctx Talloc context, destroyed on completion of the function.
3121  * @param argc  Standard main() style argc.
3122  * @param argv  Standard main() style argv. Initial components are already
3123  *              stripped.
3124  *
3125  * @return Normal NTSTATUS return.
3126  **/
3127
3128 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3129                                                 const DOM_SID *domain_sid,
3130                                                 const char *domain_name,
3131                                                 struct cli_state *cli,
3132                                                 struct rpc_pipe_client *pipe_hnd,
3133                                                 TALLOC_CTX *mem_ctx,
3134                                                 int argc,
3135                                                 const char **argv)
3136 {
3137         WERROR result;
3138         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3139         struct srvsvc_NetShareInfoCtr ctr_src;
3140         uint32 i;
3141         struct rpc_pipe_client *srvsvc_pipe = NULL;
3142         struct cli_state *cli_dst = NULL;
3143         uint32 level = 502; /* includes secdesc */
3144         uint32_t parm_error = 0;
3145
3146         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3147                                 &ctr_src);
3148         if (!W_ERROR_IS_OK(result))
3149                 goto done;
3150
3151         /* connect destination PI_SRVSVC */
3152         nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3153                                      &ndr_table_srvsvc.syntax_id);
3154         if (!NT_STATUS_IS_OK(nt_status))
3155                 return nt_status;
3156
3157
3158         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3159
3160                 union srvsvc_NetShareInfo info;
3161                 struct srvsvc_NetShareInfo502 info502 =
3162                         ctr_src.ctr.ctr502->array[i];
3163
3164                 /* reset error-code */
3165                 nt_status = NT_STATUS_UNSUCCESSFUL;
3166
3167                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3168                         continue;
3169
3170                 /* finally add the share on the dst server */
3171
3172                 printf(_("migrating: [%s], path: %s, comment: %s, without "
3173                          "share-ACLs\n"),
3174                         info502.name, info502.path, info502.comment);
3175
3176                 info.info502 = &info502;
3177
3178                 nt_status = rpccli_srvsvc_NetShareAdd(srvsvc_pipe, mem_ctx,
3179                                                       srvsvc_pipe->desthost,
3180                                                       502,
3181                                                       &info,
3182                                                       &parm_error,
3183                                                       &result);
3184
3185                 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3186                         printf(_("           [%s] does already exist\n"),
3187                                 info502.name);
3188                         continue;
3189                 }
3190
3191                 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3192                         printf(_("cannot add share: %s\n"), win_errstr(result));
3193                         goto done;
3194                 }
3195
3196         }
3197
3198         nt_status = NT_STATUS_OK;
3199
3200 done:
3201         if (cli_dst) {
3202                 cli_shutdown(cli_dst);
3203         }
3204
3205         return nt_status;
3206
3207 }
3208
3209 /**
3210  * Migrate shares from a RPC server to another.
3211  *
3212  * @param argc  Standard main() style argc.
3213  * @param argv  Standard main() style argv. Initial components are already
3214  *              stripped.
3215  *
3216  * @return A shell status integer (0 for success).
3217  **/
3218 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3219                                     const char **argv)
3220 {
3221         if (c->display_usage) {
3222                 d_printf(_("Usage:\n"
3223                            "net rpc share migrate shares\n"
3224                            "    Migrate shares to local server\n"));
3225                 return 0;
3226         }
3227
3228         if (!c->opt_host) {
3229                 printf(_("no server to migrate\n"));
3230                 return -1;
3231         }
3232
3233         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3234                                rpc_share_migrate_shares_internals,
3235                                argc, argv);
3236 }
3237
3238 /**
3239  * Copy a file/dir
3240  *
3241  * @param f     file_info
3242  * @param mask  current search mask
3243  * @param state arg-pointer
3244  *
3245  **/
3246 static void copy_fn(const char *mnt, file_info *f,
3247                     const char *mask, void *state)
3248 {
3249         static NTSTATUS nt_status;
3250         static struct copy_clistate *local_state;
3251         static fstring filename, new_mask;
3252         fstring dir;
3253         char *old_dir;
3254         struct net_context *c;
3255
3256         local_state = (struct copy_clistate *)state;
3257         nt_status = NT_STATUS_UNSUCCESSFUL;
3258
3259         c = local_state->c;
3260
3261         if (strequal(f->name, ".") || strequal(f->name, ".."))
3262                 return;
3263
3264         DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3265
3266         /* DIRECTORY */
3267         if (f->mode & aDIR) {
3268
3269                 DEBUG(3,("got dir: %s\n", f->name));
3270
3271                 fstrcpy(dir, local_state->cwd);
3272                 fstrcat(dir, "\\");
3273                 fstrcat(dir, f->name);
3274
3275                 switch (net_mode_share)
3276                 {
3277                 case NET_MODE_SHARE_MIGRATE:
3278                         /* create that directory */
3279                         nt_status = net_copy_file(c, local_state->mem_ctx,
3280                                                   local_state->cli_share_src,
3281                                                   local_state->cli_share_dst,
3282                                                   dir, dir,
3283                                                   c->opt_acls? true : false,
3284                                                   c->opt_attrs? true : false,
3285                                                   c->opt_timestamps? true:false,
3286                                                   false);
3287                         break;
3288                 default:
3289                         d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3290                         return;
3291                 }
3292
3293                 if (!NT_STATUS_IS_OK(nt_status))
3294                         printf(_("could not handle dir %s: %s\n"),
3295                                 dir, nt_errstr(nt_status));
3296
3297                 /* search below that directory */
3298                 fstrcpy(new_mask, dir);
3299                 fstrcat(new_mask, "\\*");
3300
3301                 old_dir = local_state->cwd;
3302                 local_state->cwd = dir;
3303                 if (!sync_files(local_state, new_mask))
3304                         printf(_("could not handle files\n"));
3305                 local_state->cwd = old_dir;
3306
3307                 return;
3308         }
3309
3310
3311         /* FILE */
3312         fstrcpy(filename, local_state->cwd);
3313         fstrcat(filename, "\\");
3314         fstrcat(filename, f->name);
3315
3316         DEBUG(3,("got file: %s\n", filename));
3317
3318         switch (net_mode_share)
3319         {
3320         case NET_MODE_SHARE_MIGRATE:
3321                 nt_status = net_copy_file(c, local_state->mem_ctx,
3322                                           local_state->cli_share_src,
3323                                           local_state->cli_share_dst,
3324                                           filename, filename,
3325                                           c->opt_acls? true : false,
3326                                           c->opt_attrs? true : false,
3327                                           c->opt_timestamps? true: false,
3328                                           true);
3329                 break;
3330         default:
3331                 d_fprintf(stderr, _("Unsupported file mode %d\n"),
3332                           net_mode_share);
3333                 return;
3334         }
3335
3336         if (!NT_STATUS_IS_OK(nt_status))
3337                 printf(_("could not handle file %s: %s\n"),
3338                         filename, nt_errstr(nt_status));
3339
3340 }
3341
3342 /**
3343  * sync files, can be called recursivly to list files
3344  * and then call copy_fn for each file
3345  *
3346  * @param cp_clistate   pointer to the copy_clistate we work with
3347  * @param mask          the current search mask
3348  *
3349  * @return              Boolean result
3350  **/
3351 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask)
3352 {
3353         struct cli_state *targetcli;
3354         char *targetpath = NULL;
3355
3356         DEBUG(3,("calling cli_list with mask: %s\n", mask));
3357
3358         if ( !cli_resolve_path(talloc_tos(), "", NULL, cp_clistate->cli_share_src,
3359                                 mask, &targetcli, &targetpath ) ) {
3360                 d_fprintf(stderr, _("cli_resolve_path %s failed with error: "
3361                                     "%s\n"),
3362                         mask, cli_errstr(cp_clistate->cli_share_src));
3363                 return false;
3364         }
3365
3366         if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3367                 d_fprintf(stderr, _("listing %s failed with error: %s\n"),
3368                         mask, cli_errstr(targetcli));
3369                 return false;
3370         }
3371
3372         return true;
3373 }
3374
3375
3376 /**
3377  * Set the top level directory permissions before we do any further copies.
3378  * Should set up ACL inheritance.
3379  **/
3380
3381 bool copy_top_level_perms(struct net_context *c,
3382                                 struct copy_clistate *cp_clistate,
3383                                 const char *sharename)
3384 {
3385         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3386
3387         switch (net_mode_share) {
3388         case NET_MODE_SHARE_MIGRATE:
3389                 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3390                 nt_status = net_copy_fileattr(c,
3391                                                 cp_clistate->mem_ctx,
3392                                                 cp_clistate->cli_share_src,
3393                                                 cp_clistate->cli_share_dst,
3394                                                 "\\", "\\",
3395                                                 c->opt_acls? true : false,
3396                                                 c->opt_attrs? true : false,
3397                                                 c->opt_timestamps? true: false,
3398                                                 false);
3399                 break;
3400         default:
3401                 d_fprintf(stderr, _("Unsupported mode %d\n"), net_mode_share);
3402                 break;
3403         }
3404
3405         if (!NT_STATUS_IS_OK(nt_status))  {
3406                 printf(_("Could handle directory attributes for top level "
3407                          "directory of share %s. Error %s\n"),
3408                         sharename, nt_errstr(nt_status));
3409                 return false;
3410         }
3411
3412         return true;
3413 }
3414
3415 /**
3416  * Sync all files inside a remote share to another share (over smb).
3417  *
3418  * All parameters are provided by the run_rpc_command function, except for
3419  * argc, argv which are passed through.
3420  *
3421  * @param domain_sid The domain sid acquired from the remote server.
3422  * @param cli A cli_state connected to the server.
3423  * @param mem_ctx Talloc context, destroyed on completion of the function.
3424  * @param argc  Standard main() style argc.
3425  * @param argv  Standard main() style argv. Initial components are already
3426  *              stripped.
3427  *
3428  * @return Normal NTSTATUS return.
3429  **/
3430
3431 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
3432                                                 const DOM_SID *domain_sid,
3433                                                 const char *domain_name,
3434                                                 struct cli_state *cli,
3435                                                 struct rpc_pipe_client *pipe_hnd,
3436                                                 TALLOC_CTX *mem_ctx,
3437                                                 int argc,
3438                                                 const char **argv)
3439 {
3440         WERROR result;
3441         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3442         struct srvsvc_NetShareInfoCtr ctr_src;
3443         uint32 i;
3444         uint32 level = 502;
3445         struct copy_clistate cp_clistate;
3446         bool got_src_share = false;
3447         bool got_dst_share = false;
3448         const char *mask = "\\*";
3449         char *dst = NULL;
3450
3451         dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3452         if (dst == NULL) {
3453                 nt_status = NT_STATUS_NO_MEMORY;
3454                 goto done;
3455         }
3456
3457         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3458                                 &ctr_src);
3459
3460         if (!W_ERROR_IS_OK(result))
3461                 goto done;
3462
3463         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3464
3465                 struct srvsvc_NetShareInfo502 info502 =
3466                         ctr_src.ctr.ctr502->array[i];
3467
3468                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3469                         continue;
3470
3471                 /* one might not want to mirror whole discs :) */
3472                 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3473                         d_printf(_("skipping   [%s]: builtin/hidden share\n"),
3474                                  info502.name);
3475                         continue;
3476                 }
3477
3478                 switch (net_mode_share)
3479                 {
3480                 case NET_MODE_SHARE_MIGRATE:
3481                         printf("syncing");
3482                         break;
3483                 default:
3484                         d_fprintf(stderr, _("Unsupported mode %d\n"),
3485                                   net_mode_share);
3486                         break;
3487                 }
3488                 printf(_("    [%s] files and directories %s ACLs, %s DOS "
3489                          "Attributes %s\n"),
3490                         info502.name,
3491                         c->opt_acls ? _("including") : _("without"),
3492                         c->opt_attrs ? _("including") : _("without"),
3493                         c->opt_timestamps ? _("(preserving timestamps)") : "");
3494
3495                 cp_clistate.mem_ctx = mem_ctx;
3496                 cp_clistate.cli_share_src = NULL;
3497                 cp_clistate.cli_share_dst = NULL;
3498                 cp_clistate.cwd = NULL;
3499                 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3500                 cp_clistate.c = c;
3501
3502                 /* open share source */
3503                 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
3504                                                &cli->dest_ss, cli->desthost,
3505                                                info502.name, "A:");
3506                 if (!NT_STATUS_IS_OK(nt_status))
3507                         goto done;
3508
3509                 got_src_share = true;
3510
3511                 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3512                         /* open share destination */
3513                         nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
3514                                                        NULL, dst, info502.name, "A:");
3515                         if (!NT_STATUS_IS_OK(nt_status))
3516                                 goto done;
3517
3518                         got_dst_share = true;
3519                 }
3520
3521                 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
3522                         d_fprintf(stderr, _("Could not handle the top level "
3523                                             "directory permissions for the "
3524                                             "share: %s\n"), info502.name);
3525                         nt_status = NT_STATUS_UNSUCCESSFUL;
3526                         goto done;
3527                 }
3528
3529                 if (!sync_files(&cp_clistate, mask)) {
3530                         d_fprintf(stderr, _("could not handle files for share: "
3531                                             "%s\n"), info502.name);
3532                         nt_status = NT_STATUS_UNSUCCESSFUL;
3533                         goto done;
3534                 }
3535         }
3536
3537         nt_status = NT_STATUS_OK;
3538
3539 done:
3540
3541         if (got_src_share)
3542                 cli_shutdown(cp_clistate.cli_share_src);
3543
3544         if (got_dst_share)
3545                 cli_shutdown(cp_clistate.cli_share_dst);
3546
3547         SAFE_FREE(dst);
3548         return nt_status;
3549
3550 }
3551
3552 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
3553 {
3554         if (c->display_usage) {
3555                 d_printf(_("Usage:\n"
3556                            "net share migrate files\n"
3557                            "    Migrate files to local server\n"));
3558                 return 0;
3559         }
3560
3561         if (!c->opt_host) {
3562                 d_printf(_("no server to migrate\n"));
3563                 return -1;
3564         }
3565
3566         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3567                                rpc_share_migrate_files_internals,
3568                                argc, argv);
3569 }
3570
3571 /**
3572  * Migrate share-ACLs from a remote RPC server to the local RPC server.
3573  *
3574  * All parameters are provided by the run_rpc_command function, except for
3575  * argc, argv which are passed through.
3576  *
3577  * @param domain_sid The domain sid acquired from the remote server.
3578  * @param cli A cli_state connected to the server.
3579  * @param mem_ctx Talloc context, destroyed on completion of the function.
3580  * @param argc  Standard main() style argc.
3581  * @param argv  Standard main() style argv. Initial components are already
3582  *              stripped.
3583  *
3584  * @return Normal NTSTATUS return.
3585  **/
3586
3587 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
3588                                                 const DOM_SID *domain_sid,
3589                                                 const char *domain_name,
3590                                                 struct cli_state *cli,
3591                                                 struct rpc_pipe_client *pipe_hnd,
3592                                                 TALLOC_CTX *mem_ctx,
3593                                                 int argc,
3594                                                 const char **argv)
3595 {
3596         WERROR result;
3597         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3598         struct srvsvc_NetShareInfoCtr ctr_src;
3599         union srvsvc_NetShareInfo info;
3600         uint32 i;
3601         struct rpc_pipe_client *srvsvc_pipe = NULL;
3602         struct cli_state *cli_dst = NULL;
3603         uint32 level = 502; /* includes secdesc */
3604         uint32_t parm_error = 0;
3605
3606         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3607                                 &ctr_src);
3608
3609         if (!W_ERROR_IS_OK(result))
3610                 goto done;
3611
3612         /* connect destination PI_SRVSVC */
3613         nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3614                                      &ndr_table_srvsvc.syntax_id);
3615         if (!NT_STATUS_IS_OK(nt_status))
3616                 return nt_status;
3617
3618
3619         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3620
3621                 struct srvsvc_NetShareInfo502 info502 =
3622                         ctr_src.ctr.ctr502->array[i];
3623
3624                 /* reset error-code */
3625                 nt_status = NT_STATUS_UNSUCCESSFUL;
3626
3627                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3628                         continue;
3629
3630                 printf(_("migrating: [%s], path: %s, comment: %s, including "
3631                          "share-ACLs\n"),
3632                         info502.name, info502.path, info502.comment);
3633
3634                 if (c->opt_verbose)
3635                         display_sec_desc(info502.sd_buf.sd);
3636
3637                 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3638                 info.info502 = &info502;
3639
3640                 /* finally modify the share on the dst server */
3641                 nt_status = rpccli_srvsvc_NetShareSetInfo(srvsvc_pipe, mem_ctx,
3642                                                           srvsvc_pipe->desthost,
3643                                                           info502.name,
3644                                                           level,
3645                                                           &info,
3646                                                           &parm_error,
3647                                                           &result);
3648                 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3649                         printf(_("cannot set share-acl: %s\n"),
3650                                win_errstr(result));
3651                         goto done;
3652                 }
3653
3654         }
3655
3656         nt_status = NT_STATUS_OK;
3657
3658 done:
3659         if (cli_dst) {
3660                 cli_shutdown(cli_dst);
3661         }
3662
3663         return nt_status;
3664
3665 }
3666
3667 /**
3668  * Migrate share-acls from a RPC server to another.
3669  *
3670  * @param argc  Standard main() style argc.
3671  * @param argv  Standard main() style argv. Initial components are already
3672  *              stripped.
3673  *
3674  * @return A shell status integer (0 for success).
3675  **/
3676 static int rpc_share_migrate_security(struct net_context *c, int argc,
3677                                       const char **argv)
3678 {
3679         if (c->display_usage) {
3680                 d_printf(_("Usage:\n"
3681                            "net rpc share migrate security\n"
3682                            "    Migrate share-acls to local server\n"));
3683                 return 0;
3684         }
3685
3686         if (!c->opt_host) {
3687                 d_printf(_("no server to migrate\n"));
3688                 return -1;
3689         }
3690
3691         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3692                                rpc_share_migrate_security_internals,
3693                                argc, argv);
3694 }
3695
3696 /**
3697  * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3698  * from one server to another.
3699  *
3700  * @param argc  Standard main() style argc.
3701  * @param argv  Standard main() style argv. Initial components are already
3702  *              stripped.
3703  *
3704  * @return A shell status integer (0 for success).
3705  *
3706  **/
3707 static int rpc_share_migrate_all(struct net_context *c, int argc,
3708                                  const char **argv)
3709 {
3710         int ret;
3711
3712         if (c->display_usage) {
3713                 d_printf(_("Usage:\n"
3714                            "net rpc share migrate all\n"
3715                            "    Migrates shares including all share settings\n"));
3716                 return 0;
3717         }
3718
3719         if (!c->opt_host) {
3720                 d_printf(_("no server to migrate\n"));
3721                 return -1;
3722         }
3723
3724         /* order is important. we don't want to be locked out by the share-acl
3725          * before copying files - gd */
3726
3727         ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3728                               rpc_share_migrate_shares_internals, argc, argv);
3729         if (ret)
3730                 return ret;
3731
3732         ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3733                               rpc_share_migrate_files_internals, argc, argv);
3734         if (ret)
3735                 return ret;
3736
3737         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3738                                rpc_share_migrate_security_internals, argc,
3739                                argv);
3740 }
3741
3742
3743 /**
3744  * 'net rpc share migrate' entrypoint.
3745  * @param argc  Standard main() style argc.
3746  * @param argv  Standard main() style argv. Initial components are already
3747  *              stripped.
3748  **/
3749 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
3750 {
3751
3752         struct functable func[] = {
3753                 {
3754                         "all",
3755                         rpc_share_migrate_all,
3756                         NET_TRANSPORT_RPC,
3757                         N_("Migrate shares from remote to local server"),
3758                         N_("net rpc share migrate all\n"
3759                            "    Migrate shares from remote to local server")
3760                 },
3761                 {
3762                         "files",
3763                         rpc_share_migrate_files,
3764                         NET_TRANSPORT_RPC,
3765                         N_("Migrate files from remote to local server"),
3766                         N_("net rpc share migrate files\n"
3767                            "    Migrate files from remote to local server")
3768                 },
3769                 {
3770                         "security",
3771                         rpc_share_migrate_security,
3772                         NET_TRANSPORT_RPC,
3773                         N_("Migrate share-ACLs from remote to local server"),
3774                         N_("net rpc share migrate security\n"
3775                            "    Migrate share-ACLs from remote to local server")
3776                 },
3777                 {
3778                         "shares",
3779                         rpc_share_migrate_shares,
3780                         NET_TRANSPORT_RPC,
3781                         N_("Migrate shares from remote to local server"),
3782                         N_("net rpc share migrate shares\n"
3783                            "    Migrate shares from remote to local server")
3784                 },
3785                 {NULL, NULL, 0, NULL, NULL}
3786         };
3787
3788         net_mode_share = NET_MODE_SHARE_MIGRATE;
3789
3790         return net_run_function(c, argc, argv, "net rpc share migrate", func);
3791 }
3792
3793 struct full_alias {
3794         DOM_SID sid;
3795         uint32 num_members;
3796         DOM_SID *members;
3797 };
3798
3799 static int num_server_aliases;
3800 static struct full_alias *server_aliases;
3801
3802 /*
3803  * Add an alias to the static list.
3804  */
3805 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
3806 {
3807         if (server_aliases == NULL)
3808                 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
3809
3810         server_aliases[num_server_aliases] = *alias;
3811         num_server_aliases += 1;
3812 }
3813
3814 /*
3815  * For a specific domain on the server, fetch all the aliases
3816  * and their members. Add all of them to the server_aliases.
3817  */
3818
3819 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
3820                                         TALLOC_CTX *mem_ctx,
3821                                         struct policy_handle *connect_pol,
3822                                         const DOM_SID *domain_sid)
3823 {
3824         uint32 start_idx, max_entries, num_entries, i;
3825         struct samr_SamArray *groups = NULL;
3826         NTSTATUS result;
3827         struct policy_handle domain_pol;
3828
3829         /* Get domain policy handle */
3830
3831         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
3832                                         connect_pol,
3833                                         MAXIMUM_ALLOWED_ACCESS,
3834                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
3835                                         &domain_pol);
3836         if (!NT_STATUS_IS_OK(result))
3837                 return result;
3838
3839         start_idx = 0;
3840         max_entries = 250;
3841
3842         do {
3843                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
3844                                                        &domain_pol,
3845                                                        &start_idx,
3846                                                        &groups,
3847                                                        max_entries,
3848                                                        &num_entries);
3849                 for (i = 0; i < num_entries; i++) {
3850
3851                         struct policy_handle alias_pol;
3852                         struct full_alias alias;
3853                         struct lsa_SidArray sid_array;
3854                         int j;
3855
3856                         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
3857                                                        &domain_pol,
3858                                                        MAXIMUM_ALLOWED_ACCESS,
3859                                                        groups->entries[i].idx,
3860                                                        &alias_pol);
3861                         if (!NT_STATUS_IS_OK(result))
3862                                 goto done;
3863
3864                         result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
3865                                                                &alias_pol,
3866                                                                &sid_array);
3867                         if (!NT_STATUS_IS_OK(result))
3868                                 goto done;
3869
3870                         alias.num_members = sid_array.num_sids;
3871
3872                         result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
3873                         if (!NT_STATUS_IS_OK(result))
3874                                 goto done;
3875
3876                         alias.members = NULL;
3877
3878                         if (alias.num_members > 0) {
3879                                 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
3880
3881                                 for (j = 0; j < alias.num_members; j++)
3882                                         sid_copy(&alias.members[j],
3883                                                  sid_array.sids[j].sid);
3884                         }
3885
3886                         sid_copy(&alias.sid, domain_sid);
3887                         sid_append_rid(&alias.sid, groups->entries[i].idx);
3888
3889                         push_alias(mem_ctx, &alias);
3890                 }
3891         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
3892
3893         result = NT_STATUS_OK;
3894
3895  done:
3896         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
3897
3898         return result;
3899 }
3900
3901 /*
3902  * Dump server_aliases as names for debugging purposes.
3903  */
3904
3905 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
3906                                 const DOM_SID *domain_sid,
3907                                 const char *domain_name,
3908                                 struct cli_state *cli,
3909                                 struct rpc_pipe_client *pipe_hnd,
3910                                 TALLOC_CTX *mem_ctx,
3911                                 int argc,
3912                                 const char **argv)
3913 {
3914         int i;
3915         NTSTATUS result;
3916         struct policy_handle lsa_pol;
3917
3918         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
3919                                      SEC_FLAG_MAXIMUM_ALLOWED,
3920                                      &lsa_pol);
3921         if (!NT_STATUS_IS_OK(result))
3922                 return result;
3923
3924         for (i=0; i<num_server_aliases; i++) {
3925                 char **names;
3926                 char **domains;
3927                 enum lsa_SidType *types;
3928                 int j;
3929
3930                 struct full_alias *alias = &server_aliases[i];
3931
3932                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
3933                                              &alias->sid,
3934                                              &domains, &names, &types);
3935                 if (!NT_STATUS_IS_OK(result))
3936                         continue;
3937
3938                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
3939
3940                 if (alias->num_members == 0) {
3941                         DEBUG(1, ("\n"));
3942                         continue;
3943                 }
3944
3945                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
3946                                              alias->num_members,
3947                                              alias->members,
3948                                              &domains, &names, &types);
3949
3950                 if (!NT_STATUS_IS_OK(result) &&
3951                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
3952                         continue;
3953
3954                 for (j=0; j<alias->num_members; j++)
3955                         DEBUG(1, ("%s\\%s (%d); ",
3956                                   domains[j] ? domains[j] : "*unknown*", 
3957                                   names[j] ? names[j] : "*unknown*",types[j]));
3958                 DEBUG(1, ("\n"));
3959         }
3960
3961         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
3962
3963         return NT_STATUS_OK;
3964 }
3965
3966 /*
3967  * Fetch a list of all server aliases and their members into
3968  * server_aliases.
3969  */
3970
3971 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
3972                                         const DOM_SID *domain_sid,
3973                                         const char *domain_name,
3974                                         struct cli_state *cli,
3975                                         struct rpc_pipe_client *pipe_hnd,
3976                                         TALLOC_CTX *mem_ctx,
3977                                         int argc,
3978                                         const char **argv)
3979 {
3980         NTSTATUS result;
3981         struct policy_handle connect_pol;
3982
3983         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
3984                                       pipe_hnd->desthost,
3985                                       MAXIMUM_ALLOWED_ACCESS,
3986                                       &connect_pol);
3987
3988         if (!NT_STATUS_IS_OK(result))
3989                 goto done;
3990
3991         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
3992                                           &global_sid_Builtin);
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                                           domain_sid);
3999
4000         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
4001  done:
4002         return result;
4003 }
4004
4005 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
4006 {
4007         token->num_sids = 4;
4008
4009         if (!(token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4))) {
4010                 d_fprintf(stderr, _("malloc failed\n"));
4011                 token->num_sids = 0;
4012                 return;
4013         }
4014
4015         token->user_sids[0] = *user_sid;
4016         sid_copy(&token->user_sids[1], &global_sid_World);
4017         sid_copy(&token->user_sids[2], &global_sid_Network);
4018         sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
4019 }
4020
4021 static void free_user_token(NT_USER_TOKEN *token)
4022 {
4023         SAFE_FREE(token->user_sids);
4024 }
4025
4026 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
4027 {
4028         if (is_sid_in_token(token, sid))
4029                 return;
4030
4031         token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
4032         if (!token->user_sids) {
4033                 return;
4034         }
4035
4036         sid_copy(&token->user_sids[token->num_sids], sid);
4037
4038         token->num_sids += 1;
4039 }
4040
4041 struct user_token {
4042         fstring name;
4043         NT_USER_TOKEN token;
4044 };
4045
4046 static void dump_user_token(struct user_token *token)
4047 {
4048         int i;
4049
4050         d_printf("%s\n", token->name);
4051
4052         for (i=0; i<token->token.num_sids; i++) {
4053                 d_printf(" %s\n", sid_string_tos(&token->token.user_sids[i]));
4054         }
4055 }
4056
4057 static bool is_alias_member(DOM_SID *sid, struct full_alias *alias)
4058 {
4059         int i;
4060
4061         for (i=0; i<alias->num_members; i++) {
4062                 if (sid_compare(sid, &alias->members[i]) == 0)
4063                         return true;
4064         }
4065
4066         return false;
4067 }
4068
4069 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
4070 {
4071         int i;
4072
4073         for (i=0; i<num_server_aliases; i++) {
4074                 if (is_alias_member(&sid, &server_aliases[i]))
4075                         add_sid_to_token(token, &server_aliases[i].sid);
4076         }
4077 }
4078
4079 /*
4080  * We got a user token with all the SIDs we can know about without asking the
4081  * server directly. These are the user and domain group sids. All of these can
4082  * be members of aliases. So scan the list of aliases for each of the SIDs and
4083  * add them to the token.
4084  */
4085
4086 static void collect_alias_memberships(NT_USER_TOKEN *token)
4087 {
4088         int num_global_sids = token->num_sids;
4089         int i;
4090
4091         for (i=0; i<num_global_sids; i++) {
4092                 collect_sid_memberships(token, token->user_sids[i]);
4093         }
4094 }
4095
4096 static bool get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
4097 {
4098         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4099         enum wbcSidType type;
4100         fstring full_name;
4101         struct wbcDomainSid wsid;
4102         char *sid_str = NULL;
4103         DOM_SID user_sid;
4104         uint32_t num_groups;
4105         gid_t *groups = NULL;
4106         uint32_t i;
4107
4108         fstr_sprintf(full_name, "%s%c%s",
4109                      domain, *lp_winbind_separator(), user);
4110
4111         /* First let's find out the user sid */
4112
4113         wbc_status = wbcLookupName(domain, user, &wsid, &type);
4114
4115         if (!WBC_ERROR_IS_OK(wbc_status)) {
4116                 DEBUG(1, ("winbind could not find %s: %s\n",
4117                           full_name, wbcErrorString(wbc_status)));
4118                 return false;
4119         }
4120
4121         wbc_status = wbcSidToString(&wsid, &sid_str);
4122         if (!WBC_ERROR_IS_OK(wbc_status)) {
4123                 return false;
4124         }
4125
4126         if (type != SID_NAME_USER) {
4127                 wbcFreeMemory(sid_str);
4128                 DEBUG(1, ("%s is not a user\n", full_name));
4129                 return false;
4130         }
4131
4132         if (!string_to_sid(&user_sid, sid_str)) {
4133                 DEBUG(1,("Could not convert sid %s from string\n", sid_str));
4134                 return false;
4135         }
4136
4137         wbcFreeMemory(sid_str);
4138         sid_str = NULL;
4139
4140         init_user_token(token, &user_sid);
4141
4142         /* And now the groups winbind knows about */
4143
4144         wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4145         if (!WBC_ERROR_IS_OK(wbc_status)) {
4146                 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4147                         full_name, wbcErrorString(wbc_status)));
4148                 return false;
4149         }
4150
4151         for (i = 0; i < num_groups; i++) {
4152                 gid_t gid = groups[i];
4153                 DOM_SID sid;
4154
4155                 wbc_status = wbcGidToSid(gid, &wsid);
4156                 if (!WBC_ERROR_IS_OK(wbc_status)) {
4157                         DEBUG(1, ("winbind could not find SID of gid %u: %s\n",
4158                                   (unsigned int)gid, wbcErrorString(wbc_status)));
4159                         wbcFreeMemory(groups);
4160                         return false;
4161                 }
4162
4163                 wbc_status = wbcSidToString(&wsid, &sid_str);
4164                 if (!WBC_ERROR_IS_OK(wbc_status)) {
4165                         wbcFreeMemory(groups);
4166                         return false;
4167                 }
4168
4169                 DEBUG(3, (" %s\n", sid_str));
4170
4171                 string_to_sid(&sid, sid_str);
4172                 wbcFreeMemory(sid_str);
4173                 sid_str = NULL;
4174
4175                 add_sid_to_token(token, &sid);
4176         }
4177         wbcFreeMemory(groups);
4178
4179         return true;
4180 }
4181
4182 /**
4183  * Get a list of all user tokens we want to look at
4184  **/
4185
4186 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4187                             struct user_token **user_tokens)
4188 {
4189         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4190         uint32_t i, num_users;
4191         const char **users;
4192         struct user_token *result;
4193         TALLOC_CTX *frame = NULL;
4194
4195         if (lp_winbind_use_default_domain() &&
4196             (c->opt_target_workgroup == NULL)) {
4197                 d_fprintf(stderr, _("winbind use default domain = yes set, "
4198                          "please specify a workgroup\n"));
4199                 return false;
4200         }
4201
4202         /* Send request to winbind daemon */
4203
4204         wbc_status = wbcListUsers(NULL, &num_users, &users);
4205         if (!WBC_ERROR_IS_OK(wbc_status)) {
4206                 DEBUG(1, (_("winbind could not list users: %s\n"),
4207                           wbcErrorString(wbc_status)));
4208                 return false;
4209         }
4210
4211         result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4212
4213         if (result == NULL) {
4214                 DEBUG(1, ("Could not malloc sid array\n"));
4215                 wbcFreeMemory(users);
4216                 return false;
4217         }
4218
4219         frame = talloc_stackframe();
4220         for (i=0; i < num_users; i++) {
4221                 fstring domain, user;
4222                 char *p;
4223
4224                 fstrcpy(result[i].name, users[i]);
4225
4226                 p = strchr(users[i], *lp_winbind_separator());
4227
4228                 DEBUG(3, ("%s\n", users[i]));
4229
4230                 if (p == NULL) {
4231                         fstrcpy(domain, c->opt_target_workgroup);
4232                         fstrcpy(user, users[i]);
4233                 } else {
4234                         *p++ = '\0';
4235                         fstrcpy(domain, users[i]);
4236                         strupper_m(domain);
4237                         fstrcpy(user, p);
4238                 }
4239
4240                 get_user_sids(domain, user, &(result[i].token));
4241                 i+=1;
4242         }
4243         TALLOC_FREE(frame);
4244         wbcFreeMemory(users);
4245
4246         *num_tokens = num_users;
4247         *user_tokens = result;
4248
4249         return true;
4250 }
4251
4252 static bool get_user_tokens_from_file(FILE *f,
4253                                       int *num_tokens,
4254                                       struct user_token **tokens)
4255 {
4256         struct user_token *token = NULL;
4257
4258         while (!feof(f)) {
4259                 fstring line;
4260
4261                 if (fgets(line, sizeof(line)-1, f) == NULL) {
4262                         return true;
4263                 }
4264
4265                 if ((strlen(line) > 0) && (line[strlen(line)-1] == '\n')) {
4266                         line[strlen(line)-1] = '\0';
4267                 }
4268
4269                 if (line[0] == ' ') {
4270                         /* We have a SID */
4271
4272                         DOM_SID sid;
4273                         if(!string_to_sid(&sid, &line[1])) {
4274                                 DEBUG(1,("get_user_tokens_from_file: Could "
4275                                         "not convert sid %s \n",&line[1]));
4276                                 return false;
4277                         }
4278
4279                         if (token == NULL) {
4280                                 DEBUG(0, ("File does not begin with username"));
4281                                 return false;
4282                         }
4283
4284                         add_sid_to_token(&token->token, &sid);
4285                         continue;
4286                 }
4287
4288                 /* And a new user... */
4289
4290                 *num_tokens += 1;
4291                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4292                 if (*tokens == NULL) {
4293                         DEBUG(0, ("Could not realloc tokens\n"));
4294                         return false;
4295                 }
4296
4297                 token = &((*tokens)[*num_tokens-1]);
4298
4299                 fstrcpy(token->name, line);
4300                 token->token.num_sids = 0;
4301                 token->token.user_sids = NULL;
4302                 continue;
4303         }
4304         
4305         return false;
4306 }
4307
4308
4309 /*
4310  * Show the list of all users that have access to a share
4311  */
4312
4313 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4314                         TALLOC_CTX *mem_ctx,
4315                         const char *netname,
4316                         int num_tokens,
4317                         struct user_token *tokens)
4318 {
4319         uint16_t fnum;
4320         SEC_DESC *share_sd = NULL;
4321         SEC_DESC *root_sd = NULL;
4322         struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4323         int i;
4324         union srvsvc_NetShareInfo info;
4325         WERROR result;
4326         NTSTATUS status;
4327         uint16 cnum;
4328
4329         status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4330                                                pipe_hnd->desthost,
4331                                                netname,
4332                                                502,
4333                                                &info,
4334                                                &result);
4335
4336         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4337                 DEBUG(1, ("Coult not query secdesc for share %s\n",
4338                           netname));
4339                 return;
4340         }
4341
4342         share_sd = info.info502->sd_buf.sd;
4343         if (share_sd == NULL) {
4344                 DEBUG(1, ("Got no secdesc for share %s\n",
4345                           netname));
4346         }
4347
4348         cnum = cli->cnum;
4349
4350         if (!NT_STATUS_IS_OK(cli_tcon_andx(cli, netname, "A:", "", 0))) {
4351                 return;
4352         }
4353
4354         if (!NT_STATUS_IS_OK(cli_ntcreate(cli, "\\", 0, READ_CONTROL_ACCESS, 0,
4355                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
4356                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4357         }
4358
4359         for (i=0; i<num_tokens; i++) {
4360                 uint32 acc_granted;
4361
4362                 if (share_sd != NULL) {
4363                         status = se_access_check(share_sd, &tokens[i].token,
4364                                              1, &acc_granted);
4365
4366                         if (!NT_STATUS_IS_OK(status)) {
4367                                 DEBUG(1, ("Could not check share_sd for "
4368                                           "user %s\n",
4369                                           tokens[i].name));
4370                                 continue;
4371                         }
4372                 }
4373
4374                 if (root_sd == NULL) {
4375                         d_printf(" %s\n", tokens[i].name);
4376                         continue;
4377                 }
4378
4379                 status = se_access_check(root_sd, &tokens[i].token,
4380                                      1, &acc_granted);
4381                 if (!NT_STATUS_IS_OK(status)) {
4382                         DEBUG(1, ("Could not check root_sd for user %s\n",
4383                                   tokens[i].name));
4384                         continue;
4385                 }
4386                 d_printf(" %s\n", tokens[i].name);
4387         }
4388
4389         if (fnum != (uint16_t)-1)
4390                 cli_close(cli, fnum);
4391         cli_tdis(cli);
4392         cli->cnum = cnum;
4393         
4394         return;
4395 }
4396
4397 struct share_list {
4398         int num_shares;
4399         char **shares;
4400 };
4401
4402 static void collect_share(const char *name, uint32 m,
4403                           const char *comment, void *state)
4404 {
4405         struct share_list *share_list = (struct share_list *)state;
4406
4407         if (m != STYPE_DISKTREE)
4408                 return;
4409
4410         share_list->num_shares += 1;
4411         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4412         if (!share_list->shares) {
4413                 share_list->num_shares = 0;
4414                 return;
4415         }
4416         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4417 }
4418
4419 /**
4420  * List shares on a remote RPC server, including the security descriptors.
4421  *
4422  * All parameters are provided by the run_rpc_command function, except for
4423  * argc, argv which are passed through.
4424  *
4425  * @param domain_sid The domain sid acquired from the remote server.
4426  * @param cli A cli_state connected to the server.
4427  * @param mem_ctx Talloc context, destroyed on completion of the function.
4428  * @param argc  Standard main() style argc.
4429  * @param argv  Standard main() style argv. Initial components are already
4430  *              stripped.
4431  *
4432  * @return Normal NTSTATUS return.
4433  **/
4434
4435 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
4436                                                 const DOM_SID *domain_sid,
4437                                                 const char *domain_name,
4438                                                 struct cli_state *cli,
4439                                                 struct rpc_pipe_client *pipe_hnd,
4440                                                 TALLOC_CTX *mem_ctx,
4441                                                 int argc,
4442                                                 const char **argv)
4443 {
4444         int ret;
4445         bool r;
4446         uint32 i;
4447         FILE *f;
4448
4449         struct user_token *tokens = NULL;
4450         int num_tokens = 0;
4451
4452         struct share_list share_list;
4453
4454         if (argc == 0) {
4455                 f = stdin;
4456         } else {
4457                 f = fopen(argv[0], "r");
4458         }
4459
4460         if (f == NULL) {
4461                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4462                 return NT_STATUS_UNSUCCESSFUL;
4463         }
4464
4465         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4466
4467         if (f != stdin)
4468                 fclose(f);
4469
4470         if (!r) {
4471                 DEBUG(0, ("Could not read users from file\n"));
4472                 return NT_STATUS_UNSUCCESSFUL;
4473         }
4474
4475         for (i=0; i<num_tokens; i++)
4476                 collect_alias_memberships(&tokens[i].token);
4477
4478         share_list.num_shares = 0;
4479         share_list.shares = NULL;
4480
4481         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4482
4483         if (ret == -1) {
4484                 DEBUG(0, ("Error returning browse list: %s\n",
4485                           cli_errstr(cli)));
4486                 goto done;
4487         }
4488
4489         for (i = 0; i < share_list.num_shares; i++) {
4490                 char *netname = share_list.shares[i];
4491
4492                 if (netname[strlen(netname)-1] == '$')
4493                         continue;
4494
4495                 d_printf("%s\n", netname);
4496
4497                 show_userlist(pipe_hnd, mem_ctx, netname,
4498                               num_tokens, tokens);
4499         }
4500  done:
4501         for (i=0; i<num_tokens; i++) {
4502                 free_user_token(&tokens[i].token);
4503         }
4504         SAFE_FREE(tokens);
4505         SAFE_FREE(share_list.shares);
4506
4507         return NT_STATUS_OK;
4508 }
4509
4510 static int rpc_share_allowedusers(struct net_context *c, int argc,
4511                                   const char **argv)
4512 {
4513         int result;
4514
4515         if (c->display_usage) {
4516                 d_printf(_("Usage:\n"
4517                            "net rpc share allowedusers\n"
4518                             "    List allowed users\n"));
4519                 return 0;
4520         }
4521
4522         result = run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
4523                                  rpc_aliaslist_internals,
4524                                  argc, argv);
4525         if (result != 0)
4526                 return result;
4527
4528         result = run_rpc_command(c, NULL, &ndr_table_lsarpc.syntax_id, 0,
4529                                  rpc_aliaslist_dump,
4530                                  argc, argv);
4531         if (result != 0)
4532                 return result;
4533
4534         return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4535                                rpc_share_allowedusers_internals,
4536                                argc, argv);
4537 }
4538
4539 int net_usersidlist(struct net_context *c, int argc, const char **argv)
4540 {
4541         int num_tokens = 0;
4542         struct user_token *tokens = NULL;
4543         int i;
4544
4545         if (argc != 0) {
4546                 net_usersidlist_usage(c, argc, argv);
4547                 return 0;
4548         }
4549
4550         if (!get_user_tokens(c, &num_tokens, &tokens)) {
4551                 DEBUG(0, ("Could not get the user/sid list\n"));
4552                 return 0;
4553         }
4554
4555         for (i=0; i<num_tokens; i++) {
4556                 dump_user_token(&tokens[i]);
4557                 free_user_token(&tokens[i].token);
4558         }
4559
4560         SAFE_FREE(tokens);
4561         return 1;
4562 }
4563
4564 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
4565 {
4566         d_printf(_("net usersidlist\n"
4567                    "\tprints out a list of all users the running winbind knows\n"
4568                    "\tabout, together with all their SIDs. This is used as\n"
4569                    "\tinput to the 'net rpc share allowedusers' command.\n\n"));
4570
4571         net_common_flags_usage(c, argc, argv);
4572         return -1;
4573 }
4574
4575 /**
4576  * 'net rpc share' entrypoint.
4577  * @param argc  Standard main() style argc.
4578  * @param argv  Standard main() style argv. Initial components are already
4579  *              stripped.
4580  **/
4581
4582 int net_rpc_share(struct net_context *c, int argc, const char **argv)
4583 {
4584         NET_API_STATUS status;
4585
4586         struct functable func[] = {
4587                 {
4588                         "add",
4589                         rpc_share_add,
4590                         NET_TRANSPORT_RPC,
4591                         N_("Add share"),
4592                         N_("net rpc share add\n"
4593                            "    Add share")
4594                 },
4595                 {
4596                         "delete",
4597                         rpc_share_delete,
4598                         NET_TRANSPORT_RPC,
4599                         N_("Remove share"),
4600                         N_("net rpc share delete\n"
4601                            "    Remove share")
4602                 },
4603                 {
4604                         "allowedusers",
4605                         rpc_share_allowedusers,
4606                         NET_TRANSPORT_RPC,
4607                         N_("Modify allowed users"),
4608                         N_("net rpc share allowedusers\n"
4609                            "    Modify allowed users")
4610                 },
4611                 {
4612                         "migrate",
4613                         rpc_share_migrate,
4614                         NET_TRANSPORT_RPC,
4615                         N_("Migrate share to local server"),
4616                         N_("net rpc share migrate\n"
4617                            "    Migrate share to local server")
4618                 },
4619                 {
4620                         "list",
4621                         rpc_share_list,
4622                         NET_TRANSPORT_RPC,
4623                         N_("List shares"),
4624                         N_("net rpc share list\n"
4625                            "    List shares")
4626                 },
4627                 {NULL, NULL, 0, NULL, NULL}
4628         };
4629
4630         status = libnetapi_init(&c->netapi_ctx);
4631         if (status != 0) {
4632                 return -1;
4633         }
4634         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
4635         libnetapi_set_password(c->netapi_ctx, c->opt_password);
4636         if (c->opt_kerberos) {
4637                 libnetapi_set_use_kerberos(c->netapi_ctx);
4638         }
4639
4640         if (argc == 0) {
4641                 if (c->display_usage) {
4642                         d_printf(_("Usage:\n"
4643                                    "net rpc share\n"
4644                                    "    List shares\n"
4645                                    "    Alias for net rpc share list\n"));
4646                         net_display_usage_from_functable(func);
4647                         return 0;
4648                 }
4649
4650                 return rpc_share_list(c, argc, argv);
4651         }
4652
4653         return net_run_function(c, argc, argv, "net rpc share", func);
4654 }
4655
4656 static NTSTATUS rpc_sh_share_list(struct net_context *c,
4657                                   TALLOC_CTX *mem_ctx,
4658                                   struct rpc_sh_ctx *ctx,
4659                                   struct rpc_pipe_client *pipe_hnd,
4660                                   int argc, const char **argv)
4661 {
4662
4663         return werror_to_ntstatus(W_ERROR(rpc_share_list(c, argc, argv)));
4664 }
4665
4666 static NTSTATUS rpc_sh_share_add(struct net_context *c,
4667                                  TALLOC_CTX *mem_ctx,
4668                                  struct rpc_sh_ctx *ctx,
4669                                  struct rpc_pipe_client *pipe_hnd,
4670                                  int argc, const char **argv)
4671 {
4672         NET_API_STATUS status;
4673         uint32_t parm_err = 0;
4674         struct SHARE_INFO_2 i2;
4675
4676         if ((argc < 2) || (argc > 3)) {
4677                 d_fprintf(stderr, _("usage: %s <share> <path> [comment]\n"),
4678                           ctx->whoami);
4679                 return NT_STATUS_INVALID_PARAMETER;
4680         }
4681
4682         i2.shi2_netname         = argv[0];
4683         i2.shi2_type            = STYPE_DISKTREE;
4684         i2.shi2_remark          = (argc == 3) ? argv[2] : "";
4685         i2.shi2_permissions     = 0;
4686         i2.shi2_max_uses        = 0;
4687         i2.shi2_current_uses    = 0;
4688         i2.shi2_path            = argv[1];
4689         i2.shi2_passwd          = NULL;
4690
4691         status = NetShareAdd(pipe_hnd->desthost,
4692                              2,
4693                              (uint8_t *)&i2,
4694                              &parm_err);
4695
4696         return werror_to_ntstatus(W_ERROR(status));
4697 }
4698
4699 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
4700                                     TALLOC_CTX *mem_ctx,
4701                                     struct rpc_sh_ctx *ctx,
4702                                     struct rpc_pipe_client *pipe_hnd,
4703                                     int argc, const char **argv)
4704 {
4705         if (argc != 1) {
4706                 d_fprintf(stderr, _("usage: %s <share>\n"), ctx->whoami);
4707                 return NT_STATUS_INVALID_PARAMETER;
4708         }
4709
4710         return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd->desthost, argv[0], 0)));
4711 }
4712
4713 static NTSTATUS rpc_sh_share_info(struct net_context *c,
4714                                   TALLOC_CTX *mem_ctx,
4715                                   struct rpc_sh_ctx *ctx,
4716                                   struct rpc_pipe_client *pipe_hnd,
4717                                   int argc, const char **argv)
4718 {
4719         union srvsvc_NetShareInfo info;
4720         WERROR result;
4721         NTSTATUS status;
4722
4723         if (argc != 1) {
4724                 d_fprintf(stderr, _("usage: %s <share>\n"), ctx->whoami);
4725                 return NT_STATUS_INVALID_PARAMETER;
4726         }
4727
4728         status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4729                                                pipe_hnd->desthost,
4730                                                argv[0],
4731                                                2,
4732                                                &info,
4733                                                &result);
4734         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4735                 goto done;
4736         }
4737
4738         d_printf(_("Name:     %s\n"), info.info2->name);
4739         d_printf(_("Comment:  %s\n"), info.info2->comment);
4740         d_printf(_("Path:     %s\n"), info.info2->path);
4741         d_printf(_("Password: %s\n"), info.info2->password);
4742
4743  done:
4744         return werror_to_ntstatus(result);
4745 }
4746
4747 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
4748                                       struct rpc_sh_ctx *ctx)
4749 {
4750         static struct rpc_sh_cmd cmds[] = {
4751
4752         { "list", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_list,
4753           N_("List available shares") },
4754
4755         { "add", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_add,
4756           N_("Add a share") },
4757
4758         { "delete", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_delete,
4759           N_("Delete a share") },
4760
4761         { "info", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_info,
4762           N_("Get information about a share") },
4763
4764         { NULL, NULL, 0, NULL, NULL }
4765         };
4766
4767         return cmds;
4768 }
4769
4770 /****************************************************************************/
4771
4772 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
4773 {
4774         return net_file_usage(c, argc, argv);
4775 }
4776
4777 /**
4778  * Close a file on a remote RPC server.
4779  *
4780  * @param argc  Standard main() style argc.
4781  * @param argv  Standard main() style argv. Initial components are already
4782  *              stripped.
4783  *
4784  * @return A shell status integer (0 for success).
4785  **/
4786 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
4787 {
4788         if (argc < 1 || c->display_usage) {
4789                 return rpc_file_usage(c, argc, argv);
4790         }
4791
4792         return NetFileClose(c->opt_host, atoi(argv[0]));
4793 }
4794
4795 /**
4796  * Formatted print of open file info
4797  *
4798  * @param r  struct FILE_INFO_3 contents
4799  **/
4800
4801 static void display_file_info_3(struct FILE_INFO_3 *r)
4802 {
4803         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
4804                  r->fi3_id, r->fi3_username, r->fi3_permissions,
4805                  r->fi3_num_locks, r->fi3_pathname);
4806 }
4807
4808 /**
4809  * List files for a user on a remote RPC server.
4810  *
4811  * @param argc  Standard main() style argc.
4812  * @param argv  Standard main() style argv. Initial components are already
4813  *              stripped.
4814  *
4815  * @return A shell status integer (0 for success)..
4816  **/
4817
4818 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
4819 {
4820         NET_API_STATUS status;
4821         uint32 preferred_len = 0xffffffff, i;
4822         const char *username=NULL;
4823         uint32_t total_entries = 0;
4824         uint32_t entries_read = 0;
4825         uint32_t resume_handle = 0;
4826         struct FILE_INFO_3 *i3 = NULL;
4827
4828         if (c->display_usage) {
4829                 return rpc_file_usage(c, argc, argv);
4830         }
4831
4832         /* if argc > 0, must be user command */
4833         if (argc > 0) {
4834                 username = smb_xstrdup(argv[0]);
4835         }
4836
4837         status = NetFileEnum(c->opt_host,
4838                              NULL,
4839                              username,
4840                              3,
4841                              (uint8_t **)(void *)&i3,
4842                              preferred_len,
4843                              &entries_read,
4844                              &total_entries,
4845                              &resume_handle);
4846
4847         if (status != 0) {
4848                 goto done;
4849         }
4850
4851         /* Display results */
4852
4853         d_printf(_(
4854                  "\nEnumerating open files on remote server:\n\n"
4855                  "\nFileId  Opened by            Perms  Locks  Path"
4856                  "\n------  ---------            -----  -----  ---- \n"));
4857         for (i = 0; i < entries_read; i++) {
4858                 display_file_info_3(&i3[i]);
4859         }
4860  done:
4861         return status;
4862 }
4863
4864 /**
4865  * 'net rpc file' entrypoint.
4866  * @param argc  Standard main() style argc.
4867  * @param argv  Standard main() style argv. Initial components are already
4868  *              stripped.
4869  **/
4870
4871 int net_rpc_file(struct net_context *c, int argc, const char **argv)
4872 {
4873         NET_API_STATUS status;
4874
4875         struct functable func[] = {
4876                 {
4877                         "close",
4878                         rpc_file_close,
4879                         NET_TRANSPORT_RPC,
4880                         N_("Close opened file"),
4881                         N_("net rpc file close\n"
4882                            "    Close opened file")
4883                 },
4884                 {
4885                         "user",
4886                         rpc_file_user,
4887                         NET_TRANSPORT_RPC,
4888                         N_("List files opened by user"),
4889                         N_("net rpc file user\n"
4890                            "    List files opened by user")
4891                 },
4892 #if 0
4893                 {
4894                         "info",
4895                         rpc_file_info,
4896                         NET_TRANSPORT_RPC,
4897                         N_("Display information about opened file"),
4898                         N_("net rpc file info\n"
4899                            "    Display information about opened file")
4900                 },
4901 #endif
4902                 {NULL, NULL, 0, NULL, NULL}
4903         };
4904
4905         status = libnetapi_init(&c->netapi_ctx);
4906         if (status != 0) {
4907                 return -1;
4908         }
4909         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
4910         libnetapi_set_password(c->netapi_ctx, c->opt_password);
4911         if (c->opt_kerberos) {
4912                 libnetapi_set_use_kerberos(c->netapi_ctx);
4913         }
4914
4915         if (argc == 0) {
4916                 if (c->display_usage) {
4917                         d_printf(_("Usage:\n"));
4918                         d_printf(_("net rpc file\n"
4919                                    "    List opened files\n"));
4920                         net_display_usage_from_functable(func);
4921                         return 0;
4922                 }
4923
4924                 return rpc_file_user(c, argc, argv);
4925         }
4926
4927         return net_run_function(c, argc, argv, "net rpc file", func);
4928 }
4929
4930 /**
4931  * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
4932  *
4933  * All parameters are provided by the run_rpc_command function, except for
4934  * argc, argv which are passed through.
4935  *
4936  * @param c     A net_context structure.
4937  * @param domain_sid The domain sid acquired from the remote server.
4938  * @param cli A cli_state connected to the server.
4939  * @param mem_ctx Talloc context, destroyed on completion of the function.
4940  * @param argc  Standard main() style argc.
4941  * @param argv  Standard main() style argv. Initial components are already
4942  *              stripped.
4943  *
4944  * @return Normal NTSTATUS return.
4945  **/
4946
4947 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
4948                                         const DOM_SID *domain_sid,
4949                                         const char *domain_name,
4950                                         struct cli_state *cli,
4951                                         struct rpc_pipe_client *pipe_hnd,
4952                                         TALLOC_CTX *mem_ctx,
4953                                         int argc,
4954                                         const char **argv)
4955 {
4956         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4957
4958         result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
4959
4960         if (NT_STATUS_IS_OK(result)) {
4961                 d_printf(_("\nShutdown successfully aborted\n"));
4962                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
4963         } else
4964                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
4965
4966         return result;
4967 }
4968
4969 /**
4970  * ABORT the shutdown of a remote RPC Server, over winreg pipe.
4971  *
4972  * All parameters are provided by the run_rpc_command function, except for
4973  * argc, argv which are passed through.
4974  *
4975  * @param c     A net_context structure.
4976  * @param domain_sid The domain sid acquired from the remote server.
4977  * @param cli A cli_state connected to the server.
4978  * @param mem_ctx Talloc context, destroyed on completion of the function.
4979  * @param argc  Standard main() style argc.
4980  * @param argv  Standard main() style argv. Initial components are already
4981  *              stripped.
4982  *
4983  * @return Normal NTSTATUS return.
4984  **/
4985
4986 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
4987                                                 const DOM_SID *domain_sid,
4988                                                 const char *domain_name,
4989                                                 struct cli_state *cli,
4990                                                 struct rpc_pipe_client *pipe_hnd,
4991                                                 TALLOC_CTX *mem_ctx,
4992                                                 int argc,
4993                                                 const char **argv)
4994 {
4995         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
4996
4997         result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
4998
4999         if (NT_STATUS_IS_OK(result)) {
5000                 d_printf(_("\nShutdown successfully aborted\n"));
5001                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5002         } else
5003                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5004
5005         return result;
5006 }
5007
5008 /**
5009  * ABORT the shutdown of a remote RPC server.
5010  *
5011  * @param argc  Standard main() style argc.
5012  * @param argv  Standard main() style argv. Initial components are already
5013  *              stripped.
5014  *
5015  * @return A shell status integer (0 for success).
5016  **/
5017
5018 static int rpc_shutdown_abort(struct net_context *c, int argc,
5019                               const char **argv)
5020 {
5021         int rc = -1;
5022
5023         if (c->display_usage) {
5024                 d_printf(_("Usage:\n"
5025                            "net rpc abortshutdown\n"
5026                            "    Abort a scheduled shutdown\n"));
5027                 return 0;
5028         }
5029
5030         rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5031                              rpc_shutdown_abort_internals, argc, argv);
5032
5033         if (rc == 0)
5034                 return rc;
5035
5036         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5037
5038         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5039                                rpc_reg_shutdown_abort_internals,
5040                                argc, argv);
5041 }
5042
5043 /**
5044  * Shut down a remote RPC Server via initshutdown pipe.
5045  *
5046  * All parameters are provided by the run_rpc_command function, except for
5047  * argc, argv which are passed through.
5048  *
5049  * @param c     A net_context structure.
5050  * @param domain_sid The domain sid acquired from the remote server.
5051  * @param cli A cli_state connected to the server.
5052  * @param mem_ctx Talloc context, destroyed on completion of the function.
5053  * @param argc  Standard main() style argc.
5054  * @param argv  Standard main() style argv. Initial components are already
5055  *              stripped.
5056  *
5057  * @return Normal NTSTATUS return.
5058  **/
5059
5060 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5061                                      const DOM_SID *domain_sid,
5062                                      const char *domain_name,
5063                                      struct cli_state *cli,
5064                                      struct rpc_pipe_client *pipe_hnd,
5065                                      TALLOC_CTX *mem_ctx,
5066                                      int argc,
5067                                      const char **argv)
5068 {
5069         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5070         const char *msg = N_("This machine will be shutdown shortly");
5071         uint32 timeout = 20;
5072         struct lsa_StringLarge msg_string;
5073
5074         if (c->opt_comment) {
5075                 msg = c->opt_comment;
5076         }
5077         if (c->opt_timeout) {
5078                 timeout = c->opt_timeout;
5079         }
5080
5081         msg_string.string = msg;
5082
5083         /* create an entry */
5084         result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5085                         &msg_string, timeout, c->opt_force, c->opt_reboot,
5086                         NULL);
5087
5088         if (NT_STATUS_IS_OK(result)) {
5089                 d_printf(_("\nShutdown of remote machine succeeded\n"));
5090                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5091         } else {
5092                 DEBUG(1,("Shutdown of remote machine failed!\n"));
5093         }
5094         return result;
5095 }
5096
5097 /**
5098  * Shut down a remote RPC Server via winreg pipe.
5099  *
5100  * All parameters are provided by the run_rpc_command function, except for
5101  * argc, argv which are passed through.
5102  *
5103  * @param c     A net_context structure.
5104  * @param domain_sid The domain sid acquired from the remote server.
5105  * @param cli A cli_state connected to the server.
5106  * @param mem_ctx Talloc context, destroyed on completion of the function.
5107  * @param argc  Standard main() style argc.
5108  * @param argv  Standard main() style argv. Initial components are already
5109  *              stripped.
5110  *
5111  * @return Normal NTSTATUS return.
5112  **/
5113
5114 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5115                                     const DOM_SID *domain_sid,
5116                                     const char *domain_name,
5117                                     struct cli_state *cli,
5118                                     struct rpc_pipe_client *pipe_hnd,
5119                                     TALLOC_CTX *mem_ctx,
5120                                     int argc,
5121                                     const char **argv)
5122 {
5123         const char *msg = N_("This machine will be shutdown shortly");
5124         uint32 timeout = 20;
5125         struct lsa_StringLarge msg_string;
5126         NTSTATUS result;
5127         WERROR werr;
5128
5129         if (c->opt_comment) {
5130                 msg = c->opt_comment;
5131         }
5132         msg_string.string = msg;
5133
5134         if (c->opt_timeout) {
5135                 timeout = c->opt_timeout;
5136         }
5137
5138         /* create an entry */
5139         result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5140                         &msg_string, timeout, c->opt_force, c->opt_reboot,
5141                         &werr);
5142
5143         if (NT_STATUS_IS_OK(result)) {
5144                 d_printf(_("\nShutdown of remote machine succeeded\n"));
5145         } else {
5146                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5147                 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5148                         d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5149                 else
5150                         d_fprintf(stderr, "\nresult was: %s\n", win_errstr(werr));
5151         }
5152
5153         return result;
5154 }
5155
5156 /**
5157  * Shut down a remote RPC server.
5158  *
5159  * @param argc  Standard main() style argc.
5160  * @param argv  Standard main() style argv. Initial components are already
5161  *              stripped.
5162  *
5163  * @return A shell status integer (0 for success).
5164  **/
5165
5166 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5167 {
5168         int rc =  -1;
5169
5170         if (c->display_usage) {
5171                 d_printf(_("Usage:\n"
5172                            "net rpc shutdown\n"
5173                            "    Shut down a remote RPC server\n"));
5174                 return 0;
5175         }
5176
5177         rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5178                              rpc_init_shutdown_internals, argc, argv);
5179
5180         if (rc) {
5181                 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5182                 rc = run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5183                                      rpc_reg_shutdown_internals, argc, argv);
5184         }
5185
5186         return rc;
5187 }
5188
5189 /***************************************************************************
5190   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5191  ***************************************************************************/
5192
5193 /**
5194  * Add interdomain trust account to the RPC server.
5195  * All parameters (except for argc and argv) are passed by run_rpc_command
5196  * function.
5197  *
5198  * @param c     A net_context structure.
5199  * @param domain_sid The domain sid acquired from the server.
5200  * @param cli A cli_state connected to the server.
5201  * @param mem_ctx Talloc context, destroyed on completion of the function.
5202  * @param argc  Standard main() style argc.
5203  * @param argv  Standard main() style argv. Initial components are already
5204  *              stripped.
5205  *
5206  * @return normal NTSTATUS return code.
5207  */
5208
5209 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
5210                                                 const DOM_SID *domain_sid,
5211                                                 const char *domain_name,
5212                                                 struct cli_state *cli,
5213                                                 struct rpc_pipe_client *pipe_hnd,
5214                                                 TALLOC_CTX *mem_ctx,
5215                                                 int argc,
5216                                                 const char **argv)
5217 {
5218         struct policy_handle connect_pol, domain_pol, user_pol;
5219         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5220         char *acct_name;
5221         struct lsa_String lsa_acct_name;
5222         uint32 acb_info;
5223         uint32 acct_flags=0;
5224         uint32 user_rid;
5225         uint32_t access_granted = 0;
5226         union samr_UserInfo info;
5227         unsigned int orig_timeout;
5228
5229         if (argc != 2) {
5230                 d_printf(_("Usage: net rpc trustdom add <domain_name> "
5231                            "<trust password>\n"));
5232                 return NT_STATUS_INVALID_PARAMETER;
5233         }
5234
5235         /* 
5236          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5237          */
5238
5239         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5240                 return NT_STATUS_NO_MEMORY;
5241         }
5242
5243         strupper_m(acct_name);
5244
5245         init_lsa_String(&lsa_acct_name, acct_name);
5246
5247         /* Get samr policy handle */
5248         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5249                                       pipe_hnd->desthost,
5250                                       MAXIMUM_ALLOWED_ACCESS,
5251                                       &connect_pol);
5252         if (!NT_STATUS_IS_OK(result)) {
5253                 goto done;
5254         }
5255
5256         /* Get domain policy handle */
5257         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5258                                         &connect_pol,
5259                                         MAXIMUM_ALLOWED_ACCESS,
5260                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5261                                         &domain_pol);
5262         if (!NT_STATUS_IS_OK(result)) {
5263                 goto done;
5264         }
5265
5266         /* This call can take a long time - allow the server to time out.
5267          * 35 seconds should do it. */
5268
5269         orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5270
5271         /* Create trusting domain's account */
5272         acb_info = ACB_NORMAL;
5273         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5274                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5275                      SAMR_USER_ACCESS_SET_PASSWORD |
5276                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
5277                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
5278
5279         result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5280                                          &domain_pol,
5281                                          &lsa_acct_name,
5282                                          acb_info,
5283                                          acct_flags,
5284                                          &user_pol,
5285                                          &access_granted,
5286                                          &user_rid);
5287
5288         /* And restore our original timeout. */
5289         rpccli_set_timeout(pipe_hnd, orig_timeout);
5290
5291         if (!NT_STATUS_IS_OK(result)) {
5292                 d_printf(_("net rpc trustdom add: create user %s failed %s\n"),
5293                         acct_name, nt_errstr(result));
5294                 goto done;
5295         }
5296
5297         {
5298                 struct samr_CryptPassword crypt_pwd;
5299
5300                 ZERO_STRUCT(info.info23);
5301
5302                 init_samr_CryptPassword(argv[1],
5303                                         &cli->user_session_key,
5304                                         &crypt_pwd);
5305
5306                 info.info23.info.fields_present = SAMR_FIELD_ACCT_FLAGS |
5307                                                   SAMR_FIELD_NT_PASSWORD_PRESENT;
5308                 info.info23.info.acct_flags = ACB_DOMTRUST;
5309                 info.info23.password = crypt_pwd;
5310
5311                 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5312                                                   &user_pol,
5313                                                   23,
5314                                                   &info);
5315
5316                 if (!NT_STATUS_IS_OK(result)) {
5317                         DEBUG(0,("Could not set trust account password: %s\n",
5318                                  nt_errstr(result)));
5319                         goto done;
5320                 }
5321         }
5322
5323  done:
5324         SAFE_FREE(acct_name);
5325         return result;
5326 }
5327
5328 /**
5329  * Create interdomain trust account for a remote domain.
5330  *
5331  * @param argc Standard argc.
5332  * @param argv Standard argv without initial components.
5333  *
5334  * @return Integer status (0 means success).
5335  **/
5336
5337 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5338 {
5339         if (argc > 0 && !c->display_usage) {
5340                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5341                                        rpc_trustdom_add_internals, argc, argv);
5342         } else {
5343                 d_printf(_("Usage:\n"
5344                            "net rpc trustdom add <domain_name> <trust "
5345                            "password>\n"));
5346                 return -1;
5347         }
5348 }
5349
5350
5351 /**
5352  * Remove interdomain trust account from the RPC server.
5353  * All parameters (except for argc and argv) are passed by run_rpc_command
5354  * function.
5355  *
5356  * @param c     A net_context structure.
5357  * @param domain_sid The domain sid acquired from the server.
5358  * @param cli A cli_state connected to the server.
5359  * @param mem_ctx Talloc context, destroyed on completion of the function.
5360  * @param argc  Standard main() style argc.
5361  * @param argv  Standard main() style argv. Initial components are already
5362  *              stripped.
5363  *
5364  * @return normal NTSTATUS return code.
5365  */
5366
5367 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
5368                                         const DOM_SID *domain_sid,
5369                                         const char *domain_name,
5370                                         struct cli_state *cli,
5371                                         struct rpc_pipe_client *pipe_hnd,
5372                                         TALLOC_CTX *mem_ctx,
5373                                         int argc,
5374                                         const char **argv)
5375 {
5376         struct policy_handle connect_pol, domain_pol, user_pol;
5377         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5378         char *acct_name;
5379         DOM_SID trust_acct_sid;
5380         struct samr_Ids user_rids, name_types;
5381         struct lsa_String lsa_acct_name;
5382
5383         if (argc != 1) {
5384                 d_printf(_("Usage: net rpc trustdom del <domain_name>\n"));
5385                 return NT_STATUS_INVALID_PARAMETER;
5386         }
5387
5388         /*
5389          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5390          */
5391         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5392
5393         if (acct_name == NULL)
5394                 return NT_STATUS_NO_MEMORY;
5395
5396         strupper_m(acct_name);
5397
5398         /* Get samr policy handle */
5399         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5400                                       pipe_hnd->desthost,
5401                                       MAXIMUM_ALLOWED_ACCESS,
5402                                       &connect_pol);
5403         if (!NT_STATUS_IS_OK(result)) {
5404                 goto done;
5405         }
5406
5407         /* Get domain policy handle */
5408         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5409                                         &connect_pol,
5410                                         MAXIMUM_ALLOWED_ACCESS,
5411                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5412                                         &domain_pol);
5413         if (!NT_STATUS_IS_OK(result)) {
5414                 goto done;
5415         }
5416
5417         init_lsa_String(&lsa_acct_name, acct_name);
5418
5419         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5420                                          &domain_pol,
5421                                          1,
5422                                          &lsa_acct_name,
5423                                          &user_rids,
5424                                          &name_types);
5425
5426         if (!NT_STATUS_IS_OK(result)) {
5427                 d_printf(_("net rpc trustdom del: LookupNames on user %s "
5428                            "failed %s\n"),
5429                         acct_name, nt_errstr(result) );
5430                 goto done;
5431         }
5432
5433         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5434                                       &domain_pol,
5435                                       MAXIMUM_ALLOWED_ACCESS,
5436                                       user_rids.ids[0],
5437                                       &user_pol);
5438
5439         if (!NT_STATUS_IS_OK(result)) {
5440                 d_printf(_("net rpc trustdom del: OpenUser on user %s failed "
5441                            "%s\n"),
5442                         acct_name, nt_errstr(result) );
5443                 goto done;
5444         }
5445
5446         /* append the rid to the domain sid */
5447         sid_copy(&trust_acct_sid, domain_sid);
5448         if (!sid_append_rid(&trust_acct_sid, user_rids.ids[0])) {
5449                 goto done;
5450         }
5451
5452         /* remove the sid */
5453
5454         result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5455                                                            &user_pol,
5456                                                            &trust_acct_sid);
5457         if (!NT_STATUS_IS_OK(result)) {
5458                 d_printf(_("net rpc trustdom del: RemoveMemberFromForeignDomain"
5459                            " on user %s failed %s\n"),
5460                         acct_name, nt_errstr(result) );
5461                 goto done;
5462         }
5463
5464         /* Delete user */
5465
5466         result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5467                                         &user_pol);
5468
5469         if (!NT_STATUS_IS_OK(result)) {
5470                 d_printf(_("net rpc trustdom del: DeleteUser on user %s failed "
5471                            "%s\n"),
5472                         acct_name, nt_errstr(result) );
5473                 goto done;
5474         }
5475
5476         if (!NT_STATUS_IS_OK(result)) {
5477                 d_printf(_("Could not set trust account password: %s\n"),
5478                    nt_errstr(result));
5479                 goto done;
5480         }
5481
5482  done:
5483         return result;
5484 }
5485
5486 /**
5487  * Delete interdomain trust account for a remote domain.
5488  *
5489  * @param argc Standard argc.
5490  * @param argv Standard argv without initial components.
5491  *
5492  * @return Integer status (0 means success).
5493  **/
5494
5495 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
5496 {
5497         if (argc > 0 && !c->display_usage) {
5498                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5499                                        rpc_trustdom_del_internals, argc, argv);
5500         } else {
5501                 d_printf(_("Usage:\n"
5502                            "net rpc trustdom del <domain>\n"));
5503                 return -1;
5504         }
5505 }
5506
5507 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
5508                                      struct cli_state *cli,
5509                                      TALLOC_CTX *mem_ctx,
5510                                      const char *domain_name)
5511 {
5512         char *dc_name = NULL;
5513         const char *buffer = NULL;
5514         struct rpc_pipe_client *netr;
5515         NTSTATUS status;
5516
5517         /* Use NetServerEnum2 */
5518
5519         if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
5520                 SAFE_FREE(dc_name);
5521                 return NT_STATUS_OK;
5522         }
5523
5524         DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
5525                  for domain %s\n", domain_name));
5526
5527         /* Try netr_GetDcName */
5528
5529         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
5530                                           &netr);
5531         if (!NT_STATUS_IS_OK(status)) {
5532                 return status;
5533         }
5534
5535         status = rpccli_netr_GetDcName(netr, mem_ctx,
5536                                        cli->desthost,
5537                                        domain_name,
5538                                        &buffer,
5539                                        NULL);
5540         TALLOC_FREE(netr);
5541
5542         if (NT_STATUS_IS_OK(status)) {
5543                 return status;
5544         }
5545
5546         DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
5547                  for domain %s\n", domain_name));
5548
5549         return status;
5550 }
5551
5552 /**
5553  * Establish trust relationship to a trusting domain.
5554  * Interdomain account must already be created on remote PDC.
5555  *
5556  * @param c    A net_context structure.
5557  * @param argc Standard argc.
5558  * @param argv Standard argv without initial components.
5559  *
5560  * @return Integer status (0 means success).
5561  **/
5562
5563 static int rpc_trustdom_establish(struct net_context *c, int argc,
5564                                   const char **argv)
5565 {
5566         struct cli_state *cli = NULL;
5567         struct sockaddr_storage server_ss;
5568         struct rpc_pipe_client *pipe_hnd = NULL;
5569         struct policy_handle connect_hnd;
5570         TALLOC_CTX *mem_ctx;
5571         NTSTATUS nt_status;
5572         DOM_SID *domain_sid;
5573
5574         char* domain_name;
5575         char* acct_name;
5576         fstring pdc_name;
5577         union lsa_PolicyInformation *info = NULL;
5578
5579         /*
5580          * Connect to \\server\ipc$ as 'our domain' account with password
5581          */
5582
5583         if (argc != 1 || c->display_usage) {
5584                 d_printf(_("Usage:\n"
5585                            "net rpc trustdom establish <domain_name>\n"));
5586                 return -1;
5587         }
5588
5589         domain_name = smb_xstrdup(argv[0]);
5590         strupper_m(domain_name);
5591
5592         /* account name used at first is our domain's name with '$' */
5593         if (asprintf(&acct_name, "%s$", lp_workgroup()) == -1) {
5594                 return -1;
5595         }
5596         strupper_m(acct_name);
5597
5598         /*
5599          * opt_workgroup will be used by connection functions further,
5600          * hence it should be set to remote domain name instead of ours
5601          */
5602         if (c->opt_workgroup) {
5603                 c->opt_workgroup = smb_xstrdup(domain_name);
5604         };
5605
5606         c->opt_user_name = acct_name;
5607
5608         /* find the domain controller */
5609         if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5610                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5611                 return -1;
5612         }
5613
5614         /* connect to ipc$ as username/password */
5615         nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
5616         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5617
5618                 /* Is it trusting domain account for sure ? */
5619                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5620                         nt_errstr(nt_status)));
5621                 return -1;
5622         }
5623
5624         /* store who we connected to */
5625
5626         saf_store( domain_name, pdc_name );
5627
5628         /*
5629          * Connect to \\server\ipc$ again (this time anonymously)
5630          */
5631
5632         nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
5633                                              (char*)pdc_name);
5634
5635         if (NT_STATUS_IS_ERR(nt_status)) {
5636                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5637                         domain_name, nt_errstr(nt_status)));
5638                 return -1;
5639         }
5640
5641         if (!(mem_ctx = talloc_init("establishing trust relationship to "
5642                                     "domain %s", domain_name))) {
5643                 DEBUG(0, ("talloc_init() failed\n"));
5644                 cli_shutdown(cli);
5645                 return -1;
5646         }
5647
5648         /* Make sure we're talking to a proper server */
5649
5650         nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
5651         if (!NT_STATUS_IS_OK(nt_status)) {
5652                 cli_shutdown(cli);
5653                 talloc_destroy(mem_ctx);
5654                 return -1;
5655         }
5656
5657         /*
5658          * Call LsaOpenPolicy and LsaQueryInfo
5659          */
5660
5661         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5662                                              &pipe_hnd);
5663         if (!NT_STATUS_IS_OK(nt_status)) {
5664                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5665                 cli_shutdown(cli);
5666                 talloc_destroy(mem_ctx);
5667                 return -1;
5668         }
5669
5670         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, KEY_QUERY_VALUE,
5671                                          &connect_hnd);
5672         if (NT_STATUS_IS_ERR(nt_status)) {
5673                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5674                         nt_errstr(nt_status)));
5675                 cli_shutdown(cli);
5676                 talloc_destroy(mem_ctx);
5677                 return -1;
5678         }
5679
5680         /* Querying info level 5 */
5681
5682         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5683                                                &connect_hnd,
5684                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5685                                                &info);
5686         if (NT_STATUS_IS_ERR(nt_status)) {
5687                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5688                         nt_errstr(nt_status)));
5689                 cli_shutdown(cli);
5690                 talloc_destroy(mem_ctx);
5691                 return -1;
5692         }
5693
5694         domain_sid = info->account_domain.sid;
5695
5696         /* There should be actually query info level 3 (following nt serv behaviour),
5697            but I still don't know if it's _really_ necessary */
5698
5699         /*
5700          * Store the password in secrets db
5701          */
5702
5703         if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
5704                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5705                 cli_shutdown(cli);
5706                 talloc_destroy(mem_ctx);
5707                 return -1;
5708         }
5709
5710         /*
5711          * Close the pipes and clean up
5712          */
5713
5714         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5715         if (NT_STATUS_IS_ERR(nt_status)) {
5716                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5717                         nt_errstr(nt_status)));
5718                 cli_shutdown(cli);
5719                 talloc_destroy(mem_ctx);
5720                 return -1;
5721         }
5722
5723         cli_shutdown(cli);
5724
5725         talloc_destroy(mem_ctx);
5726
5727         d_printf(_("Trust to domain %s established\n"), domain_name);
5728         return 0;
5729 }
5730
5731 /**
5732  * Revoke trust relationship to the remote domain.
5733  *
5734  * @param c    A net_context structure.
5735  * @param argc Standard argc.
5736  * @param argv Standard argv without initial components.
5737  *
5738  * @return Integer status (0 means success).
5739  **/
5740
5741 static int rpc_trustdom_revoke(struct net_context *c, int argc,
5742                                const char **argv)
5743 {
5744         char* domain_name;
5745         int rc = -1;
5746
5747         if (argc < 1 || c->display_usage) {
5748                 d_printf(_("Usage:\n"
5749                            "net rpc trustdom revoke <domain_name>\n"
5750                            "  Revoke trust relationship\n"
5751                            "    domain_name\tName of domain to revoke trust\n"));
5752                 return -1;
5753         }
5754
5755         /* generate upper cased domain name */
5756         domain_name = smb_xstrdup(argv[0]);
5757         strupper_m(domain_name);
5758
5759         /* delete password of the trust */
5760         if (!pdb_del_trusteddom_pw(domain_name)) {
5761                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
5762                           domain_name));
5763                 goto done;
5764         };
5765
5766         rc = 0;
5767 done:
5768         SAFE_FREE(domain_name);
5769         return rc;
5770 }
5771
5772 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
5773                                         const DOM_SID *domain_sid,
5774                                         const char *domain_name,
5775                                         struct cli_state *cli,
5776                                         struct rpc_pipe_client *pipe_hnd,
5777                                         TALLOC_CTX *mem_ctx,
5778                                         int argc,
5779                                         const char **argv)
5780 {
5781         fstring str_sid;
5782         if (!sid_to_fstring(str_sid, domain_sid)) {
5783                 return NT_STATUS_UNSUCCESSFUL;
5784         }
5785         d_printf("%s\n", str_sid);
5786         return NT_STATUS_OK;
5787 }
5788
5789 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
5790 {
5791         fstring ascii_sid;
5792
5793         /* convert sid into ascii string */
5794         sid_to_fstring(ascii_sid, dom_sid);
5795
5796         d_printf("%-20s%s\n", trusted_dom_name, ascii_sid);
5797 }
5798
5799 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
5800                                       TALLOC_CTX *mem_ctx,
5801                                       struct policy_handle *pol,
5802                                       DOM_SID dom_sid,
5803                                       const char *trusted_dom_name)
5804 {
5805         NTSTATUS nt_status;
5806         union lsa_TrustedDomainInfo *info = NULL;
5807         char *cleartextpwd = NULL;
5808         uint8_t session_key[16];
5809         DATA_BLOB session_key_blob;
5810         DATA_BLOB data = data_blob_null;
5811
5812         nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
5813                                                            pol,
5814                                                            &dom_sid,
5815                                                            LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
5816                                                            &info);
5817         if (NT_STATUS_IS_ERR(nt_status)) {
5818                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5819                 nt_errstr(nt_status)));
5820                 goto done;
5821         }
5822
5823         data = data_blob(info->password.password->data,
5824                          info->password.password->length);
5825
5826         if (!rpccli_get_pwd_hash(pipe_hnd, session_key)) {
5827                 DEBUG(0, ("Could not retrieve password hash\n"));
5828                 goto done;
5829         }
5830
5831         session_key_blob = data_blob_const(session_key, sizeof(session_key));
5832         cleartextpwd = sess_decrypt_string(mem_ctx, &data, &session_key_blob);
5833
5834         if (cleartextpwd == NULL) {
5835                 DEBUG(0,("retrieved NULL password\n"));
5836                 nt_status = NT_STATUS_UNSUCCESSFUL;
5837                 goto done;
5838         }
5839
5840         if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
5841                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5842                 nt_status = NT_STATUS_UNSUCCESSFUL;
5843                 goto done;
5844         }
5845
5846 #ifdef DEBUG_PASSWORD
5847         DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
5848                    "password: [%s]\n", trusted_dom_name,
5849                    sid_string_dbg(&dom_sid), cleartextpwd));
5850 #endif
5851
5852 done:
5853         SAFE_FREE(cleartextpwd);
5854         data_blob_free(&data);
5855
5856         return nt_status;
5857 }
5858
5859 static int rpc_trustdom_vampire(struct net_context *c, int argc,
5860                                 const char **argv)
5861 {
5862         /* common variables */
5863         TALLOC_CTX* mem_ctx;
5864         struct cli_state *cli = NULL;
5865         struct rpc_pipe_client *pipe_hnd = NULL;
5866         NTSTATUS nt_status;
5867         const char *domain_name = NULL;
5868         DOM_SID *queried_dom_sid;
5869         struct policy_handle connect_hnd;
5870         union lsa_PolicyInformation *info = NULL;
5871
5872         /* trusted domains listing variables */
5873         unsigned int enum_ctx = 0;
5874         int i;
5875         struct lsa_DomainList dom_list;
5876         fstring pdc_name;
5877
5878         if (c->display_usage) {
5879                 d_printf(_("Usage:\n"
5880                            "net rpc trustdom vampire\n"
5881                            "  Vampire trust relationship from remote server\n"));
5882                 return 0;
5883         }
5884
5885         /*
5886          * Listing trusted domains (stored in secrets.tdb, if local)
5887          */
5888
5889         mem_ctx = talloc_init("trust relationships vampire");
5890
5891         /*
5892          * set domain and pdc name to local samba server (default)
5893          * or to remote one given in command line
5894          */
5895
5896         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
5897                 domain_name = c->opt_workgroup;
5898                 c->opt_target_workgroup = c->opt_workgroup;
5899         } else {
5900                 fstrcpy(pdc_name, global_myname());
5901                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
5902                 c->opt_target_workgroup = domain_name;
5903         };
5904
5905         /* open \PIPE\lsarpc and open policy handle */
5906         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
5907         if (!NT_STATUS_IS_OK(nt_status)) {
5908                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
5909                           nt_errstr(nt_status)));
5910                 talloc_destroy(mem_ctx);
5911                 return -1;
5912         };
5913
5914         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5915                                              &pipe_hnd);
5916         if (!NT_STATUS_IS_OK(nt_status)) {
5917                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
5918                         nt_errstr(nt_status) ));
5919                 cli_shutdown(cli);
5920                 talloc_destroy(mem_ctx);
5921                 return -1;
5922         };
5923
5924         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
5925                                         &connect_hnd);
5926         if (NT_STATUS_IS_ERR(nt_status)) {
5927                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5928                         nt_errstr(nt_status)));
5929                 cli_shutdown(cli);
5930                 talloc_destroy(mem_ctx);
5931                 return -1;
5932         };
5933
5934         /* query info level 5 to obtain sid of a domain being queried */
5935         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5936                                                &connect_hnd,
5937                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5938                                                &info);
5939
5940         if (NT_STATUS_IS_ERR(nt_status)) {
5941                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5942                         nt_errstr(nt_status)));
5943                 cli_shutdown(cli);
5944                 talloc_destroy(mem_ctx);
5945                 return -1;
5946         }
5947
5948         queried_dom_sid = info->account_domain.sid;
5949
5950         /*
5951          * Keep calling LsaEnumTrustdom over opened pipe until
5952          * the end of enumeration is reached
5953          */
5954
5955         d_printf(_("Vampire trusted domains:\n\n"));
5956
5957         do {
5958                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
5959                                                     &connect_hnd,
5960                                                     &enum_ctx,
5961                                                     &dom_list,
5962                                                     (uint32_t)-1);
5963                 if (NT_STATUS_IS_ERR(nt_status)) {
5964                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
5965                                 nt_errstr(nt_status)));
5966                         cli_shutdown(cli);
5967                         talloc_destroy(mem_ctx);
5968                         return -1;
5969                 };
5970
5971                 for (i = 0; i < dom_list.count; i++) {
5972
5973                         print_trusted_domain(dom_list.domains[i].sid,
5974                                              dom_list.domains[i].name.string);
5975
5976                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
5977                                                            *dom_list.domains[i].sid,
5978                                                            dom_list.domains[i].name.string);
5979                         if (!NT_STATUS_IS_OK(nt_status)) {
5980                                 cli_shutdown(cli);
5981                                 talloc_destroy(mem_ctx);
5982                                 return -1;
5983                         }
5984                 };
5985
5986                 /*
5987                  * in case of no trusted domains say something rather
5988                  * than just display blank line
5989                  */
5990                 if (!dom_list.count) d_printf(_("none\n"));
5991
5992         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
5993
5994         /* close this connection before doing next one */
5995         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
5996         if (NT_STATUS_IS_ERR(nt_status)) {
5997                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
5998                         nt_errstr(nt_status)));
5999                 cli_shutdown(cli);
6000                 talloc_destroy(mem_ctx);
6001                 return -1;
6002         };
6003
6004         /* close lsarpc pipe and connection to IPC$ */
6005         cli_shutdown(cli);
6006
6007         talloc_destroy(mem_ctx);
6008         return 0;
6009 }
6010
6011 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6012 {
6013         /* common variables */
6014         TALLOC_CTX* mem_ctx;
6015         struct cli_state *cli = NULL, *remote_cli = NULL;
6016         struct rpc_pipe_client *pipe_hnd = NULL;
6017         NTSTATUS nt_status;
6018         const char *domain_name = NULL;
6019         DOM_SID *queried_dom_sid;
6020         int ascii_dom_name_len;
6021         struct policy_handle connect_hnd;
6022         union lsa_PolicyInformation *info = NULL;
6023
6024         /* trusted domains listing variables */
6025         unsigned int num_domains, enum_ctx = 0;
6026         int i;
6027         struct lsa_DomainList dom_list;
6028         fstring pdc_name;
6029         bool found_domain;
6030
6031         /* trusting domains listing variables */
6032         struct policy_handle domain_hnd;
6033         struct samr_SamArray *trusts = NULL;
6034
6035         if (c->display_usage) {
6036                 d_printf(_("Usage:\n"
6037                            "net rpc trustdom list\n"
6038                            "    List in- and outgoing trust relationships\n"));
6039                 return 0;
6040         }
6041
6042         /*
6043          * Listing trusted domains (stored in secrets.tdb, if local)
6044          */
6045
6046         mem_ctx = talloc_init("trust relationships listing");
6047
6048         /*
6049          * set domain and pdc name to local samba server (default)
6050          * or to remote one given in command line
6051          */
6052
6053         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6054                 domain_name = c->opt_workgroup;
6055                 c->opt_target_workgroup = c->opt_workgroup;
6056         } else {
6057                 fstrcpy(pdc_name, global_myname());
6058                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6059                 c->opt_target_workgroup = domain_name;
6060         };
6061
6062         /* open \PIPE\lsarpc and open policy handle */
6063         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6064         if (!NT_STATUS_IS_OK(nt_status)) {
6065                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6066                           nt_errstr(nt_status)));
6067                 talloc_destroy(mem_ctx);
6068                 return -1;
6069         };
6070
6071         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6072                                              &pipe_hnd);
6073         if (!NT_STATUS_IS_OK(nt_status)) {
6074                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6075                         nt_errstr(nt_status) ));
6076                 cli_shutdown(cli);
6077                 talloc_destroy(mem_ctx);
6078                 return -1;
6079         };
6080
6081         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, KEY_QUERY_VALUE,
6082                                         &connect_hnd);
6083         if (NT_STATUS_IS_ERR(nt_status)) {
6084                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6085                         nt_errstr(nt_status)));
6086                 cli_shutdown(cli);
6087                 talloc_destroy(mem_ctx);
6088                 return -1;
6089         };
6090         
6091         /* query info level 5 to obtain sid of a domain being queried */
6092         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6093                                                &connect_hnd,
6094                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6095                                                &info);
6096
6097         if (NT_STATUS_IS_ERR(nt_status)) {
6098                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6099                         nt_errstr(nt_status)));
6100                 cli_shutdown(cli);
6101                 talloc_destroy(mem_ctx);
6102                 return -1;
6103         }
6104
6105         queried_dom_sid = info->account_domain.sid;
6106
6107         /*
6108          * Keep calling LsaEnumTrustdom over opened pipe until
6109          * the end of enumeration is reached
6110          */
6111
6112         d_printf(_("Trusted domains list:\n\n"));
6113
6114         found_domain = false;
6115
6116         do {
6117                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6118                                                     &connect_hnd,
6119                                                     &enum_ctx,
6120                                                     &dom_list,
6121                                                     (uint32_t)-1);
6122                 if (NT_STATUS_IS_ERR(nt_status)) {
6123                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6124                                 nt_errstr(nt_status)));
6125                         cli_shutdown(cli);
6126                         talloc_destroy(mem_ctx);
6127                         return -1;
6128                 };
6129
6130                 for (i = 0; i < dom_list.count; i++) {
6131                         print_trusted_domain(dom_list.domains[i].sid,
6132                                              dom_list.domains[i].name.string);
6133                         found_domain = true;
6134                 };
6135
6136
6137         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6138
6139         /*
6140          * in case of no trusted domains say something rather
6141          * than just display blank line
6142          */
6143         if (!found_domain) {
6144                 d_printf(_("none\n"));
6145         }
6146
6147         /* close this connection before doing next one */
6148         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6149         if (NT_STATUS_IS_ERR(nt_status)) {
6150                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6151                         nt_errstr(nt_status)));
6152                 cli_shutdown(cli);
6153                 talloc_destroy(mem_ctx);
6154                 return -1;
6155         };
6156         
6157         TALLOC_FREE(pipe_hnd);
6158
6159         /*
6160          * Listing trusting domains (stored in passdb backend, if local)
6161          */
6162         
6163         d_printf(_("\nTrusting domains list:\n\n"));
6164
6165         /*
6166          * Open \PIPE\samr and get needed policy handles
6167          */
6168         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6169                                              &pipe_hnd);
6170         if (!NT_STATUS_IS_OK(nt_status)) {
6171                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6172                 cli_shutdown(cli);
6173                 talloc_destroy(mem_ctx);
6174                 return -1;
6175         };
6176
6177         /* SamrConnect2 */
6178         nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6179                                          pipe_hnd->desthost,
6180                                          SAMR_ACCESS_LOOKUP_DOMAIN,
6181                                          &connect_hnd);
6182         if (!NT_STATUS_IS_OK(nt_status)) {
6183                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6184                         nt_errstr(nt_status)));
6185                 cli_shutdown(cli);
6186                 talloc_destroy(mem_ctx);
6187                 return -1;
6188         };
6189
6190         /* SamrOpenDomain - we have to open domain policy handle in order to be
6191            able to enumerate accounts*/
6192         nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6193                                            &connect_hnd,
6194                                            SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
6195                                            queried_dom_sid,
6196                                            &domain_hnd);
6197         if (!NT_STATUS_IS_OK(nt_status)) {
6198                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6199                         nt_errstr(nt_status)));
6200                 cli_shutdown(cli);
6201                 talloc_destroy(mem_ctx);
6202                 return -1;
6203         };
6204
6205         /*
6206          * perform actual enumeration
6207          */
6208
6209         found_domain = false;
6210
6211         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6212         do {
6213
6214                 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6215                                                         &domain_hnd,
6216                                                         &enum_ctx,
6217                                                         ACB_DOMTRUST,
6218                                                         &trusts,
6219                                                         0xffff,
6220                                                         &num_domains);
6221                 if (NT_STATUS_IS_ERR(nt_status)) {
6222                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6223                                 nt_errstr(nt_status)));
6224                         cli_shutdown(cli);
6225                         talloc_destroy(mem_ctx);
6226                         return -1;
6227                 };
6228
6229                 for (i = 0; i < num_domains; i++) {
6230
6231                         char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6232
6233                         found_domain = true;
6234
6235                         /*
6236                          * get each single domain's sid (do we _really_ need this ?):
6237                          *  1) connect to domain's pdc
6238                          *  2) query the pdc for domain's sid
6239                          */
6240
6241                         /* get rid of '$' tail */
6242                         ascii_dom_name_len = strlen(str);
6243                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6244                                 str[ascii_dom_name_len - 1] = '\0';
6245
6246                         /* set opt_* variables to remote domain */
6247                         strupper_m(str);
6248                         c->opt_workgroup = talloc_strdup(mem_ctx, str);
6249                         c->opt_target_workgroup = c->opt_workgroup;
6250
6251                         d_printf("%-20s", str);
6252
6253                         /* connect to remote domain controller */
6254                         nt_status = net_make_ipc_connection(c,
6255                                         NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6256                                         &remote_cli);
6257                         if (NT_STATUS_IS_OK(nt_status)) {
6258                                 /* query for domain's sid */
6259                                 if (run_rpc_command(
6260                                             c, remote_cli,
6261                                             &ndr_table_lsarpc.syntax_id, 0,
6262                                             rpc_query_domain_sid, argc,
6263                                             argv))
6264                                         d_printf(_("strange - couldn't get domain's sid\n"));
6265
6266                                 cli_shutdown(remote_cli);
6267
6268                         } else {
6269                                 d_fprintf(stderr, _("domain controller is not "
6270                                           "responding: %s\n"),
6271                                           nt_errstr(nt_status));
6272                                 d_printf(_("couldn't get domain's sid\n"));
6273                         }
6274                 }
6275
6276         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6277
6278         if (!found_domain) {
6279                 d_printf("none\n");
6280         }
6281
6282         /* close opened samr and domain policy handles */
6283         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6284         if (!NT_STATUS_IS_OK(nt_status)) {
6285                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6286         };
6287
6288         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6289         if (!NT_STATUS_IS_OK(nt_status)) {
6290                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6291         };
6292
6293         /* close samr pipe and connection to IPC$ */
6294         cli_shutdown(cli);
6295
6296         talloc_destroy(mem_ctx);
6297         return 0;
6298 }
6299
6300 /**
6301  * Entrypoint for 'net rpc trustdom' code.
6302  *
6303  * @param argc Standard argc.
6304  * @param argv Standard argv without initial components.
6305  *
6306  * @return Integer status (0 means success).
6307  */
6308
6309 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
6310 {
6311         struct functable func[] = {
6312                 {
6313                         "add",
6314                         rpc_trustdom_add,
6315                         NET_TRANSPORT_RPC,
6316                         N_("Add trusting domain's account"),
6317                         N_("net rpc trustdom add\n"
6318                            "    Add trusting domain's account")
6319                 },
6320                 {
6321                         "del",
6322                         rpc_trustdom_del,
6323                         NET_TRANSPORT_RPC,
6324                         N_("Remove trusting domain's account"),
6325                         N_("net rpc trustdom del\n"
6326                            "    Remove trusting domain's account")
6327                 },
6328                 {
6329                         "establish",
6330                         rpc_trustdom_establish,
6331                         NET_TRANSPORT_RPC,
6332                         N_("Establish outgoing trust relationship"),
6333                         N_("net rpc trustdom establish\n"
6334                            "    Establish outgoing trust relationship")
6335                 },
6336                 {
6337                         "revoke",
6338                         rpc_trustdom_revoke,
6339                         NET_TRANSPORT_RPC,
6340                         N_("Revoke outgoing trust relationship"),
6341                         N_("net rpc trustdom revoke\n"
6342                            "    Revoke outgoing trust relationship")
6343                 },
6344                 {
6345                         "list",
6346                         rpc_trustdom_list,
6347                         NET_TRANSPORT_RPC,
6348                         N_("List in- and outgoing domain trusts"),
6349                         N_("net rpc trustdom list\n"
6350                            "    List in- and outgoing domain trusts")
6351                 },
6352                 {
6353                         "vampire",
6354                         rpc_trustdom_vampire,
6355                         NET_TRANSPORT_RPC,
6356                         N_("Vampire trusts from remote server"),
6357                         N_("net rpc trustdom vampire\n"
6358                            "    Vampire trusts from remote server")
6359                 },
6360                 {NULL, NULL, 0, NULL, NULL}
6361         };
6362
6363         return net_run_function(c, argc, argv, "net rpc trustdom", func);
6364 }
6365
6366 /**
6367  * Check if a server will take rpc commands
6368  * @param flags Type of server to connect to (PDC, DMB, localhost)
6369  *              if the host is not explicitly specified
6370  * @return  bool (true means rpc supported)
6371  */
6372 bool net_rpc_check(struct net_context *c, unsigned flags)
6373 {
6374         struct cli_state *cli;
6375         bool ret = false;
6376         struct sockaddr_storage server_ss;
6377         char *server_name = NULL;
6378         NTSTATUS status;
6379
6380         /* flags (i.e. server type) may depend on command */
6381         if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
6382                 return false;
6383
6384         if ((cli = cli_initialise()) == NULL) {
6385                 return false;
6386         }
6387
6388         status = cli_connect(cli, server_name, &server_ss);
6389         if (!NT_STATUS_IS_OK(status))
6390                 goto done;
6391         if (!attempt_netbios_session_request(&cli, global_myname(),
6392                                              server_name, &server_ss))
6393                 goto done;
6394         status = cli_negprot(cli);
6395         if (!NT_STATUS_IS_OK(status))
6396                 goto done;
6397         if (cli->protocol < PROTOCOL_NT1)
6398                 goto done;
6399
6400         ret = true;
6401  done:
6402         cli_shutdown(cli);
6403         return ret;
6404 }
6405
6406 /* dump sam database via samsync rpc calls */
6407 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
6408         if (c->display_usage) {
6409                 d_printf(_("Usage:\n"
6410                            "net rpc samdump\n"
6411                            "    Dump remote SAM database\n"));
6412                 return 0;
6413         }
6414
6415         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6416                                NET_FLAGS_ANONYMOUS,
6417                                rpc_samdump_internals, argc, argv);
6418 }
6419
6420 /* syncronise sam database via samsync rpc calls */
6421 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
6422 {
6423         struct functable func[] = {
6424                 {
6425                         "ldif",
6426                         rpc_vampire_ldif,
6427                         NET_TRANSPORT_RPC,
6428                         N_("Dump remote SAM database to ldif"),
6429                         N_("net rpc vampire ldif\n"
6430                            "    Dump remote SAM database to LDIF file or "
6431                            "stdout")
6432                 },
6433                 {
6434                         "keytab",
6435                         rpc_vampire_keytab,
6436                         NET_TRANSPORT_RPC,
6437                         N_("Dump remote SAM database to Kerberos Keytab"),
6438                         N_("net rpc vampire keytab\n"
6439                            "    Dump remote SAM database to Kerberos keytab "
6440                            "file")
6441                 },
6442                 {
6443                         "passdb",
6444                         rpc_vampire_passdb,
6445                         NET_TRANSPORT_RPC,
6446                         N_("Dump remote SAM database to passdb"),
6447                         N_("net rpc vampire passdb\n"
6448                            "    Dump remote SAM database to passdb")
6449                 },
6450
6451                 {NULL, NULL, 0, NULL, NULL}
6452         };
6453
6454         if (argc == 0) {
6455                 if (c->display_usage) {
6456                         d_printf(_("Usage:\n"
6457                                    "net rpc vampire\n"
6458                                    "    Vampire remote SAM database\n"));
6459                         return 0;
6460                 }
6461
6462                 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6463                                        NET_FLAGS_ANONYMOUS,
6464                                        rpc_vampire_internals,
6465                                        argc, argv);
6466         }
6467
6468         return net_run_function(c, argc, argv, "net rpc vampire", func);
6469 }
6470
6471 /**
6472  * Migrate everything from a print server.
6473  *
6474  * @param c     A net_context structure.
6475  * @param argc  Standard main() style argc.
6476  * @param argv  Standard main() style argv. Initial components are already
6477  *              stripped.
6478  *
6479  * @return A shell status integer (0 for success).
6480  *
6481  * The order is important !
6482  * To successfully add drivers the print queues have to exist !
6483  * Applying ACLs should be the last step, because you're easily locked out.
6484  *
6485  **/
6486 static int rpc_printer_migrate_all(struct net_context *c, int argc,
6487                                    const char **argv)
6488 {
6489         int ret;
6490
6491         if (c->display_usage) {
6492                 d_printf(_("Usage:\n"
6493                            "net rpc printer migrate all\n"
6494                            "    Migrate everything from a print server\n"));
6495                 return 0;
6496         }
6497
6498         if (!c->opt_host) {
6499                 d_printf(_("no server to migrate\n"));
6500                 return -1;
6501         }
6502
6503         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6504                               rpc_printer_migrate_printers_internals, argc,
6505                               argv);
6506         if (ret)
6507                 return ret;
6508
6509         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6510                               rpc_printer_migrate_drivers_internals, argc,
6511                               argv);
6512         if (ret)
6513                 return ret;
6514
6515         ret = run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6516                               rpc_printer_migrate_forms_internals, argc, 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_settings_internals, argc,
6522                               argv);
6523         if (ret)
6524                 return ret;
6525
6526         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6527                                rpc_printer_migrate_security_internals, argc,
6528                                argv);
6529
6530 }
6531
6532 /**
6533  * Migrate print drivers from a print server.
6534  *
6535  * @param c     A net_context structure.
6536  * @param argc  Standard main() style argc.
6537  * @param argv  Standard main() style argv. Initial components are already
6538  *              stripped.
6539  *
6540  * @return A shell status integer (0 for success).
6541  **/
6542 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
6543                                        const char **argv)
6544 {
6545         if (c->display_usage) {
6546                 d_printf(_("Usage:\n"
6547                            "net rpc printer migrate drivers\n"
6548                            "     Migrate print-drivers from a print-server\n"));
6549                 return 0;
6550         }
6551
6552         if (!c->opt_host) {
6553                 d_printf(_("no server to migrate\n"));
6554                 return -1;
6555         }
6556
6557         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6558                                rpc_printer_migrate_drivers_internals,
6559                                argc, argv);
6560 }
6561
6562 /**
6563  * Migrate print-forms from a print-server.
6564  *
6565  * @param c     A net_context structure.
6566  * @param argc  Standard main() style argc.
6567  * @param argv  Standard main() style argv. Initial components are already
6568  *              stripped.
6569  *
6570  * @return A shell status integer (0 for success).
6571  **/
6572 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
6573                                      const char **argv)
6574 {
6575         if (c->display_usage) {
6576                 d_printf(_("Usage:\n"
6577                            "net rpc printer migrate forms\n"
6578                            "    Migrate print-forms from a print-server\n"));
6579                 return 0;
6580         }
6581
6582         if (!c->opt_host) {
6583                 d_printf(_("no server to migrate\n"));
6584                 return -1;
6585         }
6586
6587         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6588                                rpc_printer_migrate_forms_internals,
6589                                argc, argv);
6590 }
6591
6592 /**
6593  * Migrate printers from a print-server.
6594  *
6595  * @param c     A net_context structure.
6596  * @param argc  Standard main() style argc.
6597  * @param argv  Standard main() style argv. Initial components are already
6598  *              stripped.
6599  *
6600  * @return A shell status integer (0 for success).
6601  **/
6602 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
6603                                         const char **argv)
6604 {
6605         if (c->display_usage) {
6606                 d_printf(_("Usage:\n"
6607                            "net rpc printer migrate printers\n"
6608                            "    Migrate printers from a print-server\n"));
6609                 return 0;
6610         }
6611
6612         if (!c->opt_host) {
6613                 d_printf(_("no server to migrate\n"));
6614                 return -1;
6615         }
6616
6617         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6618                                rpc_printer_migrate_printers_internals,
6619                                argc, argv);
6620 }
6621
6622 /**
6623  * Migrate printer-ACLs from a print-server
6624  *
6625  * @param c     A net_context structure.
6626  * @param argc  Standard main() style argc.
6627  * @param argv  Standard main() style argv. Initial components are already
6628  *              stripped.
6629  *
6630  * @return A shell status integer (0 for success).
6631  **/
6632 static int rpc_printer_migrate_security(struct net_context *c, int argc,
6633                                         const char **argv)
6634 {
6635         if (c->display_usage) {
6636                 d_printf(_("Usage:\n"
6637                            "net rpc printer migrate security\n"
6638                            "    Migrate printer-ACLs from a print-server\n"));
6639                 return 0;
6640         }
6641
6642         if (!c->opt_host) {
6643                 d_printf(_("no server to migrate\n"));
6644                 return -1;
6645         }
6646
6647         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6648                                rpc_printer_migrate_security_internals,
6649                                argc, argv);
6650 }
6651
6652 /**
6653  * Migrate printer-settings from a print-server.
6654  *
6655  * @param c     A net_context structure.
6656  * @param argc  Standard main() style argc.
6657  * @param argv  Standard main() style argv. Initial components are already
6658  *              stripped.
6659  *
6660  * @return A shell status integer (0 for success).
6661  **/
6662 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
6663                                         const char **argv)
6664 {
6665         if (c->display_usage) {
6666                 d_printf(_("Usage:\n"
6667                            "net rpc printer migrate settings\n"
6668                             "    Migrate printer-settings from a "
6669                             "print-server\n"));
6670                 return 0;
6671         }
6672
6673         if (!c->opt_host) {
6674                 d_printf(_("no server to migrate\n"));
6675                 return -1;
6676         }
6677
6678         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6679                                rpc_printer_migrate_settings_internals,
6680                                argc, argv);
6681 }
6682
6683 /**
6684  * 'net rpc printer' entrypoint.
6685  *
6686  * @param c     A net_context structure.
6687  * @param argc  Standard main() style argc.
6688  * @param argv  Standard main() style argv. Initial components are already
6689  *              stripped.
6690  **/
6691
6692 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
6693 {
6694
6695         /* ouch: when addriver and setdriver are called from within
6696            rpc_printer_migrate_drivers_internals, the printer-queue already
6697            *has* to exist */
6698
6699         struct functable func[] = {
6700                 {
6701                         "all",
6702                         rpc_printer_migrate_all,
6703                         NET_TRANSPORT_RPC,
6704                         N_("Migrate all from remote to local print server"),
6705                         N_("net rpc printer migrate all\n"
6706                            "    Migrate all from remote to local print server")
6707                 },
6708                 {
6709                         "drivers",
6710                         rpc_printer_migrate_drivers,
6711                         NET_TRANSPORT_RPC,
6712                         N_("Migrate drivers to local server"),
6713                         N_("net rpc printer migrate drivers\n"
6714                            "    Migrate drivers to local server")
6715                 },
6716                 {
6717                         "forms",
6718                         rpc_printer_migrate_forms,
6719                         NET_TRANSPORT_RPC,
6720                         N_("Migrate froms to local server"),
6721                         N_("net rpc printer migrate forms\n"
6722                            "    Migrate froms to local server")
6723                 },
6724                 {
6725                         "printers",
6726                         rpc_printer_migrate_printers,
6727                         NET_TRANSPORT_RPC,
6728                         N_("Migrate printers to local server"),
6729                         N_("net rpc printer migrate printers\n"
6730                            "    Migrate printers to local server")
6731                 },
6732                 {
6733                         "security",
6734                         rpc_printer_migrate_security,
6735                         NET_TRANSPORT_RPC,
6736                         N_("Mirgate printer ACLs to local server"),
6737                         N_("net rpc printer migrate security\n"
6738                            "    Mirgate printer ACLs to local server")
6739                 },
6740                 {
6741                         "settings",
6742                         rpc_printer_migrate_settings,
6743                         NET_TRANSPORT_RPC,
6744                         N_("Migrate printer settings to local server"),
6745                         N_("net rpc printer migrate settings\n"
6746                            "    Migrate printer settings to local server")
6747                 },
6748                 {NULL, NULL, 0, NULL, NULL}
6749         };
6750
6751         return net_run_function(c, argc, argv, "net rpc printer migrate",func);
6752 }
6753
6754
6755 /**
6756  * List printers on a remote RPC server.
6757  *
6758  * @param c     A net_context structure.
6759  * @param argc  Standard main() style argc.
6760  * @param argv  Standard main() style argv. Initial components are already
6761  *              stripped.
6762  *
6763  * @return A shell status integer (0 for success).
6764  **/
6765 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
6766 {
6767         if (c->display_usage) {
6768                 d_printf(_("Usage:\n"
6769                            "net rpc printer list\n"
6770                            "    List printers on a remote RPC server\n"));
6771                 return 0;
6772         }
6773
6774         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6775                                rpc_printer_list_internals,
6776                                argc, argv);
6777 }
6778
6779 /**
6780  * List printer-drivers on a remote RPC server.
6781  *
6782  * @param c     A net_context structure.
6783  * @param argc  Standard main() style argc.
6784  * @param argv  Standard main() style argv. Initial components are already
6785  *              stripped.
6786  *
6787  * @return A shell status integer (0 for success).
6788  **/
6789 static int rpc_printer_driver_list(struct net_context *c, int argc,
6790                                    const char **argv)
6791 {
6792         if (c->display_usage) {
6793                 d_printf(_("Usage:\n"
6794                            "net rpc printer driver\n"
6795                            "    List printer-drivers on a remote RPC server\n"));
6796                 return 0;
6797         }
6798
6799         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6800                                rpc_printer_driver_list_internals,
6801                                argc, argv);
6802 }
6803
6804 /**
6805  * Publish printer in ADS via MSRPC.
6806  *
6807  * @param c     A net_context structure.
6808  * @param argc  Standard main() style argc.
6809  * @param argv  Standard main() style argv. Initial components are already
6810  *              stripped.
6811  *
6812  * @return A shell status integer (0 for success).
6813  **/
6814 static int rpc_printer_publish_publish(struct net_context *c, int argc,
6815                                        const char **argv)
6816 {
6817         if (c->display_usage) {
6818                 d_printf(_("Usage:\n"
6819                            "net rpc printer publish publish\n"
6820                            "     Publish printer in ADS via MSRPC\n"));
6821                 return 0;
6822         }
6823
6824         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6825                                rpc_printer_publish_publish_internals,
6826                                argc, argv);
6827 }
6828
6829 /**
6830  * Update printer in ADS via MSRPC.
6831  *
6832  * @param c     A net_context structure.
6833  * @param argc  Standard main() style argc.
6834  * @param argv  Standard main() style argv. Initial components are already
6835  *              stripped.
6836  *
6837  * @return A shell status integer (0 for success).
6838  **/
6839 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
6840 {
6841         if (c->display_usage) {
6842                 d_printf(_("Usage:\n"
6843                            "net rpc printer publish update\n"
6844                            "    Update printer in ADS via MSRPC\n"));
6845                 return 0;
6846         }
6847
6848         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6849                                rpc_printer_publish_update_internals,
6850                                argc, argv);
6851 }
6852
6853 /**
6854  * UnPublish printer in ADS via MSRPC.
6855  *
6856  * @param c     A net_context structure.
6857  * @param argc  Standard main() style argc.
6858  * @param argv  Standard main() style argv. Initial components are already
6859  *              stripped.
6860  *
6861  * @return A shell status integer (0 for success).
6862  **/
6863 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
6864                                          const char **argv)
6865 {
6866         if (c->display_usage) {
6867                 d_printf(_("Usage:\n"
6868                            "net rpc printer publish unpublish\n"
6869                            "    UnPublish printer in ADS via MSRPC\n"));
6870                 return 0;
6871         }
6872
6873         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6874                                rpc_printer_publish_unpublish_internals,
6875                                argc, argv);
6876 }
6877
6878 /**
6879  * List published printers via MSRPC.
6880  *
6881  * @param c     A net_context structure.
6882  * @param argc  Standard main() style argc.
6883  * @param argv  Standard main() style argv. Initial components are already
6884  *              stripped.
6885  *
6886  * @return A shell status integer (0 for success).
6887  **/
6888 static int rpc_printer_publish_list(struct net_context *c, int argc,
6889                                     const char **argv)
6890 {
6891         if (c->display_usage) {
6892                 d_printf(_("Usage:\n"
6893                            "net rpc printer publish list\n"
6894                            "    List published printers via MSRPC\n"));
6895                 return 0;
6896         }
6897
6898         return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6899                                rpc_printer_publish_list_internals,
6900                                argc, argv);
6901 }
6902
6903
6904 /**
6905  * Publish printer in ADS.
6906  *
6907  * @param c     A net_context structure.
6908  * @param argc  Standard main() style argc.
6909  * @param argv  Standard main() style argv. Initial components are already
6910  *              stripped.
6911  *
6912  * @return A shell status integer (0 for success).
6913  **/
6914 static int rpc_printer_publish(struct net_context *c, int argc,
6915                                const char **argv)
6916 {
6917
6918         struct functable func[] = {
6919                 {
6920                         "publish",
6921                         rpc_printer_publish_publish,
6922                         NET_TRANSPORT_RPC,
6923                         N_("Publish printer in AD"),
6924                         N_("net rpc printer publish publish\n"
6925                            "    Publish printer in AD")
6926                 },
6927                 {
6928                         "update",
6929                         rpc_printer_publish_update,
6930                         NET_TRANSPORT_RPC,
6931                         N_("Update printer in AD"),
6932                         N_("net rpc printer publish update\n"
6933                            "    Update printer in AD")
6934                 },
6935                 {
6936                         "unpublish",
6937                         rpc_printer_publish_unpublish,
6938                         NET_TRANSPORT_RPC,
6939                         N_("Unpublish printer"),
6940                         N_("net rpc printer publish unpublish\n"
6941                            "    Unpublish printer")
6942                 },
6943                 {
6944                         "list",
6945                         rpc_printer_publish_list,
6946                         NET_TRANSPORT_RPC,
6947                         N_("List published printers"),
6948                         N_("net rpc printer publish list\n"
6949                            "    List published printers")
6950                 },
6951                 {NULL, NULL, 0, NULL, NULL}
6952         };
6953
6954         if (argc == 0) {
6955                 if (c->display_usage) {
6956                         d_printf(_("Usage:\n"));
6957                         d_printf(_("net rpc printer publish\n"
6958                                    "    List published printers\n"
6959                                    "    Alias of net rpc printer publish "
6960                                    "list\n"));
6961                         net_display_usage_from_functable(func);
6962                         return 0;
6963                 }
6964                 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
6965                                rpc_printer_publish_list_internals,
6966                                argc, argv);
6967         }
6968
6969         return net_run_function(c, argc, argv, "net rpc printer publish",func);
6970
6971 }
6972
6973
6974 /**
6975  * Display rpc printer help page.
6976  *
6977  * @param c     A net_context structure.
6978  * @param argc  Standard main() style argc.
6979  * @param argv  Standard main() style argv. Initial components are already
6980  *              stripped.
6981  **/
6982 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
6983 {
6984         d_printf(_("net rpc printer LIST [printer] [misc. options] [targets]\n"
6985                    "\tlists all printers on print-server\n\n"));
6986         d_printf(_("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
6987                    "\tlists all printer-drivers on print-server\n\n"));
6988         d_printf(_("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
6989                    "\tpublishes printer settings in Active Directory\n"
6990                    "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n"));
6991         d_printf(_("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
6992                    "\n\tmigrates printers from remote to local server\n\n"));
6993         d_printf(_("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
6994                    "\n\tmigrates printer-settings from remote to local server\n\n"));
6995         d_printf(_("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
6996                    "\n\tmigrates printer-drivers from remote to local server\n\n"));
6997         d_printf(_("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
6998                    "\n\tmigrates printer-forms from remote to local server\n\n"));
6999         d_printf(_("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
7000                    "\n\tmigrates printer-ACLs from remote to local server\n\n"));
7001         d_printf(_("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
7002                    "\n\tmigrates drivers, forms, queues, settings and acls from\n"
7003                    "\tremote to local print-server\n\n"));
7004         net_common_methods_usage(c, argc, argv);
7005         net_common_flags_usage(c, argc, argv);
7006         d_printf(_(
7007          "\t-v or --verbose\t\t\tgive verbose output\n"
7008          "\t      --destination\t\tmigration target server (default: localhost)\n"));
7009
7010         return -1;
7011 }
7012
7013 /**
7014  * 'net rpc printer' entrypoint.
7015  *
7016  * @param c     A net_context structure.
7017  * @param argc  Standard main() style argc.
7018  * @param argv  Standard main() style argv. Initial components are already
7019  *              stripped.
7020  **/
7021 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7022 {
7023         struct functable func[] = {
7024                 {
7025                         "list",
7026                         rpc_printer_list,
7027                         NET_TRANSPORT_RPC,
7028                         N_("List all printers on print server"),
7029                         N_("net rpc printer list\n"
7030                            "    List all printers on print server")
7031                 },
7032                 {
7033                         "migrate",
7034                         rpc_printer_migrate,
7035                         NET_TRANSPORT_RPC,
7036                         N_("Migrate printer to local server"),
7037                         N_("net rpc printer migrate\n"
7038                            "    Migrate printer to local server")
7039                 },
7040                 {
7041                         "driver",
7042                         rpc_printer_driver_list,
7043                         NET_TRANSPORT_RPC,
7044                         N_("List printer drivers"),
7045                         N_("net rpc printer driver\n"
7046                            "    List printer drivers")
7047                 },
7048                 {
7049                         "publish",
7050                         rpc_printer_publish,
7051                         NET_TRANSPORT_RPC,
7052                         N_("Publish printer in AD"),
7053                         N_("net rpc printer publish\n"
7054                            "    Publish printer in AD")
7055                 },
7056                 {NULL, NULL, 0, NULL, NULL}
7057         };
7058
7059         if (argc == 0) {
7060                 if (c->display_usage) {
7061                         d_printf(_("Usage:\n"));
7062                         d_printf(_("net rpc printer\n"
7063                                    "    List printers\n"));
7064                         net_display_usage_from_functable(func);
7065                         return 0;
7066                 }
7067                 return run_rpc_command(c, NULL, &ndr_table_spoolss.syntax_id, 0,
7068                                rpc_printer_list_internals,
7069                                argc, argv);
7070         }
7071
7072         return net_run_function(c, argc, argv, "net rpc printer", func);
7073 }
7074
7075 /**
7076  * 'net rpc' entrypoint.
7077  *
7078  * @param c     A net_context structure.
7079  * @param argc  Standard main() style argc.
7080  * @param argv  Standard main() style argv. Initial components are already
7081  *              stripped.
7082  **/
7083
7084 int net_rpc(struct net_context *c, int argc, const char **argv)
7085 {
7086         NET_API_STATUS status;
7087
7088         struct functable func[] = {
7089                 {
7090                         "audit",
7091                         net_rpc_audit,
7092                         NET_TRANSPORT_RPC,
7093                         N_("Modify global audit settings"),
7094                         N_("net rpc audit\n"
7095                            "    Modify global audit settings")
7096                 },
7097                 {
7098                         "info",
7099                         net_rpc_info,
7100                         NET_TRANSPORT_RPC,
7101                         N_("Show basic info about a domain"),
7102                         N_("net rpc info\n"
7103                            "    Show basic info about a domain")
7104                 },
7105                 {
7106                         "join",
7107                         net_rpc_join,
7108                         NET_TRANSPORT_RPC,
7109                         N_("Join a domain"),
7110                         N_("net rpc join\n"
7111                            "    Join a domain")
7112                 },
7113                 {
7114                         "oldjoin",
7115                         net_rpc_oldjoin,
7116                         NET_TRANSPORT_RPC,
7117                         N_("Join a domain created in server manager"),
7118                         N_("net rpc oldjoin\n"
7119                            "    Join a domain created in server manager")
7120                 },
7121                 {
7122                         "testjoin",
7123                         net_rpc_testjoin,
7124                         NET_TRANSPORT_RPC,
7125                         N_("Test that a join is valid"),
7126                         N_("net rpc testjoin\n"
7127                            "    Test that a join is valid")
7128                 },
7129                 {
7130                         "user",
7131                         net_rpc_user,
7132                         NET_TRANSPORT_RPC,
7133                         N_("List/modify users"),
7134                         N_("net rpc user\n"
7135                            "    List/modify users")
7136                 },
7137                 {
7138                         "password",
7139                         rpc_user_password,
7140                         NET_TRANSPORT_RPC,
7141                         N_("Change a user password"),
7142                         N_("net rpc password\n"
7143                            "    Change a user password\n"
7144                            "    Alias for net rpc user password")
7145                 },
7146                 {
7147                         "group",
7148                         net_rpc_group,
7149                         NET_TRANSPORT_RPC,
7150                         N_("List/modify groups"),
7151                         N_("net rpc group\n"
7152                            "    List/modify groups")
7153                 },
7154                 {
7155                         "share",
7156                         net_rpc_share,
7157                         NET_TRANSPORT_RPC,
7158                         N_("List/modify shares"),
7159                         N_("net rpc share\n"
7160                            "    List/modify shares")
7161                 },
7162                 {
7163                         "file",
7164                         net_rpc_file,
7165                         NET_TRANSPORT_RPC,
7166                         N_("List open files"),
7167                         N_("net rpc file\n"
7168                            "    List open files")
7169                 },
7170                 {
7171                         "printer",
7172                         net_rpc_printer,
7173                         NET_TRANSPORT_RPC,
7174                         N_("List/modify printers"),
7175                         N_("net rpc printer\n"
7176                            "    List/modify printers")
7177                 },
7178                 {
7179                         "changetrustpw",
7180                         net_rpc_changetrustpw,
7181                         NET_TRANSPORT_RPC,
7182                         N_("Change trust account password"),
7183                         N_("net rpc changetrustpw\n"
7184                            "    Change trust account password")
7185                 },
7186                 {
7187                         "trustdom",
7188                         rpc_trustdom,
7189                         NET_TRANSPORT_RPC,
7190                         N_("Modify domain trusts"),
7191                         N_("net rpc trustdom\n"
7192                            "    Modify domain trusts")
7193                 },
7194                 {
7195                         "abortshutdown",
7196                         rpc_shutdown_abort,
7197                         NET_TRANSPORT_RPC,
7198                         N_("Abort a remote shutdown"),
7199                         N_("net rpc abortshutdown\n"
7200                            "    Abort a remote shutdown")
7201                 },
7202                 {
7203                         "shutdown",
7204                         rpc_shutdown,
7205                         NET_TRANSPORT_RPC,
7206                         N_("Shutdown a remote server"),
7207                         N_("net rpc shutdown\n"
7208                            "    Shutdown a remote server")
7209                 },
7210                 {
7211                         "samdump",
7212                         rpc_samdump,
7213                         NET_TRANSPORT_RPC,
7214                         N_("Dump SAM data of remote NT PDC"),
7215                         N_("net rpc samdump\n"
7216                            "    Dump SAM data of remote NT PDC")
7217                 },
7218                 {
7219                         "vampire",
7220                         rpc_vampire,
7221                         NET_TRANSPORT_RPC,
7222                         N_("Sync a remote NT PDC's data into local passdb"),
7223                         N_("net rpc vampire\n"
7224                            "    Sync a remote NT PDC's data into local passdb")
7225                 },
7226                 {
7227                         "getsid",
7228                         net_rpc_getsid,
7229                         NET_TRANSPORT_RPC,
7230                         N_("Fetch the domain sid into local secrets.tdb"),
7231                         N_("net rpc getsid\n"
7232                            "    Fetch the domain sid into local secrets.tdb")
7233                 },
7234                 {
7235                         "rights",
7236                         net_rpc_rights,
7237                         NET_TRANSPORT_RPC,
7238                         N_("Manage privileges assigned to SID"),
7239                         N_("net rpc rights\n"
7240                            "    Manage privileges assigned to SID")
7241                 },
7242                 {
7243                         "service",
7244                         net_rpc_service,
7245                         NET_TRANSPORT_RPC,
7246                         N_("Start/stop/query remote services"),
7247                         N_("net rpc service\n"
7248                            "    Start/stop/query remote services")
7249                 },
7250                 {
7251                         "registry",
7252                         net_rpc_registry,
7253                         NET_TRANSPORT_RPC,
7254                         N_("Manage registry hives"),
7255                         N_("net rpc registry\n"
7256                            "    Manage registry hives")
7257                 },
7258                 {
7259                         "shell",
7260                         net_rpc_shell,
7261                         NET_TRANSPORT_RPC,
7262                         N_("Open interactive shell on remote server"),
7263                         N_("net rpc shell\n"
7264                            "    Open interactive shell on remote server")
7265                 },
7266                 {NULL, NULL, 0, NULL, NULL}
7267         };
7268
7269         status = libnetapi_init(&c->netapi_ctx);
7270         if (status != 0) {
7271                 return -1;
7272         }
7273         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
7274         libnetapi_set_password(c->netapi_ctx, c->opt_password);
7275         if (c->opt_kerberos) {
7276                 libnetapi_set_use_kerberos(c->netapi_ctx);
7277         }
7278
7279         return net_run_function(c, argc, argv, "net rpc", func);
7280 }