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