7481c43ea0f915c81e5dbfa8f72b3f21d457c818
[samba.git] / source3 / utils / net_rpc.c
1 /*
2    Samba Unix/Linux SMB client library
3    Distributed SMB/CIFS Server Management Utility
4    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
6    Copyright (C) 2004,2008 Guenther Deschner (gd@samba.org)
7    Copyright (C) 2005 Jeremy Allison (jra@samba.org)
8    Copyright (C) 2006 Jelmer Vernooij (jelmer@samba.org)
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
23 #include "includes.h"
24 #include "utils/net.h"
25 #include "../libcli/auth/libcli_auth.h"
26 #include "../librpc/gen_ndr/ndr_samr_c.h"
27 #include "rpc_client/cli_samr.h"
28 #include "rpc_client/init_samr.h"
29 #include "../librpc/gen_ndr/ndr_lsa_c.h"
30 #include "rpc_client/cli_lsarpc.h"
31 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
33 #include "../librpc/gen_ndr/ndr_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_initshutdown_c.h"
35 #include "../librpc/gen_ndr/ndr_winreg_c.h"
36 #include "secrets.h"
37 #include "lib/netapi/netapi.h"
38 #include "lib/netapi/netapi_net.h"
39 #include "rpc_client/init_lsa.h"
40 #include "../libcli/security/security.h"
41
42 static int net_mode_share;
43 static NTSTATUS sync_files(struct copy_clistate *cp_clistate, const char *mask);
44
45 /**
46  * @file net_rpc.c
47  *
48  * @brief RPC based subcommands for the 'net' utility.
49  *
50  * This file should contain much of the functionality that used to
51  * be found in rpcclient, execpt that the commands should change
52  * less often, and the fucntionality should be sane (the user is not
53  * expected to know a rid/sid before they conduct an operation etc.)
54  *
55  * @todo Perhaps eventually these should be split out into a number
56  * of files, as this could get quite big.
57  **/
58
59
60 /**
61  * Many of the RPC functions need the domain sid.  This function gets
62  *  it at the start of every run
63  *
64  * @param cli A cli_state already connected to the remote machine
65  *
66  * @return The Domain SID of the remote machine.
67  **/
68
69 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
70                                    struct dom_sid **domain_sid,
71                                    const char **domain_name)
72 {
73         struct rpc_pipe_client *lsa_pipe = NULL;
74         struct policy_handle pol;
75         NTSTATUS status, result;
76         union lsa_PolicyInformation *info = NULL;
77         struct dcerpc_binding_handle *b;
78
79         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
80                                           &lsa_pipe);
81         if (!NT_STATUS_IS_OK(status)) {
82                 d_fprintf(stderr, _("Could not initialise lsa pipe\n"));
83                 return status;
84         }
85
86         b = lsa_pipe->binding_handle;
87
88         status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
89                                      SEC_FLAG_MAXIMUM_ALLOWED,
90                                      &pol);
91         if (!NT_STATUS_IS_OK(status)) {
92                 d_fprintf(stderr, "open_policy %s: %s\n",
93                           _("failed"),
94                           nt_errstr(status));
95                 return status;
96         }
97
98         status = dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
99                                             &pol,
100                                             LSA_POLICY_INFO_ACCOUNT_DOMAIN,
101                                             &info,
102                                             &result);
103         if (!NT_STATUS_IS_OK(status)) {
104                 d_fprintf(stderr, "lsaquery %s: %s\n",
105                           _("failed"),
106                           nt_errstr(status));
107                 return status;
108         }
109         if (!NT_STATUS_IS_OK(result)) {
110                 d_fprintf(stderr, "lsaquery %s: %s\n",
111                           _("failed"),
112                           nt_errstr(result));
113                 return result;
114         }
115
116         *domain_name = info->account_domain.name.string;
117         *domain_sid = info->account_domain.sid;
118
119         dcerpc_lsa_Close(b, mem_ctx, &pol, &result);
120         TALLOC_FREE(lsa_pipe);
121
122         return NT_STATUS_OK;
123 }
124
125 /**
126  * Run a single RPC command, from start to finish.
127  *
128  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
129  * @param conn_flag a NET_FLAG_ combination.  Passed to
130  *                   net_make_ipc_connection.
131  * @param argc  Standard main() style argc.
132  * @param argv  Standard main() style argv. Initial components are already
133  *              stripped.
134  * @return A shell status integer (0 for success).
135  */
136
137 int run_rpc_command(struct net_context *c,
138                         struct cli_state *cli_arg,
139                         const struct ndr_syntax_id *interface,
140                         int conn_flags,
141                         rpc_command_fn fn,
142                         int argc,
143                         const char **argv)
144 {
145         struct cli_state *cli = NULL;
146         struct rpc_pipe_client *pipe_hnd = NULL;
147         TALLOC_CTX *mem_ctx;
148         NTSTATUS nt_status;
149         struct dom_sid *domain_sid;
150         const char *domain_name;
151         int ret = -1;
152
153         /* make use of cli_state handed over as an argument, if possible */
154         if (!cli_arg) {
155                 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
156                 if (!NT_STATUS_IS_OK(nt_status)) {
157                         DEBUG(1, ("failed to make ipc connection: %s\n",
158                                   nt_errstr(nt_status)));
159                         return -1;
160                 }
161         } else {
162                 cli = cli_arg;
163         }
164
165         if (!cli) {
166                 return -1;
167         }
168
169         /* Create mem_ctx */
170
171         if (!(mem_ctx = talloc_init("run_rpc_command"))) {
172                 DEBUG(0, ("talloc_init() failed\n"));
173                 goto fail;
174         }
175
176         nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
177                                               &domain_name);
178         if (!NT_STATUS_IS_OK(nt_status)) {
179                 goto fail;
180         }
181
182         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
183                 if (lp_client_schannel()
184                     && (ndr_syntax_id_equal(interface,
185                                             &ndr_table_netlogon.syntax_id))) {
186                         /* Always try and create an schannel netlogon pipe. */
187                         nt_status = cli_rpc_pipe_open_schannel(
188                                 cli, interface, NCACN_NP,
189                                 DCERPC_AUTH_LEVEL_PRIVACY, domain_name,
190                                 &pipe_hnd);
191                         if (!NT_STATUS_IS_OK(nt_status)) {
192                                 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
193                                         nt_errstr(nt_status) ));
194                                 goto fail;
195                         }
196                 } else {
197                         if (conn_flags & NET_FLAGS_SEAL) {
198                                 nt_status = cli_rpc_pipe_open_ntlmssp(
199                                         cli, interface,
200                                         (conn_flags & NET_FLAGS_TCP) ?
201                                         NCACN_IP_TCP : NCACN_NP,
202                                         DCERPC_AUTH_LEVEL_PRIVACY,
203                                         lp_workgroup(), c->opt_user_name,
204                                         c->opt_password, &pipe_hnd);
205                         } else {
206                                 nt_status = cli_rpc_pipe_open_noauth(
207                                         cli, interface,
208                                         &pipe_hnd);
209                         }
210                         if (!NT_STATUS_IS_OK(nt_status)) {
211                                 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
212                                           get_pipe_name_from_syntax(
213                                                   talloc_tos(), interface),
214                                         nt_errstr(nt_status) ));
215                                 goto fail;
216                         }
217                 }
218         }
219
220         nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
221
222         if (!NT_STATUS_IS_OK(nt_status)) {
223                 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
224         } else {
225                 ret = 0;
226                 DEBUG(5, ("rpc command function succedded\n"));
227         }
228
229         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
230                 if (pipe_hnd) {
231                         TALLOC_FREE(pipe_hnd);
232                 }
233         }
234
235 fail:
236         /* close the connection only if it was opened here */
237         if (!cli_arg) {
238                 cli_shutdown(cli);
239         }
240
241         talloc_destroy(mem_ctx);
242         return ret;
243 }
244
245 /**
246  * Force a change of the trust acccount password.
247  *
248  * All parameters are provided by the run_rpc_command function, except for
249  * argc, argv which are passed through.
250  *
251  * @param domain_sid The domain sid acquired from the remote server.
252  * @param cli A cli_state connected to the server.
253  * @param mem_ctx Talloc context, destroyed on completion of the function.
254  * @param argc  Standard main() style argc.
255  * @param argv  Standard main() style argv. Initial components are already
256  *              stripped.
257  *
258  * @return Normal NTSTATUS return.
259  **/
260
261 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
262                                         const struct dom_sid *domain_sid,
263                                         const char *domain_name,
264                                         struct cli_state *cli,
265                                         struct rpc_pipe_client *pipe_hnd,
266                                         TALLOC_CTX *mem_ctx,
267                                         int argc,
268                                         const char **argv)
269 {
270         NTSTATUS status;
271
272         status = trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
273         if (!NT_STATUS_IS_OK(status)) {
274                 d_fprintf(stderr, _("Failed to change machine account password: %s\n"),
275                         nt_errstr(status));
276                 return status;
277         }
278
279         return NT_STATUS_OK;
280 }
281
282 /**
283  * Force a change of the trust acccount password.
284  *
285  * @param argc  Standard main() style argc.
286  * @param argv  Standard main() style argv. Initial components are already
287  *              stripped.
288  *
289  * @return A shell status integer (0 for success).
290  **/
291
292 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
293 {
294         if (c->display_usage) {
295                 d_printf(  "%s\n"
296                            "net rpc changetrustpw\n"
297                            "    %s\n",
298                          _("Usage:"),
299                          _("Change the machine trust password"));
300                 return 0;
301         }
302
303         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
304                                NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
305                                rpc_changetrustpw_internals,
306                                argc, argv);
307 }
308
309 /**
310  * Join a domain, the old way.
311  *
312  * This uses 'machinename' as the inital password, and changes it.
313  *
314  * The password should be created with 'server manager' or equiv first.
315  *
316  * All parameters are provided by the run_rpc_command function, except for
317  * argc, argv which are passed through.
318  *
319  * @param domain_sid The domain sid acquired from the remote server.
320  * @param cli A cli_state connected to the server.
321  * @param mem_ctx Talloc context, destroyed on completion of the function.
322  * @param argc  Standard main() style argc.
323  * @param argv  Standard main() style argv. Initial components are already
324  *              stripped.
325  *
326  * @return Normal NTSTATUS return.
327  **/
328
329 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
330                                         const struct dom_sid *domain_sid,
331                                         const char *domain_name,
332                                         struct cli_state *cli,
333                                         struct rpc_pipe_client *pipe_hnd,
334                                         TALLOC_CTX *mem_ctx,
335                                         int argc,
336                                         const char **argv)
337 {
338
339         fstring trust_passwd;
340         unsigned char orig_trust_passwd_hash[16];
341         NTSTATUS result;
342         enum netr_SchannelType sec_channel_type;
343
344         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
345                                           &pipe_hnd);
346         if (!NT_STATUS_IS_OK(result)) {
347                 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
348                         "error was %s\n",
349                         cli->desthost,
350                         nt_errstr(result) ));
351                 return result;
352         }
353
354         /*
355            check what type of join - if the user want's to join as
356            a BDC, the server must agree that we are a BDC.
357         */
358         if (argc >= 0) {
359                 sec_channel_type = get_sec_channel_type(argv[0]);
360         } else {
361                 sec_channel_type = get_sec_channel_type(NULL);
362         }
363
364         fstrcpy(trust_passwd, global_myname());
365         strlower_m(trust_passwd);
366
367         /*
368          * Machine names can be 15 characters, but the max length on
369          * a password is 14.  --jerry
370          */
371
372         trust_passwd[14] = '\0';
373
374         E_md4hash(trust_passwd, orig_trust_passwd_hash);
375
376         result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
377                                               global_myname(),
378                                               orig_trust_passwd_hash,
379                                               sec_channel_type);
380
381         if (NT_STATUS_IS_OK(result))
382                 printf(_("Joined domain %s.\n"), c->opt_target_workgroup);
383
384
385         if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
386                 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
387                 result = NT_STATUS_UNSUCCESSFUL;
388         }
389
390         return result;
391 }
392
393 /**
394  * Join a domain, the old way.
395  *
396  * @param argc  Standard main() style argc.
397  * @param argv  Standard main() style argv. Initial components are already
398  *              stripped.
399  *
400  * @return A shell status integer (0 for success).
401  **/
402
403 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
404 {
405         return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
406                                NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
407                                rpc_oldjoin_internals,
408                                argc, argv);
409 }
410
411 /**
412  * Join a domain, the old way.  This function exists to allow
413  * the message to be displayed when oldjoin was explicitly
414  * requested, but not when it was implied by "net rpc join".
415  *
416  * @param argc  Standard main() style argc.
417  * @param argv  Standard main() style argv. Initial components are already
418  *              stripped.
419  *
420  * @return A shell status integer (0 for success).
421  **/
422
423 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
424 {
425         int rc = -1;
426
427         if (c->display_usage) {
428                 d_printf(  "%s\n"
429                            "net rpc oldjoin\n"
430                            "    %s\n",
431                          _("Usage:"),
432                          _("Join a domain the old way"));
433                 return 0;
434         }
435
436         rc = net_rpc_perform_oldjoin(c, argc, argv);
437
438         if (rc) {
439                 d_fprintf(stderr, _("Failed to join domain\n"));
440         }
441
442         return rc;
443 }
444
445 /**
446  * 'net rpc join' entrypoint.
447  * @param argc  Standard main() style argc.
448  * @param argv  Standard main() style argv. Initial components are already
449  *              stripped
450  *
451  * Main 'net_rpc_join()' (where the admin username/password is used) is
452  * in net_rpc_join.c.
453  * Try to just change the password, but if that doesn't work, use/prompt
454  * for a username/password.
455  **/
456
457 int net_rpc_join(struct net_context *c, int argc, const char **argv)
458 {
459         if (c->display_usage) {
460                 d_printf("%s\n%s",
461                          _("Usage:"),
462                          _("net rpc join -U <username>[%%password] <type>\n"
463                            "  Join a domain\n"
464                            "    username\tName of the admin user"
465                            "    password\tPassword of the admin user, will "
466                            "prompt if not specified\n"
467                            "    type\tCan be one of the following:\n"
468                            "\t\tMEMBER\tJoin as member server (default)\n"
469                            "\t\tBDC\tJoin as BDC\n"
470                            "\t\tPDC\tJoin as PDC\n"));
471                 return 0;
472         }
473
474         if (lp_server_role() == ROLE_STANDALONE) {
475                 d_printf(_("cannot join as standalone machine\n"));
476                 return -1;
477         }
478
479         if (strlen(global_myname()) > 15) {
480                 d_printf(_("Our netbios name can be at most 15 chars long, "
481                            "\"%s\" is %u chars long\n"),
482                          global_myname(), (unsigned int)strlen(global_myname()));
483                 return -1;
484         }
485
486         if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
487                 return 0;
488
489         return net_rpc_join_newstyle(c, argc, argv);
490 }
491
492 /**
493  * display info about a rpc domain
494  *
495  * All parameters are provided by the run_rpc_command function, except for
496  * argc, argv which are passed through.
497  *
498  * @param domain_sid The domain sid acquired from the remote server
499  * @param cli A cli_state connected to the server.
500  * @param mem_ctx Talloc context, destroyed on completion of the function.
501  * @param argc  Standard main() style argc.
502  * @param argv  Standard main() style argv. Initial components are already
503  *              stripped.
504  *
505  * @return Normal NTSTATUS return.
506  **/
507
508 NTSTATUS rpc_info_internals(struct net_context *c,
509                         const struct dom_sid *domain_sid,
510                         const char *domain_name,
511                         struct cli_state *cli,
512                         struct rpc_pipe_client *pipe_hnd,
513                         TALLOC_CTX *mem_ctx,
514                         int argc,
515                         const char **argv)
516 {
517         struct policy_handle connect_pol, domain_pol;
518         NTSTATUS status, result;
519         union samr_DomainInfo *info = NULL;
520         fstring sid_str;
521         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
522
523         sid_to_fstring(sid_str, domain_sid);
524
525         /* Get sam policy handle */
526         status = dcerpc_samr_Connect2(b, mem_ctx,
527                                       pipe_hnd->desthost,
528                                       MAXIMUM_ALLOWED_ACCESS,
529                                       &connect_pol,
530                                       &result);
531         if (!NT_STATUS_IS_OK(status)) {
532                 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
533                           nt_errstr(status));
534                 goto done;
535         }
536
537         if (!NT_STATUS_IS_OK(result)) {
538                 status = result;
539                 d_fprintf(stderr, _("Could not connect to SAM: %s\n"),
540                           nt_errstr(result));
541                 goto done;
542         }
543
544         /* Get domain policy handle */
545         status = dcerpc_samr_OpenDomain(b, mem_ctx,
546                                         &connect_pol,
547                                         MAXIMUM_ALLOWED_ACCESS,
548                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
549                                         &domain_pol,
550                                         &result);
551         if (!NT_STATUS_IS_OK(status)) {
552                 d_fprintf(stderr, _("Could not open domain: %s\n"),
553                           nt_errstr(status));
554                 goto done;
555         }
556         if (!NT_STATUS_IS_OK(result)) {
557                 status = result;
558                 d_fprintf(stderr, _("Could not open domain: %s\n"),
559                           nt_errstr(result));
560                 goto done;
561         }
562
563         status = dcerpc_samr_QueryDomainInfo(b, mem_ctx,
564                                              &domain_pol,
565                                              2,
566                                              &info,
567                                              &result);
568         if (!NT_STATUS_IS_OK(status)) {
569                 goto done;
570         }
571         status = result;
572         if (NT_STATUS_IS_OK(result)) {
573                 d_printf(_("Domain Name: %s\n"),
574                          info->general.domain_name.string);
575                 d_printf(_("Domain SID: %s\n"), sid_str);
576                 d_printf(_("Sequence number: %llu\n"),
577                         (unsigned long long)info->general.sequence_num);
578                 d_printf(_("Num users: %u\n"), info->general.num_users);
579                 d_printf(_("Num domain groups: %u\n"),info->general.num_groups);
580                 d_printf(_("Num local groups: %u\n"),info->general.num_aliases);
581         }
582
583  done:
584         return status;
585 }
586
587 /**
588  * 'net rpc info' entrypoint.
589  * @param argc  Standard main() style argc.
590  * @param argv  Standard main() style argv. Initial components are already
591  *              stripped.
592  **/
593
594 int net_rpc_info(struct net_context *c, int argc, const char **argv)
595 {
596         if (c->display_usage) {
597                 d_printf(  "%s\n"
598                            "net rpc info\n"
599                            "  %s\n",
600                          _("Usage:"),
601                          _("Display information about the domain"));
602                 return 0;
603         }
604
605         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
606                                NET_FLAGS_PDC, rpc_info_internals,
607                                argc, argv);
608 }
609
610 /**
611  * Fetch domain SID into the local secrets.tdb.
612  *
613  * All parameters are provided by the run_rpc_command function, except for
614  * argc, argv which are passed through.
615  *
616  * @param domain_sid The domain sid acquired from the remote server.
617  * @param cli A cli_state connected to the server.
618  * @param mem_ctx Talloc context, destroyed on completion of the function.
619  * @param argc  Standard main() style argc.
620  * @param argv  Standard main() style argv. Initial components are already
621  *              stripped.
622  *
623  * @return Normal NTSTATUS return.
624  **/
625
626 static NTSTATUS rpc_getsid_internals(struct net_context *c,
627                         const struct dom_sid *domain_sid,
628                         const char *domain_name,
629                         struct cli_state *cli,
630                         struct rpc_pipe_client *pipe_hnd,
631                         TALLOC_CTX *mem_ctx,
632                         int argc,
633                         const char **argv)
634 {
635         fstring sid_str;
636
637         sid_to_fstring(sid_str, domain_sid);
638         d_printf(_("Storing SID %s for Domain %s in secrets.tdb\n"),
639                  sid_str, domain_name);
640
641         if (!secrets_store_domain_sid(domain_name, domain_sid)) {
642                 DEBUG(0,("Can't store domain SID\n"));
643                 return NT_STATUS_UNSUCCESSFUL;
644         }
645
646         return NT_STATUS_OK;
647 }
648
649 /**
650  * 'net rpc getsid' entrypoint.
651  * @param argc  Standard main() style argc.
652  * @param argv  Standard main() style argv. Initial components are already
653  *              stripped.
654  **/
655
656 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
657 {
658         int conn_flags = NET_FLAGS_PDC;
659
660         if (!c->opt_user_specified) {
661                 conn_flags |= NET_FLAGS_ANONYMOUS;
662         }
663
664         if (c->display_usage) {
665                 d_printf(  "%s\n"
666                            "net rpc getsid\n"
667                            "    %s\n",
668                          _("Usage:"),
669                          _("Fetch domain SID into local secrets.tdb"));
670                 return 0;
671         }
672
673         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
674                                conn_flags,
675                                rpc_getsid_internals,
676                                argc, argv);
677 }
678
679 /****************************************************************************/
680
681 /**
682  * Basic usage function for 'net rpc user'.
683  * @param argc  Standard main() style argc.
684  * @param argv  Standard main() style argv. Initial components are already
685  *              stripped.
686  **/
687
688 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
689 {
690         return net_user_usage(c, argc, argv);
691 }
692
693 /**
694  * Add a new user to a remote RPC server.
695  *
696  * @param argc  Standard main() style argc.
697  * @param argv  Standard main() style argv. Initial components are already
698  *              stripped.
699  *
700  * @return A shell status integer (0 for success).
701  **/
702
703 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
704 {
705         NET_API_STATUS status;
706         struct USER_INFO_1 info1;
707         uint32_t parm_error = 0;
708
709         if (argc < 1 || c->display_usage) {
710                 rpc_user_usage(c, argc, argv);
711                 return 0;
712         }
713
714         ZERO_STRUCT(info1);
715
716         info1.usri1_name = argv[0];
717         if (argc == 2) {
718                 info1.usri1_password = argv[1];
719         }
720
721         status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
722
723         if (status != 0) {
724                 d_fprintf(stderr,_("Failed to add user '%s' with error: %s.\n"),
725                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
726                                                             status));
727                 return -1;
728         } else {
729                 d_printf(_("Added user '%s'.\n"), argv[0]);
730         }
731
732         return 0;
733 }
734
735 /**
736  * Rename a user on a remote RPC server.
737  *
738  * @param argc  Standard main() style argc.
739  * @param argv  Standard main() style argv. Initial components are already
740  *              stripped.
741  *
742  * @return A shell status integer (0 for success).
743  **/
744
745 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
746 {
747         NET_API_STATUS status;
748         struct USER_INFO_0 u0;
749         uint32_t parm_err = 0;
750
751         if (argc != 2 || c->display_usage) {
752                 rpc_user_usage(c, argc, argv);
753                 return 0;
754         }
755
756         u0.usri0_name = argv[1];
757
758         status = NetUserSetInfo(c->opt_host, argv[0],
759                                 0, (uint8_t *)&u0, &parm_err);
760         if (status) {
761                 d_fprintf(stderr,
762                           _("Failed to rename user from %s to %s - %s\n"),
763                           argv[0], argv[1],
764                           libnetapi_get_error_string(c->netapi_ctx, status));
765         } else {
766                 d_printf(_("Renamed user from %s to %s\n"), argv[0], argv[1]);
767         }
768
769         return status;
770 }
771
772 /**
773  * Set a user's primary group
774  *
775  * @param argc  Standard main() style argc.
776  * @param argv  Standard main() style argv. Initial components are already
777  *              stripped.
778  *
779  * @return A shell status integer (0 for success).
780  **/
781
782 static int rpc_user_setprimarygroup(struct net_context *c, int argc,
783                                     const char **argv)
784 {
785         NET_API_STATUS status;
786         uint8_t *buffer;
787         struct GROUP_INFO_2 *g2;
788         struct USER_INFO_1051 u1051;
789         uint32_t parm_err = 0;
790
791         if (argc != 2 || c->display_usage) {
792                 rpc_user_usage(c, argc, argv);
793                 return 0;
794         }
795
796         status = NetGroupGetInfo(c->opt_host, argv[1], 2, &buffer);
797         if (status) {
798                 d_fprintf(stderr, _("Failed to find group name %s -- %s\n"),
799                           argv[1],
800                           libnetapi_get_error_string(c->netapi_ctx, status));
801                 return status;
802         }
803         g2 = (struct GROUP_INFO_2 *)buffer;
804
805         u1051.usri1051_primary_group_id = g2->grpi2_group_id;
806
807         NetApiBufferFree(buffer);
808
809         status = NetUserSetInfo(c->opt_host, argv[0], 1051,
810                                 (uint8_t *)&u1051, &parm_err);
811         if (status) {
812                 d_fprintf(stderr,
813                           _("Failed to set user's primary group %s to %s - "
814                             "%s\n"), argv[0], argv[1],
815                           libnetapi_get_error_string(c->netapi_ctx, status));
816         } else {
817                 d_printf(_("Set primary group of user %s to %s\n"), argv[0],
818                          argv[1]);
819         }
820         return status;
821 }
822
823 /**
824  * Delete a user from a remote RPC server.
825  *
826  * @param argc  Standard main() style argc.
827  * @param argv  Standard main() style argv. Initial components are already
828  *              stripped.
829  *
830  * @return A shell status integer (0 for success).
831  **/
832
833 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
834 {
835         NET_API_STATUS status;
836
837         if (argc < 1 || c->display_usage) {
838                 rpc_user_usage(c, argc, argv);
839                 return 0;
840         }
841
842         status = NetUserDel(c->opt_host, argv[0]);
843
844         if (status != 0) {
845                 d_fprintf(stderr, _("Failed to delete user '%s' with: %s.\n"),
846                           argv[0],
847                           libnetapi_get_error_string(c->netapi_ctx, status));
848                 return -1;
849         } else {
850                 d_printf(_("Deleted user '%s'.\n"), argv[0]);
851         }
852
853         return 0;
854 }
855
856 /**
857  * Set a user's password on a remote RPC server.
858  *
859  * @param argc  Standard main() style argc.
860  * @param argv  Standard main() style argv. Initial components are already
861  *              stripped.
862  *
863  * @return A shell status integer (0 for success).
864  **/
865
866 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
867 {
868         NET_API_STATUS status;
869         char *prompt = NULL;
870         struct USER_INFO_1003 u1003;
871         uint32_t parm_err = 0;
872         int ret;
873
874         if (argc < 1 || c->display_usage) {
875                 rpc_user_usage(c, argc, argv);
876                 return 0;
877         }
878
879         if (argv[1]) {
880                 u1003.usri1003_password = argv[1];
881         } else {
882                 ret = asprintf(&prompt, _("Enter new password for %s:"),
883                                argv[0]);
884                 if (ret == -1) {
885                         return -1;
886                 }
887                 u1003.usri1003_password = talloc_strdup(c, getpass(prompt));
888                 SAFE_FREE(prompt);
889                 if (u1003.usri1003_password == NULL) {
890                         return -1;
891                 }
892         }
893
894         status = NetUserSetInfo(c->opt_host, argv[0], 1003, (uint8_t *)&u1003, &parm_err);
895
896         /* Display results */
897         if (status != 0) {
898                 d_fprintf(stderr,
899                         _("Failed to set password for '%s' with error: %s.\n"),
900                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
901                                                             status));
902                 return -1;
903         }
904
905         return 0;
906 }
907
908 /**
909  * List a user's groups from a remote RPC server.
910  *
911  * @param argc  Standard main() style argc.
912  * @param argv  Standard main() style argv. Initial components are already
913  *              stripped.
914  *
915  * @return A shell status integer (0 for success)
916  **/
917
918 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
919
920 {
921         NET_API_STATUS status;
922         struct GROUP_USERS_INFO_0 *u0 = NULL;
923         uint32_t entries_read = 0;
924         uint32_t total_entries = 0;
925         int i;
926
927
928         if (argc < 1 || c->display_usage) {
929                 rpc_user_usage(c, argc, argv);
930                 return 0;
931         }
932
933         status = NetUserGetGroups(c->opt_host,
934                                   argv[0],
935                                   0,
936                                   (uint8_t **)(void *)&u0,
937                                   (uint32_t)-1,
938                                   &entries_read,
939                                   &total_entries);
940         if (status != 0) {
941                 d_fprintf(stderr,
942                         _("Failed to get groups for '%s' with error: %s.\n"),
943                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
944                                                             status));
945                 return -1;
946         }
947
948         for (i=0; i < entries_read; i++) {
949                 printf("%s\n", u0->grui0_name);
950                 u0++;
951         }
952
953         return 0;
954 }
955
956 /**
957  * List users on a remote RPC server.
958  *
959  * All parameters are provided by the run_rpc_command function, except for
960  * argc, argv which are passed through.
961  *
962  * @param domain_sid The domain sid acquired from the remote server.
963  * @param cli A cli_state connected to the server.
964  * @param mem_ctx Talloc context, destroyed on completion of the function.
965  * @param argc  Standard main() style argc.
966  * @param argv  Standard main() style argv. Initial components are already
967  *              stripped.
968  *
969  * @return Normal NTSTATUS return.
970  **/
971
972 static int rpc_user_list(struct net_context *c, int argc, const char **argv)
973 {
974         NET_API_STATUS status;
975         uint32_t start_idx=0, num_entries, i, loop_count = 0;
976         struct NET_DISPLAY_USER *info = NULL;
977         void *buffer = NULL;
978
979         /* Query domain users */
980         if (c->opt_long_list_entries)
981                 d_printf(_("\nUser name             Comment"
982                            "\n-----------------------------\n"));
983         do {
984                 uint32_t max_entries, max_size;
985
986                 dcerpc_get_query_dispinfo_params(
987                         loop_count, &max_entries, &max_size);
988
989                 status = NetQueryDisplayInformation(c->opt_host,
990                                                     1,
991                                                     start_idx,
992                                                     max_entries,
993                                                     max_size,
994                                                     &num_entries,
995                                                     &buffer);
996                 if (status != 0 && status != ERROR_MORE_DATA) {
997                         return status;
998                 }
999
1000                 info = (struct NET_DISPLAY_USER *)buffer;
1001
1002                 for (i = 0; i < num_entries; i++) {
1003
1004                         if (c->opt_long_list_entries)
1005                                 printf("%-21.21s %s\n", info->usri1_name,
1006                                         info->usri1_comment);
1007                         else
1008                                 printf("%s\n", info->usri1_name);
1009                         info++;
1010                 }
1011
1012                 NetApiBufferFree(buffer);
1013
1014                 loop_count++;
1015                 start_idx += num_entries;
1016
1017         } while (status == ERROR_MORE_DATA);
1018
1019         return status;
1020 }
1021
1022 /**
1023  * 'net rpc user' entrypoint.
1024  * @param argc  Standard main() style argc.
1025  * @param argv  Standard main() style argv. Initial components are already
1026  *              stripped.
1027  **/
1028
1029 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1030 {
1031         NET_API_STATUS status;
1032
1033         struct functable func[] = {
1034                 {
1035                         "add",
1036                         rpc_user_add,
1037                         NET_TRANSPORT_RPC,
1038                         N_("Add specified user"),
1039                         N_("net rpc user add\n"
1040                            "    Add specified user")
1041                 },
1042                 {
1043                         "info",
1044                         rpc_user_info,
1045                         NET_TRANSPORT_RPC,
1046                         N_("List domain groups of user"),
1047                         N_("net rpc user info\n"
1048                            "    List domain groups of user")
1049                 },
1050                 {
1051                         "delete",
1052                         rpc_user_delete,
1053                         NET_TRANSPORT_RPC,
1054                         N_("Remove specified user"),
1055                         N_("net rpc user delete\n"
1056                            "    Remove specified user")
1057                 },
1058                 {
1059                         "password",
1060                         rpc_user_password,
1061                         NET_TRANSPORT_RPC,
1062                         N_("Change user password"),
1063                         N_("net rpc user password\n"
1064                            "    Change user password")
1065                 },
1066                 {
1067                         "rename",
1068                         rpc_user_rename,
1069                         NET_TRANSPORT_RPC,
1070                         N_("Rename specified user"),
1071                         N_("net rpc user rename\n"
1072                            "    Rename specified user")
1073                 },
1074                 {
1075                         "setprimarygroup",
1076                         rpc_user_setprimarygroup,
1077                         NET_TRANSPORT_RPC,
1078                         "Set a user's primary group",
1079                         "net rpc user setprimarygroup\n"
1080                         "    Set a user's primary group"
1081                 },
1082                 {NULL, NULL, 0, NULL, NULL}
1083         };
1084
1085         status = libnetapi_net_init(&c->netapi_ctx);
1086         if (status != 0) {
1087                 return -1;
1088         }
1089         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1090         libnetapi_set_password(c->netapi_ctx, c->opt_password);
1091         if (c->opt_kerberos) {
1092                 libnetapi_set_use_kerberos(c->netapi_ctx);
1093         }
1094
1095         if (argc == 0) {
1096                 if (c->display_usage) {
1097                         d_printf(  "%s\n"
1098                                    "net rpc user\n"
1099                                    "    %s\n",
1100                                  _("Usage:"),
1101                                  _("List all users"));
1102                         net_display_usage_from_functable(func);
1103                         return 0;
1104                 }
1105
1106                 return rpc_user_list(c, argc, argv);
1107         }
1108
1109         return net_run_function(c, argc, argv, "net rpc user", func);
1110 }
1111
1112 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1113                                  TALLOC_CTX *mem_ctx,
1114                                  struct rpc_sh_ctx *ctx,
1115                                  struct rpc_pipe_client *pipe_hnd,
1116                                  int argc, const char **argv)
1117 {
1118         return werror_to_ntstatus(W_ERROR(rpc_user_list(c, argc, argv)));
1119 }
1120
1121 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1122                                  TALLOC_CTX *mem_ctx,
1123                                  struct rpc_sh_ctx *ctx,
1124                                  struct rpc_pipe_client *pipe_hnd,
1125                                  int argc, const char **argv)
1126 {
1127         return werror_to_ntstatus(W_ERROR(rpc_user_info(c, argc, argv)));
1128 }
1129
1130 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1131                                    TALLOC_CTX *mem_ctx,
1132                                    struct rpc_sh_ctx *ctx,
1133                                    struct rpc_pipe_client *pipe_hnd,
1134                                    int argc, const char **argv,
1135                                    NTSTATUS (*fn)(
1136                                            struct net_context *c,
1137                                            TALLOC_CTX *mem_ctx,
1138                                            struct rpc_sh_ctx *ctx,
1139                                            struct rpc_pipe_client *pipe_hnd,
1140                                            struct policy_handle *user_hnd,
1141                                            int argc, const char **argv))
1142 {
1143         struct policy_handle connect_pol, domain_pol, user_pol;
1144         NTSTATUS status, result;
1145         struct dom_sid sid;
1146         uint32 rid;
1147         enum lsa_SidType type;
1148         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1149
1150         if (argc == 0) {
1151                 d_fprintf(stderr, "%s %s <username>\n", _("Usage:"),
1152                           ctx->whoami);
1153                 return NT_STATUS_INVALID_PARAMETER;
1154         }
1155
1156         ZERO_STRUCT(connect_pol);
1157         ZERO_STRUCT(domain_pol);
1158         ZERO_STRUCT(user_pol);
1159
1160         status = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1161                                      argv[0], NULL, NULL, &sid, &type);
1162         if (!NT_STATUS_IS_OK(status)) {
1163                 d_fprintf(stderr, _("Could not lookup %s: %s\n"), argv[0],
1164                           nt_errstr(status));
1165                 goto done;
1166         }
1167
1168         if (type != SID_NAME_USER) {
1169                 d_fprintf(stderr, _("%s is a %s, not a user\n"), argv[0],
1170                           sid_type_lookup(type));
1171                 status = NT_STATUS_NO_SUCH_USER;
1172                 goto done;
1173         }
1174
1175         if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1176                 d_fprintf(stderr, _("%s is not in our domain\n"), argv[0]);
1177                 status = NT_STATUS_NO_SUCH_USER;
1178                 goto done;
1179         }
1180
1181         status = dcerpc_samr_Connect2(b, mem_ctx,
1182                                       pipe_hnd->desthost,
1183                                       MAXIMUM_ALLOWED_ACCESS,
1184                                       &connect_pol,
1185                                       &result);
1186         if (!NT_STATUS_IS_OK(status)) {
1187                 goto done;
1188         }
1189         if (!NT_STATUS_IS_OK(result)) {
1190                 status = result;
1191                 goto done;
1192         }
1193
1194         status = dcerpc_samr_OpenDomain(b, mem_ctx,
1195                                         &connect_pol,
1196                                         MAXIMUM_ALLOWED_ACCESS,
1197                                         ctx->domain_sid,
1198                                         &domain_pol,
1199                                         &result);
1200         if (!NT_STATUS_IS_OK(status)) {
1201                 goto done;
1202         }
1203         if (!NT_STATUS_IS_OK(result)) {
1204                 status = result;
1205                 goto done;
1206         }
1207
1208         status = dcerpc_samr_OpenUser(b, mem_ctx,
1209                                       &domain_pol,
1210                                       MAXIMUM_ALLOWED_ACCESS,
1211                                       rid,
1212                                       &user_pol,
1213                                       &result);
1214         if (!NT_STATUS_IS_OK(status)) {
1215                 goto done;
1216         }
1217         if (!NT_STATUS_IS_OK(result)) {
1218                 status = result;
1219                 goto done;
1220         }
1221
1222         status = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1223
1224  done:
1225         if (is_valid_policy_hnd(&user_pol)) {
1226                 dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1227         }
1228         if (is_valid_policy_hnd(&domain_pol)) {
1229                 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
1230         }
1231         if (is_valid_policy_hnd(&connect_pol)) {
1232                 dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
1233         }
1234         return status;
1235 }
1236
1237 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1238                                            TALLOC_CTX *mem_ctx,
1239                                            struct rpc_sh_ctx *ctx,
1240                                            struct rpc_pipe_client *pipe_hnd,
1241                                            struct policy_handle *user_hnd,
1242                                            int argc, const char **argv)
1243 {
1244         NTSTATUS status, result;
1245         union samr_UserInfo *info = NULL;
1246         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1247
1248         if (argc != 0) {
1249                 d_fprintf(stderr, "%s %s show <username>\n", _("Usage:"),
1250                           ctx->whoami);
1251                 return NT_STATUS_INVALID_PARAMETER;
1252         }
1253
1254         status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1255                                            user_hnd,
1256                                            21,
1257                                            &info,
1258                                            &result);
1259         if (!NT_STATUS_IS_OK(status)) {
1260                 return status;
1261         }
1262         if (!NT_STATUS_IS_OK(result)) {
1263                 return result;
1264         }
1265
1266         d_printf(_("user rid: %d, group rid: %d\n"),
1267                 info->info21.rid,
1268                 info->info21.primary_gid);
1269
1270         return result;
1271 }
1272
1273 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1274                                  TALLOC_CTX *mem_ctx,
1275                                  struct rpc_sh_ctx *ctx,
1276                                  struct rpc_pipe_client *pipe_hnd,
1277                                  int argc, const char **argv)
1278 {
1279         return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1280                                   rpc_sh_user_show_internals);
1281 }
1282
1283 #define FETCHSTR(name, rec) \
1284 do { if (strequal(ctx->thiscmd, name)) { \
1285         oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1286 } while (0);
1287
1288 #define SETSTR(name, rec, flag) \
1289 do { if (strequal(ctx->thiscmd, name)) { \
1290         init_lsa_String(&(info->info21.rec), argv[0]); \
1291         info->info21.fields_present |= SAMR_FIELD_##flag; } \
1292 } while (0);
1293
1294 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1295                                                TALLOC_CTX *mem_ctx,
1296                                                struct rpc_sh_ctx *ctx,
1297                                                struct rpc_pipe_client *pipe_hnd,
1298                                                struct policy_handle *user_hnd,
1299                                                int argc, const char **argv)
1300 {
1301         NTSTATUS status, result;
1302         const char *username;
1303         const char *oldval = "";
1304         union samr_UserInfo *info = NULL;
1305         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1306
1307         if (argc > 1) {
1308                 d_fprintf(stderr, "%s %s <username> [new value|NULL]\n",
1309                           _("Usage:"), ctx->whoami);
1310                 return NT_STATUS_INVALID_PARAMETER;
1311         }
1312
1313         status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1314                                            user_hnd,
1315                                            21,
1316                                            &info,
1317                                            &result);
1318         if (!NT_STATUS_IS_OK(status)) {
1319                 return status;
1320         }
1321         if (!NT_STATUS_IS_OK(result)) {
1322                 return result;
1323         }
1324
1325         username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1326
1327         FETCHSTR("fullname", full_name);
1328         FETCHSTR("homedir", home_directory);
1329         FETCHSTR("homedrive", home_drive);
1330         FETCHSTR("logonscript", logon_script);
1331         FETCHSTR("profilepath", profile_path);
1332         FETCHSTR("description", description);
1333
1334         if (argc == 0) {
1335                 d_printf(_("%s's %s: [%s]\n"), username, ctx->thiscmd, oldval);
1336                 goto done;
1337         }
1338
1339         if (strcmp(argv[0], "NULL") == 0) {
1340                 argv[0] = "";
1341         }
1342
1343         ZERO_STRUCT(info->info21);
1344
1345         SETSTR("fullname", full_name, FULL_NAME);
1346         SETSTR("homedir", home_directory, HOME_DIRECTORY);
1347         SETSTR("homedrive", home_drive, HOME_DRIVE);
1348         SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1349         SETSTR("profilepath", profile_path, PROFILE_PATH);
1350         SETSTR("description", description, DESCRIPTION);
1351
1352         status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1353                                          user_hnd,
1354                                          21,
1355                                          info,
1356                                          &result);
1357         if (!NT_STATUS_IS_OK(status)) {
1358                 return status;
1359         }
1360
1361         status = result;
1362
1363         d_printf(_("Set %s's %s from [%s] to [%s]\n"), username,
1364                  ctx->thiscmd, oldval, argv[0]);
1365
1366  done:
1367
1368         return status;
1369 }
1370
1371 #define HANDLEFLG(name, rec) \
1372 do { if (strequal(ctx->thiscmd, name)) { \
1373         oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1374         if (newval) { \
1375                 newflags = oldflags | ACB_##rec; \
1376         } else { \
1377                 newflags = oldflags & ~ACB_##rec; \
1378         } } } while (0);
1379
1380 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1381                                      TALLOC_CTX *mem_ctx,
1382                                      struct rpc_sh_ctx *ctx,
1383                                      struct rpc_pipe_client *pipe_hnd,
1384                                      int argc, const char **argv)
1385 {
1386         return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1387                                   rpc_sh_user_str_edit_internals);
1388 }
1389
1390 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1391                                                 TALLOC_CTX *mem_ctx,
1392                                                 struct rpc_sh_ctx *ctx,
1393                                                 struct rpc_pipe_client *pipe_hnd,
1394                                                 struct policy_handle *user_hnd,
1395                                                 int argc, const char **argv)
1396 {
1397         NTSTATUS status, result;
1398         const char *username;
1399         const char *oldval = "unknown";
1400         uint32 oldflags, newflags;
1401         bool newval;
1402         union samr_UserInfo *info = NULL;
1403         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1404
1405         if ((argc > 1) ||
1406             ((argc == 1) && !strequal(argv[0], "yes") &&
1407              !strequal(argv[0], "no"))) {
1408                 /* TRANSATORS: The yes|no here are program keywords. Please do
1409                    not translate. */
1410                 d_fprintf(stderr, _("Usage: %s <username> [yes|no]\n"),
1411                           ctx->whoami);
1412                 return NT_STATUS_INVALID_PARAMETER;
1413         }
1414
1415         newval = strequal(argv[0], "yes");
1416
1417         status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1418                                            user_hnd,
1419                                            21,
1420                                            &info,
1421                                            &result);
1422         if (!NT_STATUS_IS_OK(status)) {
1423                 return status;
1424         }
1425         if (!NT_STATUS_IS_OK(result)) {
1426                 return result;
1427         }
1428
1429         username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1430         oldflags = info->info21.acct_flags;
1431         newflags = info->info21.acct_flags;
1432
1433         HANDLEFLG("disabled", DISABLED);
1434         HANDLEFLG("pwnotreq", PWNOTREQ);
1435         HANDLEFLG("autolock", AUTOLOCK);
1436         HANDLEFLG("pwnoexp", PWNOEXP);
1437
1438         if (argc == 0) {
1439                 d_printf(_("%s's %s flag: %s\n"), username, ctx->thiscmd,
1440                          oldval);
1441                 goto done;
1442         }
1443
1444         ZERO_STRUCT(info->info21);
1445
1446         info->info21.acct_flags = newflags;
1447         info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1448
1449         status = dcerpc_samr_SetUserInfo(b, mem_ctx,
1450                                          user_hnd,
1451                                          21,
1452                                          info,
1453                                          &result);
1454         if (!NT_STATUS_IS_OK(status)) {
1455                 goto done;
1456         }
1457         status = result;
1458         if (NT_STATUS_IS_OK(result)) {
1459                 d_printf(_("Set %s's %s flag from [%s] to [%s]\n"), username,
1460                          ctx->thiscmd, oldval, argv[0]);
1461         }
1462
1463  done:
1464
1465         return status;
1466 }
1467
1468 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1469                                       TALLOC_CTX *mem_ctx,
1470                                       struct rpc_sh_ctx *ctx,
1471                                       struct rpc_pipe_client *pipe_hnd,
1472                                       int argc, const char **argv)
1473 {
1474         return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1475                                   rpc_sh_user_flag_edit_internals);
1476 }
1477
1478 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1479                                           TALLOC_CTX *mem_ctx,
1480                                           struct rpc_sh_ctx *ctx)
1481 {
1482         static struct rpc_sh_cmd cmds[] = {
1483
1484                 { "fullname", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1485                   N_("Show/Set a user's full name") },
1486
1487                 { "homedir", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1488                   N_("Show/Set a user's home directory") },
1489
1490                 { "homedrive", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1491                   N_("Show/Set a user's home drive") },
1492
1493                 { "logonscript", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1494                   N_("Show/Set a user's logon script") },
1495
1496                 { "profilepath", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1497                   N_("Show/Set a user's profile path") },
1498
1499                 { "description", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1500                   N_("Show/Set a user's description") },
1501
1502                 { "disabled", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1503                   N_("Show/Set whether a user is disabled") },
1504
1505                 { "autolock", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1506                   N_("Show/Set whether a user locked out") },
1507
1508                 { "pwnotreq", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1509                   N_("Show/Set whether a user does not need a password") },
1510
1511                 { "pwnoexp", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1512                   N_("Show/Set whether a user's password does not expire") },
1513
1514                 { NULL, NULL, 0, NULL, NULL }
1515         };
1516
1517         return cmds;
1518 }
1519
1520 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1521                                      TALLOC_CTX *mem_ctx,
1522                                      struct rpc_sh_ctx *ctx)
1523 {
1524         static struct rpc_sh_cmd cmds[] = {
1525
1526                 { "list", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_list,
1527                   N_("List available users") },
1528
1529                 { "info", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_info,
1530                   N_("List the domain groups a user is member of") },
1531
1532                 { "show", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_show,
1533                   N_("Show info about a user") },
1534
1535                 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1536                   N_("Show/Modify a user's fields") },
1537
1538                 { NULL, NULL, 0, NULL, NULL }
1539         };
1540
1541         return cmds;
1542 }
1543
1544 /****************************************************************************/
1545
1546 /**
1547  * Basic usage function for 'net rpc group'.
1548  * @param argc  Standard main() style argc.
1549  * @param argv  Standard main() style argv. Initial components are already
1550  *              stripped.
1551  **/
1552
1553 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1554 {
1555         return net_group_usage(c, argc, argv);
1556 }
1557
1558 /**
1559  * Delete group on a remote RPC server.
1560  *
1561  * All parameters are provided by the run_rpc_command function, except for
1562  * argc, argv which are passed through.
1563  *
1564  * @param domain_sid The domain sid acquired from the remote server.
1565  * @param cli A cli_state connected to the server.
1566  * @param mem_ctx Talloc context, destroyed on completion of the function.
1567  * @param argc  Standard main() style argc.
1568  * @param argv  Standard main() style argv. Initial components are already
1569  *              stripped.
1570  *
1571  * @return Normal NTSTATUS return.
1572  **/
1573
1574 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1575                                         const struct dom_sid *domain_sid,
1576                                         const char *domain_name,
1577                                         struct cli_state *cli,
1578                                         struct rpc_pipe_client *pipe_hnd,
1579                                         TALLOC_CTX *mem_ctx,
1580                                         int argc,
1581                                         const char **argv)
1582 {
1583         struct policy_handle connect_pol, domain_pol, group_pol, user_pol;
1584         bool group_is_primary = false;
1585         NTSTATUS status, result;
1586         uint32_t group_rid;
1587         struct samr_RidAttrArray *rids = NULL;
1588         /* char **names; */
1589         int i;
1590         /* struct samr_RidWithAttribute *user_gids; */
1591         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
1592
1593         struct samr_Ids group_rids, name_types;
1594         struct lsa_String lsa_acct_name;
1595         union samr_UserInfo *info = NULL;
1596
1597         if (argc < 1 || c->display_usage) {
1598                 rpc_group_usage(c, argc,argv);
1599                 return NT_STATUS_OK; /* ok? */
1600         }
1601
1602         status = dcerpc_samr_Connect2(b, mem_ctx,
1603                                       pipe_hnd->desthost,
1604                                       MAXIMUM_ALLOWED_ACCESS,
1605                                       &connect_pol,
1606                                       &result);
1607         if (!NT_STATUS_IS_OK(status)) {
1608                 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1609                 goto done;
1610         }
1611
1612         if (!NT_STATUS_IS_OK(result)) {
1613                 status = result;
1614                 d_fprintf(stderr, _("Request samr_Connect2 failed\n"));
1615                 goto done;
1616         }
1617
1618         status = dcerpc_samr_OpenDomain(b, mem_ctx,
1619                                         &connect_pol,
1620                                         MAXIMUM_ALLOWED_ACCESS,
1621                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1622                                         &domain_pol,
1623                                         &result);
1624         if (!NT_STATUS_IS_OK(status)) {
1625                 d_fprintf(stderr, _("Request open_domain failed\n"));
1626                 goto done;
1627         }
1628
1629         if (!NT_STATUS_IS_OK(result)) {
1630                 status = result;
1631                 d_fprintf(stderr, _("Request open_domain failed\n"));
1632                 goto done;
1633         }
1634
1635         init_lsa_String(&lsa_acct_name, argv[0]);
1636
1637         status = dcerpc_samr_LookupNames(b, mem_ctx,
1638                                          &domain_pol,
1639                                          1,
1640                                          &lsa_acct_name,
1641                                          &group_rids,
1642                                          &name_types,
1643                                          &result);
1644         if (!NT_STATUS_IS_OK(status)) {
1645                 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1646                 goto done;
1647         }
1648
1649         if (!NT_STATUS_IS_OK(result)) {
1650                 status = result;
1651                 d_fprintf(stderr, _("Lookup of '%s' failed\n"),argv[0]);
1652                 goto done;
1653         }
1654
1655         switch (name_types.ids[0])
1656         {
1657         case SID_NAME_DOM_GRP:
1658                 status = dcerpc_samr_OpenGroup(b, mem_ctx,
1659                                                &domain_pol,
1660                                                MAXIMUM_ALLOWED_ACCESS,
1661                                                group_rids.ids[0],
1662                                                &group_pol,
1663                                                &result);
1664                 if (!NT_STATUS_IS_OK(status)) {
1665                         d_fprintf(stderr, _("Request open_group failed"));
1666                         goto done;
1667                 }
1668
1669                 if (!NT_STATUS_IS_OK(result)) {
1670                         status = result;
1671                         d_fprintf(stderr, _("Request open_group failed"));
1672                         goto done;
1673                 }
1674
1675                 group_rid = group_rids.ids[0];
1676
1677                 status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
1678                                                       &group_pol,
1679                                                       &rids,
1680                                                       &result);
1681                 if (!NT_STATUS_IS_OK(status)) {
1682                         d_fprintf(stderr,
1683                                   _("Unable to query group members of %s"),
1684                                   argv[0]);
1685                         goto done;
1686                 }
1687
1688                 if (!NT_STATUS_IS_OK(result)) {
1689                         status = result;
1690                         d_fprintf(stderr,
1691                                   _("Unable to query group members of %s"),
1692                                   argv[0]);
1693                         goto done;
1694                 }
1695
1696                 if (c->opt_verbose) {
1697                         d_printf(
1698                                 _("Domain Group %s (rid: %d) has %d members\n"),
1699                                 argv[0],group_rid, rids->count);
1700                 }
1701
1702                 /* Check if group is anyone's primary group */
1703                 for (i = 0; i < rids->count; i++)
1704                 {
1705                         status = dcerpc_samr_OpenUser(b, mem_ctx,
1706                                                       &domain_pol,
1707                                                       MAXIMUM_ALLOWED_ACCESS,
1708                                                       rids->rids[i],
1709                                                       &user_pol,
1710                                                       &result);
1711                         if (!NT_STATUS_IS_OK(status)) {
1712                                 d_fprintf(stderr,
1713                                         _("Unable to open group member %d\n"),
1714                                         rids->rids[i]);
1715                                 goto done;
1716                         }
1717
1718                         if (!NT_STATUS_IS_OK(result)) {
1719                                 status = result;
1720                                 d_fprintf(stderr,
1721                                         _("Unable to open group member %d\n"),
1722                                         rids->rids[i]);
1723                                 goto done;
1724                         }
1725
1726                         status = dcerpc_samr_QueryUserInfo(b, mem_ctx,
1727                                                            &user_pol,
1728                                                            21,
1729                                                            &info,
1730                                                            &result);
1731                         if (!NT_STATUS_IS_OK(status)) {
1732                                 d_fprintf(stderr,
1733                                         _("Unable to lookup userinfo for group "
1734                                           "member %d\n"),
1735                                         rids->rids[i]);
1736                                 goto done;
1737                         }
1738
1739                         if (!NT_STATUS_IS_OK(result)) {
1740                                 status = result;
1741                                 d_fprintf(stderr,
1742                                         _("Unable to lookup userinfo for group "
1743                                           "member %d\n"),
1744                                         rids->rids[i]);
1745                                 goto done;
1746                         }
1747
1748                         if (info->info21.primary_gid == group_rid) {
1749                                 if (c->opt_verbose) {
1750                                         d_printf(_("Group is primary group "
1751                                                    "of %s\n"),
1752                                                 info->info21.account_name.string);
1753                                 }
1754                                 group_is_primary = true;
1755                         }
1756
1757                         dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
1758                 }
1759
1760                 if (group_is_primary) {
1761                         d_fprintf(stderr, _("Unable to delete group because "
1762                                  "some of it's members have it as primary "
1763                                  "group\n"));
1764                         status = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1765                         goto done;
1766                 }
1767
1768                 /* remove all group members */
1769                 for (i = 0; i < rids->count; i++)
1770                 {
1771                         if (c->opt_verbose)
1772                                 d_printf(_("Remove group member %d..."),
1773                                         rids->rids[i]);
1774                         status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
1775                                                                &group_pol,
1776                                                                rids->rids[i],
1777                                                                &result);
1778                         if (!NT_STATUS_IS_OK(status)) {
1779                                 goto done;
1780                         }
1781                         status = result;
1782                         if (NT_STATUS_IS_OK(result)) {
1783                                 if (c->opt_verbose)
1784                                         d_printf(_("ok\n"));
1785                         } else {
1786                                 if (c->opt_verbose)
1787                                         d_printf("%s\n", _("failed"));
1788                                 goto done;
1789                         }
1790                 }
1791
1792                 status = dcerpc_samr_DeleteDomainGroup(b, mem_ctx,
1793                                                        &group_pol,
1794                                                        &result);
1795                 if (!NT_STATUS_IS_OK(status)) {
1796                         break;
1797                 }
1798
1799                 status = result;
1800
1801                 break;
1802         /* removing a local group is easier... */
1803         case SID_NAME_ALIAS:
1804                 status = dcerpc_samr_OpenAlias(b, mem_ctx,
1805                                                &domain_pol,
1806                                                MAXIMUM_ALLOWED_ACCESS,
1807                                                group_rids.ids[0],
1808                                                &group_pol,
1809                                                &result);
1810                 if (!NT_STATUS_IS_OK(status)) {
1811                         d_fprintf(stderr, _("Request open_alias failed\n"));
1812                         goto done;
1813                 }
1814                 if (!NT_STATUS_IS_OK(result)) {
1815                         status = result;
1816                         d_fprintf(stderr, _("Request open_alias failed\n"));
1817                         goto done;
1818                 }
1819
1820                 status = dcerpc_samr_DeleteDomAlias(b, mem_ctx,
1821                                                     &group_pol,
1822                                                     &result);
1823                 if (!NT_STATUS_IS_OK(status)) {
1824                         break;
1825                 }
1826
1827                 status = result;
1828
1829                 break;
1830         default:
1831                 d_fprintf(stderr, _("%s is of type %s. This command is only "
1832                                     "for deleting local or global groups\n"),
1833                         argv[0],sid_type_lookup(name_types.ids[0]));
1834                 status = NT_STATUS_UNSUCCESSFUL;
1835                 goto done;
1836         }
1837
1838         if (NT_STATUS_IS_OK(status)) {
1839                 if (c->opt_verbose)
1840                         d_printf(_("Deleted %s '%s'\n"),
1841                                  sid_type_lookup(name_types.ids[0]), argv[0]);
1842         } else {
1843                 d_fprintf(stderr, _("Deleting of %s failed: %s\n"), argv[0],
1844                         get_friendly_nt_error_msg(status));
1845         }
1846
1847  done:
1848         return status;
1849
1850 }
1851
1852 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1853 {
1854         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1855                                rpc_group_delete_internals, argc,argv);
1856 }
1857
1858 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1859 {
1860         NET_API_STATUS status;
1861         struct GROUP_INFO_1 info1;
1862         uint32_t parm_error = 0;
1863
1864         if (argc != 1 || c->display_usage) {
1865                 rpc_group_usage(c, argc, argv);
1866                 return 0;
1867         }
1868
1869         ZERO_STRUCT(info1);
1870
1871         info1.grpi1_name = argv[0];
1872         if (c->opt_comment && strlen(c->opt_comment) > 0) {
1873                 info1.grpi1_comment = c->opt_comment;
1874         }
1875
1876         status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1877
1878         if (status != 0) {
1879                 d_fprintf(stderr,
1880                         _("Failed to add group '%s' with error: %s.\n"),
1881                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
1882                                                             status));
1883                 return -1;
1884         } else {
1885                 d_printf(_("Added group '%s'.\n"), argv[0]);
1886         }
1887
1888         return 0;
1889 }
1890
1891 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
1892 {
1893         NET_API_STATUS status;
1894         struct LOCALGROUP_INFO_1 info1;
1895         uint32_t parm_error = 0;
1896
1897         if (argc != 1 || c->display_usage) {
1898                 rpc_group_usage(c, argc, argv);
1899                 return 0;
1900         }
1901
1902         ZERO_STRUCT(info1);
1903
1904         info1.lgrpi1_name = argv[0];
1905         if (c->opt_comment && strlen(c->opt_comment) > 0) {
1906                 info1.lgrpi1_comment = c->opt_comment;
1907         }
1908
1909         status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1910
1911         if (status != 0) {
1912                 d_fprintf(stderr,
1913                         _("Failed to add alias '%s' with error: %s.\n"),
1914                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
1915                                                             status));
1916                 return -1;
1917         } else {
1918                 d_printf(_("Added alias '%s'.\n"), argv[0]);
1919         }
1920
1921         return 0;
1922 }
1923
1924 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1925 {
1926         if (c->opt_localgroup)
1927                 return rpc_alias_add_internals(c, argc, argv);
1928
1929         return rpc_group_add_internals(c, argc, argv);
1930 }
1931
1932 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1933                                 TALLOC_CTX *mem_ctx,
1934                                 const char *name,
1935                                 struct dom_sid *sid,
1936                                 enum lsa_SidType *type)
1937 {
1938         struct dom_sid *sids = NULL;
1939         enum lsa_SidType *types = NULL;
1940         struct rpc_pipe_client *pipe_hnd = NULL;
1941         struct policy_handle lsa_pol;
1942         NTSTATUS status, result;
1943         struct dcerpc_binding_handle *b;
1944
1945         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1946                                           &pipe_hnd);
1947         if (!NT_STATUS_IS_OK(status)) {
1948                 goto done;
1949         }
1950
1951         b = pipe_hnd->binding_handle;
1952
1953         status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1954                                      SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
1955
1956         if (!NT_STATUS_IS_OK(status)) {
1957                 goto done;
1958         }
1959
1960         status = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1961                                       &name, NULL, 1, &sids, &types);
1962
1963         if (NT_STATUS_IS_OK(status)) {
1964                 sid_copy(sid, &sids[0]);
1965                 *type = types[0];
1966         }
1967
1968         dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
1969
1970  done:
1971         if (pipe_hnd) {
1972                 TALLOC_FREE(pipe_hnd);
1973         }
1974
1975         if (!NT_STATUS_IS_OK(status) && (StrnCaseCmp(name, "S-", 2) == 0)) {
1976
1977                 /* Try as S-1-5-whatever */
1978
1979                 struct dom_sid tmp_sid;
1980
1981                 if (string_to_sid(&tmp_sid, name)) {
1982                         sid_copy(sid, &tmp_sid);
1983                         *type = SID_NAME_UNKNOWN;
1984                         status = NT_STATUS_OK;
1985                 }
1986         }
1987
1988         return status;
1989 }
1990
1991 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
1992                                 TALLOC_CTX *mem_ctx,
1993                                 const struct dom_sid *group_sid,
1994                                 const char *member)
1995 {
1996         struct policy_handle connect_pol, domain_pol;
1997         NTSTATUS status, result;
1998         uint32 group_rid;
1999         struct policy_handle group_pol;
2000         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2001
2002         struct samr_Ids rids, rid_types;
2003         struct lsa_String lsa_acct_name;
2004
2005         struct dom_sid sid;
2006
2007         sid_copy(&sid, group_sid);
2008
2009         if (!sid_split_rid(&sid, &group_rid)) {
2010                 return NT_STATUS_UNSUCCESSFUL;
2011         }
2012
2013         /* Get sam policy handle */
2014         status = dcerpc_samr_Connect2(b, mem_ctx,
2015                                       pipe_hnd->desthost,
2016                                       MAXIMUM_ALLOWED_ACCESS,
2017                                       &connect_pol,
2018                                       &result);
2019         if (!NT_STATUS_IS_OK(status)) {
2020                 return status;
2021         }
2022         if (!NT_STATUS_IS_OK(result)) {
2023                 return result;
2024         }
2025
2026         /* Get domain policy handle */
2027         status = dcerpc_samr_OpenDomain(b, mem_ctx,
2028                                         &connect_pol,
2029                                         MAXIMUM_ALLOWED_ACCESS,
2030                                         &sid,
2031                                         &domain_pol,
2032                                         &result);
2033         if (!NT_STATUS_IS_OK(status)) {
2034                 return status;
2035         }
2036         if (!NT_STATUS_IS_OK(result)) {
2037                 return result;
2038         }
2039
2040         init_lsa_String(&lsa_acct_name, member);
2041
2042         status = dcerpc_samr_LookupNames(b, mem_ctx,
2043                                          &domain_pol,
2044                                          1,
2045                                          &lsa_acct_name,
2046                                          &rids,
2047                                          &rid_types,
2048                                          &result);
2049         if (!NT_STATUS_IS_OK(status)) {
2050                 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2051                           member);
2052                 goto done;
2053         }
2054
2055         if (!NT_STATUS_IS_OK(result)) {
2056                 status = result;
2057                 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2058                           member);
2059                 goto done;
2060         }
2061
2062         status = dcerpc_samr_OpenGroup(b, mem_ctx,
2063                                        &domain_pol,
2064                                        MAXIMUM_ALLOWED_ACCESS,
2065                                        group_rid,
2066                                        &group_pol,
2067                                        &result);
2068         if (!NT_STATUS_IS_OK(status)) {
2069                 goto done;
2070         }
2071
2072         if (!NT_STATUS_IS_OK(result)) {
2073                 status = result;
2074                 goto done;
2075         }
2076
2077         status = dcerpc_samr_AddGroupMember(b, mem_ctx,
2078                                             &group_pol,
2079                                             rids.ids[0],
2080                                             0x0005, /* unknown flags */
2081                                             &result);
2082         if (!NT_STATUS_IS_OK(status)) {
2083                 goto done;
2084         }
2085
2086         status = result;
2087
2088  done:
2089         dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2090         return status;
2091 }
2092
2093 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2094                                 TALLOC_CTX *mem_ctx,
2095                                 const struct dom_sid *alias_sid,
2096                                 const char *member)
2097 {
2098         struct policy_handle connect_pol, domain_pol;
2099         NTSTATUS status, result;
2100         uint32 alias_rid;
2101         struct policy_handle alias_pol;
2102         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2103
2104         struct dom_sid member_sid;
2105         enum lsa_SidType member_type;
2106
2107         struct dom_sid sid;
2108
2109         sid_copy(&sid, alias_sid);
2110
2111         if (!sid_split_rid(&sid, &alias_rid)) {
2112                 return NT_STATUS_UNSUCCESSFUL;
2113         }
2114
2115         result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2116                                    member, &member_sid, &member_type);
2117
2118         if (!NT_STATUS_IS_OK(result)) {
2119                 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2120                           member);
2121                 return result;
2122         }
2123
2124         /* Get sam policy handle */
2125         status = dcerpc_samr_Connect2(b, mem_ctx,
2126                                       pipe_hnd->desthost,
2127                                       MAXIMUM_ALLOWED_ACCESS,
2128                                       &connect_pol,
2129                                       &result);
2130         if (!NT_STATUS_IS_OK(status)) {
2131                 goto done;
2132         }
2133         if (!NT_STATUS_IS_OK(result)) {
2134                 status = result;
2135                 goto done;
2136         }
2137
2138         /* Get domain policy handle */
2139         status = dcerpc_samr_OpenDomain(b, mem_ctx,
2140                                         &connect_pol,
2141                                         MAXIMUM_ALLOWED_ACCESS,
2142                                         &sid,
2143                                         &domain_pol,
2144                                         &result);
2145         if (!NT_STATUS_IS_OK(status)) {
2146                 goto done;
2147         }
2148         if (!NT_STATUS_IS_OK(result)) {
2149                 status = result;
2150                 goto done;
2151         }
2152
2153         status = dcerpc_samr_OpenAlias(b, mem_ctx,
2154                                        &domain_pol,
2155                                        MAXIMUM_ALLOWED_ACCESS,
2156                                        alias_rid,
2157                                        &alias_pol,
2158                                        &result);
2159         if (!NT_STATUS_IS_OK(status)) {
2160                 return status;
2161         }
2162         if (!NT_STATUS_IS_OK(result)) {
2163                 return result;
2164         }
2165
2166         status = dcerpc_samr_AddAliasMember(b, mem_ctx,
2167                                             &alias_pol,
2168                                             &member_sid,
2169                                             &result);
2170         if (!NT_STATUS_IS_OK(status)) {
2171                 return status;
2172         }
2173
2174         status = result;
2175
2176  done:
2177         dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2178         return status;
2179 }
2180
2181 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2182                                         const struct dom_sid *domain_sid,
2183                                         const char *domain_name,
2184                                         struct cli_state *cli,
2185                                         struct rpc_pipe_client *pipe_hnd,
2186                                         TALLOC_CTX *mem_ctx,
2187                                         int argc,
2188                                         const char **argv)
2189 {
2190         struct dom_sid group_sid;
2191         enum lsa_SidType group_type;
2192
2193         if (argc != 2 || c->display_usage) {
2194                 d_printf("%s\n%s",
2195                          _("Usage:"),
2196                          _("net rpc group addmem <group> <member>\n"
2197                            "  Add a member to a group\n"
2198                            "    group\tGroup to add member to\n"
2199                            "    member\tMember to add to group\n"));
2200                 return NT_STATUS_UNSUCCESSFUL;
2201         }
2202
2203         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2204                                                &group_sid, &group_type))) {
2205                 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2206                           argv[0]);
2207                 return NT_STATUS_UNSUCCESSFUL;
2208         }
2209
2210         if (group_type == SID_NAME_DOM_GRP) {
2211                 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2212                                                    &group_sid, argv[1]);
2213
2214                 if (!NT_STATUS_IS_OK(result)) {
2215                         d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2216                                  argv[1], argv[0], nt_errstr(result));
2217                 }
2218                 return result;
2219         }
2220
2221         if (group_type == SID_NAME_ALIAS) {
2222                 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2223                                                    &group_sid, argv[1]);
2224
2225                 if (!NT_STATUS_IS_OK(result)) {
2226                         d_fprintf(stderr, _("Could not add %s to %s: %s\n"),
2227                                  argv[1], argv[0], nt_errstr(result));
2228                 }
2229                 return result;
2230         }
2231
2232         d_fprintf(stderr, _("Can only add members to global or local groups "
2233                  "which %s is not\n"), argv[0]);
2234
2235         return NT_STATUS_UNSUCCESSFUL;
2236 }
2237
2238 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2239 {
2240         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2241                                rpc_group_addmem_internals,
2242                                argc, argv);
2243 }
2244
2245 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2246                                 struct rpc_pipe_client *pipe_hnd,
2247                                 TALLOC_CTX *mem_ctx,
2248                                 const struct dom_sid *group_sid,
2249                                 const char *member)
2250 {
2251         struct policy_handle connect_pol, domain_pol;
2252         NTSTATUS status, result;
2253         uint32 group_rid;
2254         struct policy_handle group_pol;
2255         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2256
2257         struct samr_Ids rids, rid_types;
2258         struct lsa_String lsa_acct_name;
2259
2260         struct dom_sid sid;
2261
2262         sid_copy(&sid, group_sid);
2263
2264         if (!sid_split_rid(&sid, &group_rid))
2265                 return NT_STATUS_UNSUCCESSFUL;
2266
2267         /* Get sam policy handle */
2268         status = dcerpc_samr_Connect2(b, mem_ctx,
2269                                       pipe_hnd->desthost,
2270                                       MAXIMUM_ALLOWED_ACCESS,
2271                                       &connect_pol,
2272                                       &result);
2273         if (!NT_STATUS_IS_OK(status)) {
2274                 return status;
2275         }
2276         if (!NT_STATUS_IS_OK(result)) {
2277                 return result;
2278         }
2279
2280
2281         /* Get domain policy handle */
2282         status = dcerpc_samr_OpenDomain(b, mem_ctx,
2283                                         &connect_pol,
2284                                         MAXIMUM_ALLOWED_ACCESS,
2285                                         &sid,
2286                                         &domain_pol,
2287                                         &result);
2288         if (!NT_STATUS_IS_OK(status)) {
2289                 return status;
2290         }
2291         if (!NT_STATUS_IS_OK(result)) {
2292                 return result;
2293         }
2294
2295         init_lsa_String(&lsa_acct_name, member);
2296
2297         status = dcerpc_samr_LookupNames(b, mem_ctx,
2298                                          &domain_pol,
2299                                          1,
2300                                          &lsa_acct_name,
2301                                          &rids,
2302                                          &rid_types,
2303                                          &result);
2304         if (!NT_STATUS_IS_OK(status)) {
2305                 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2306                           member);
2307                 goto done;
2308         }
2309
2310         if (!NT_STATUS_IS_OK(result)) {
2311                 status = result;
2312                 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2313                           member);
2314                 goto done;
2315         }
2316
2317         status = dcerpc_samr_OpenGroup(b, mem_ctx,
2318                                        &domain_pol,
2319                                        MAXIMUM_ALLOWED_ACCESS,
2320                                        group_rid,
2321                                        &group_pol,
2322                                        &result);
2323         if (!NT_STATUS_IS_OK(status)) {
2324                 goto done;
2325         }
2326         if (!NT_STATUS_IS_OK(result)) {
2327                 status = result;
2328                 goto done;
2329         }
2330
2331         status = dcerpc_samr_DeleteGroupMember(b, mem_ctx,
2332                                                &group_pol,
2333                                                rids.ids[0],
2334                                                &result);
2335         if (!NT_STATUS_IS_OK(status)) {
2336                 goto done;
2337         }
2338
2339         status = result;
2340  done:
2341         dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2342         return status;
2343 }
2344
2345 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2346                                 TALLOC_CTX *mem_ctx,
2347                                 const struct dom_sid *alias_sid,
2348                                 const char *member)
2349 {
2350         struct policy_handle connect_pol, domain_pol;
2351         NTSTATUS status, result;
2352         uint32 alias_rid;
2353         struct policy_handle alias_pol;
2354         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2355
2356         struct dom_sid member_sid;
2357         enum lsa_SidType member_type;
2358
2359         struct dom_sid sid;
2360
2361         sid_copy(&sid, alias_sid);
2362
2363         if (!sid_split_rid(&sid, &alias_rid))
2364                 return NT_STATUS_UNSUCCESSFUL;
2365
2366         result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2367                                    member, &member_sid, &member_type);
2368
2369         if (!NT_STATUS_IS_OK(result)) {
2370                 d_fprintf(stderr, _("Could not lookup up group member %s\n"),
2371                           member);
2372                 return result;
2373         }
2374
2375         /* Get sam policy handle */
2376         status = dcerpc_samr_Connect2(b, mem_ctx,
2377                                       pipe_hnd->desthost,
2378                                       MAXIMUM_ALLOWED_ACCESS,
2379                                       &connect_pol,
2380                                       &result);
2381         if (!NT_STATUS_IS_OK(status)) {
2382                 goto done;
2383         }
2384         if (!NT_STATUS_IS_OK(result)) {
2385                 status = result;
2386                 goto done;
2387         }
2388
2389         /* Get domain policy handle */
2390         status = dcerpc_samr_OpenDomain(b, mem_ctx,
2391                                         &connect_pol,
2392                                         MAXIMUM_ALLOWED_ACCESS,
2393                                         &sid,
2394                                         &domain_pol,
2395                                         &result);
2396         if (!NT_STATUS_IS_OK(status)) {
2397                 goto done;
2398         }
2399         if (!NT_STATUS_IS_OK(result)) {
2400                 status = result;
2401                 goto done;
2402         }
2403
2404         status = dcerpc_samr_OpenAlias(b, mem_ctx,
2405                                        &domain_pol,
2406                                        MAXIMUM_ALLOWED_ACCESS,
2407                                        alias_rid,
2408                                        &alias_pol,
2409                                        &result);
2410         if (!NT_STATUS_IS_OK(status)) {
2411                 return status;
2412         }
2413
2414         if (!NT_STATUS_IS_OK(result)) {
2415                 return result;
2416         }
2417
2418         status = dcerpc_samr_DeleteAliasMember(b, mem_ctx,
2419                                                &alias_pol,
2420                                                &member_sid,
2421                                                &result);
2422
2423         if (!NT_STATUS_IS_OK(status)) {
2424                 return status;
2425         }
2426
2427         status = result;
2428
2429  done:
2430         dcerpc_samr_Close(b, mem_ctx, &connect_pol, &result);
2431         return status;
2432 }
2433
2434 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2435                                         const struct dom_sid *domain_sid,
2436                                         const char *domain_name,
2437                                         struct cli_state *cli,
2438                                         struct rpc_pipe_client *pipe_hnd,
2439                                         TALLOC_CTX *mem_ctx,
2440                                         int argc,
2441                                         const char **argv)
2442 {
2443         struct dom_sid group_sid;
2444         enum lsa_SidType group_type;
2445
2446         if (argc != 2 || c->display_usage) {
2447                 d_printf("%s\n%s",
2448                          _("Usage:"),
2449                          _("net rpc group delmem <group> <member>\n"
2450                            "  Delete a member from a group\n"
2451                            "    group\tGroup to delete member from\n"
2452                            "    member\tMember to delete from group\n"));
2453                 return NT_STATUS_UNSUCCESSFUL;
2454         }
2455
2456         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2457                                                &group_sid, &group_type))) {
2458                 d_fprintf(stderr, _("Could not lookup group name %s\n"),
2459                           argv[0]);
2460                 return NT_STATUS_UNSUCCESSFUL;
2461         }
2462
2463         if (group_type == SID_NAME_DOM_GRP) {
2464                 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2465                                                    &group_sid, argv[1]);
2466
2467                 if (!NT_STATUS_IS_OK(result)) {
2468                         d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2469                                  argv[1], argv[0], nt_errstr(result));
2470                 }
2471                 return result;
2472         }
2473
2474         if (group_type == SID_NAME_ALIAS) {
2475                 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2476                                                    &group_sid, argv[1]);
2477
2478                 if (!NT_STATUS_IS_OK(result)) {
2479                         d_fprintf(stderr, _("Could not del %s from %s: %s\n"),
2480                                  argv[1], argv[0], nt_errstr(result));
2481                 }
2482                 return result;
2483         }
2484
2485         d_fprintf(stderr, _("Can only delete members from global or local "
2486                  "groups which %s is not\n"), argv[0]);
2487
2488         return NT_STATUS_UNSUCCESSFUL;
2489 }
2490
2491 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2492 {
2493         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2494                                rpc_group_delmem_internals,
2495                                argc, argv);
2496 }
2497
2498 /**
2499  * List groups on a remote RPC server.
2500  *
2501  * All parameters are provided by the run_rpc_command function, except for
2502  * argc, argv which are passes through.
2503  *
2504  * @param domain_sid The domain sid acquired from the remote server.
2505  * @param cli A cli_state connected to the server.
2506  * @param mem_ctx Talloc context, destroyed on completion of the function.
2507  * @param argc  Standard main() style argc.
2508  * @param argv  Standard main() style argv. Initial components are already
2509  *              stripped.
2510  *
2511  * @return Normal NTSTATUS return.
2512  **/
2513
2514 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2515                                         const struct dom_sid *domain_sid,
2516                                         const char *domain_name,
2517                                         struct cli_state *cli,
2518                                         struct rpc_pipe_client *pipe_hnd,
2519                                         TALLOC_CTX *mem_ctx,
2520                                         int argc,
2521                                         const char **argv)
2522 {
2523         struct policy_handle connect_pol, domain_pol;
2524         NTSTATUS status, result;
2525         uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2526         struct samr_SamArray *groups = NULL;
2527         bool global = false;
2528         bool local = false;
2529         bool builtin = false;
2530         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2531
2532         if (c->display_usage) {
2533                 d_printf("%s\n%s",
2534                          _("Usage:"),
2535                          _("net rpc group list [global] [local] [builtin]\n"
2536                            "  List groups on RPC server\n"
2537                            "    global\tList global groups\n"
2538                            "    local\tList local groups\n"
2539                            "    builtin\tList builtin groups\n"
2540                            "    If none of global, local or builtin is "
2541                            "specified, all three options are considered "
2542                            "set\n"));
2543                 return NT_STATUS_OK;
2544         }
2545
2546         if (argc == 0) {
2547                 global = true;
2548                 local = true;
2549                 builtin = true;
2550         }
2551
2552         for (i=0; i<argc; i++) {
2553                 if (strequal(argv[i], "global"))
2554                         global = true;
2555
2556                 if (strequal(argv[i], "local"))
2557                         local = true;
2558
2559                 if (strequal(argv[i], "builtin"))
2560                         builtin = true;
2561         }
2562
2563         /* Get sam policy handle */
2564
2565         status = dcerpc_samr_Connect2(b, mem_ctx,
2566                                       pipe_hnd->desthost,
2567                                       MAXIMUM_ALLOWED_ACCESS,
2568                                       &connect_pol,
2569                                       &result);
2570         if (!NT_STATUS_IS_OK(status)) {
2571                 goto done;
2572         }
2573         if (!NT_STATUS_IS_OK(result)) {
2574                 status = result;
2575                 goto done;
2576         }
2577
2578         /* Get domain policy handle */
2579
2580         status = dcerpc_samr_OpenDomain(b, mem_ctx,
2581                                         &connect_pol,
2582                                         MAXIMUM_ALLOWED_ACCESS,
2583                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2584                                         &domain_pol,
2585                                         &result);
2586         if (!NT_STATUS_IS_OK(status)) {
2587                 goto done;
2588         }
2589         if (!NT_STATUS_IS_OK(result)) {
2590                 status = result;
2591                 goto done;
2592         }
2593
2594         /* Query domain groups */
2595         if (c->opt_long_list_entries)
2596                 d_printf(_("\nGroup name            Comment"
2597                            "\n-----------------------------\n"));
2598         do {
2599                 uint32_t max_size, total_size, returned_size;
2600                 union samr_DispInfo info;
2601
2602                 if (!global) break;
2603
2604                 dcerpc_get_query_dispinfo_params(
2605                         loop_count, &max_entries, &max_size);
2606
2607                 status = dcerpc_samr_QueryDisplayInfo(b, mem_ctx,
2608                                                       &domain_pol,
2609                                                       3,
2610                                                       start_idx,
2611                                                       max_entries,
2612                                                       max_size,
2613                                                       &total_size,
2614                                                       &returned_size,
2615                                                       &info,
2616                                                       &result);
2617                 if (!NT_STATUS_IS_OK(status)) {
2618                         goto done;
2619                 }
2620                 num_entries = info.info3.count;
2621                 start_idx += info.info3.count;
2622
2623                 if (!NT_STATUS_IS_OK(result) &&
2624                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2625                         break;
2626
2627                 for (i = 0; i < num_entries; i++) {
2628
2629                         const char *group = NULL;
2630                         const char *desc = NULL;
2631
2632                         group = info.info3.entries[i].account_name.string;
2633                         desc = info.info3.entries[i].description.string;
2634
2635                         if (c->opt_long_list_entries)
2636                                 printf("%-21.21s %-50.50s\n",
2637                                        group, desc);
2638                         else
2639                                 printf("%s\n", group);
2640                 }
2641         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2642         /* query domain aliases */
2643         start_idx = 0;
2644         do {
2645                 if (!local) break;
2646
2647                 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2648                                                        &domain_pol,
2649                                                        &start_idx,
2650                                                        &groups,
2651                                                        0xffff,
2652                                                        &num_entries,
2653                                                        &result);
2654                 if (!NT_STATUS_IS_OK(status)) {
2655                         goto done;
2656                 }
2657                 if (!NT_STATUS_IS_OK(result) &&
2658                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2659                         break;
2660
2661                 for (i = 0; i < num_entries; i++) {
2662
2663                         const char *description = NULL;
2664
2665                         if (c->opt_long_list_entries) {
2666
2667                                 struct policy_handle alias_pol;
2668                                 union samr_AliasInfo *info = NULL;
2669                                 NTSTATUS _result;
2670
2671                                 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2672                                                                &domain_pol,
2673                                                                0x8,
2674                                                                groups->entries[i].idx,
2675                                                                &alias_pol,
2676                                                                &_result);
2677                                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2678                                         status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2679                                                                             &alias_pol,
2680                                                                             3,
2681                                                                             &info,
2682                                                                             &_result);
2683                                         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2684                                                 status = dcerpc_samr_Close(b, mem_ctx,
2685                                                                            &alias_pol,
2686                                                                            &_result);
2687                                                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2688                                                         description = info->description.string;
2689                                                 }
2690                                         }
2691                                 }
2692                         }
2693
2694                         if (description != NULL) {
2695                                 printf("%-21.21s %-50.50s\n",
2696                                        groups->entries[i].name.string,
2697                                        description);
2698                         } else {
2699                                 printf("%s\n", groups->entries[i].name.string);
2700                         }
2701                 }
2702         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2703         dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
2704         /* Get builtin policy handle */
2705
2706         status = dcerpc_samr_OpenDomain(b, mem_ctx,
2707                                         &connect_pol,
2708                                         MAXIMUM_ALLOWED_ACCESS,
2709                                         CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2710                                         &domain_pol,
2711                                         &result);
2712         if (!NT_STATUS_IS_OK(status)) {
2713                 goto done;
2714         }
2715         if (!NT_STATUS_IS_OK(result)) {
2716                 status = result;
2717                 goto done;
2718         }
2719
2720         /* query builtin aliases */
2721         start_idx = 0;
2722         do {
2723                 if (!builtin) break;
2724
2725                 status = dcerpc_samr_EnumDomainAliases(b, mem_ctx,
2726                                                        &domain_pol,
2727                                                        &start_idx,
2728                                                        &groups,
2729                                                        max_entries,
2730                                                        &num_entries,
2731                                                        &result);
2732                 if (!NT_STATUS_IS_OK(status)) {
2733                         break;
2734                 }
2735                 if (!NT_STATUS_IS_OK(result) &&
2736                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
2737                         status = result;
2738                         break;
2739                 }
2740
2741                 for (i = 0; i < num_entries; i++) {
2742
2743                         const char *description = NULL;
2744
2745                         if (c->opt_long_list_entries) {
2746
2747                                 struct policy_handle alias_pol;
2748                                 union samr_AliasInfo *info = NULL;
2749                                 NTSTATUS _result;
2750
2751                                 status = dcerpc_samr_OpenAlias(b, mem_ctx,
2752                                                                &domain_pol,
2753                                                                0x8,
2754                                                                groups->entries[i].idx,
2755                                                                &alias_pol,
2756                                                                &_result);
2757                                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2758                                         status = dcerpc_samr_QueryAliasInfo(b, mem_ctx,
2759                                                                             &alias_pol,
2760                                                                             3,
2761                                                                             &info,
2762                                                                             &_result);
2763                                         if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2764                                                 status = dcerpc_samr_Close(b, mem_ctx,
2765                                                                            &alias_pol,
2766                                                                            &_result);
2767                                                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(_result)) {
2768                                                         description = info->description.string;
2769                                                 }
2770                                         }
2771                                 }
2772                         }
2773
2774                         if (description != NULL) {
2775                                 printf("%-21.21s %-50.50s\n",
2776                                        groups->entries[i].name.string,
2777                                        description);
2778                         } else {
2779                                 printf("%s\n", groups->entries[i].name.string);
2780                         }
2781                 }
2782         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2783
2784         status = result;
2785
2786  done:
2787         return status;
2788 }
2789
2790 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2791 {
2792         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2793                                rpc_group_list_internals,
2794                                argc, argv);
2795 }
2796
2797 static NTSTATUS rpc_list_group_members(struct net_context *c,
2798                                         struct rpc_pipe_client *pipe_hnd,
2799                                         TALLOC_CTX *mem_ctx,
2800                                         const char *domain_name,
2801                                         const struct dom_sid *domain_sid,
2802                                         struct policy_handle *domain_pol,
2803                                         uint32 rid)
2804 {
2805         NTSTATUS result, status;
2806         struct policy_handle group_pol;
2807         uint32 num_members, *group_rids;
2808         int i;
2809         struct samr_RidAttrArray *rids = NULL;
2810         struct lsa_Strings names;
2811         struct samr_Ids types;
2812         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2813
2814         fstring sid_str;
2815         sid_to_fstring(sid_str, domain_sid);
2816
2817         status = dcerpc_samr_OpenGroup(b, mem_ctx,
2818                                        domain_pol,
2819                                        MAXIMUM_ALLOWED_ACCESS,
2820                                        rid,
2821                                        &group_pol,
2822                                        &result);
2823         if (!NT_STATUS_IS_OK(status)) {
2824                 return status;
2825         }
2826         if (!NT_STATUS_IS_OK(result)) {
2827                 return result;
2828         }
2829
2830         status = dcerpc_samr_QueryGroupMember(b, mem_ctx,
2831                                               &group_pol,
2832                                               &rids,
2833                                               &result);
2834         if (!NT_STATUS_IS_OK(status)) {
2835                 return status;
2836         }
2837         if (!NT_STATUS_IS_OK(result)) {
2838                 return result;
2839         }
2840
2841         num_members = rids->count;
2842         group_rids = rids->rids;
2843
2844         while (num_members > 0) {
2845                 int this_time = 512;
2846
2847                 if (num_members < this_time)
2848                         this_time = num_members;
2849
2850                 status = dcerpc_samr_LookupRids(b, mem_ctx,
2851                                                 domain_pol,
2852                                                 this_time,
2853                                                 group_rids,
2854                                                 &names,
2855                                                 &types,
2856                                                 &result);
2857                 if (!NT_STATUS_IS_OK(status)) {
2858                         return status;
2859                 }
2860                 if (!NT_STATUS_IS_OK(result)) {
2861                         return result;
2862                 }
2863
2864                 /* We only have users as members, but make the output
2865                    the same as the output of alias members */
2866
2867                 for (i = 0; i < this_time; i++) {
2868
2869                         if (c->opt_long_list_entries) {
2870                                 printf("%s-%d %s\\%s %d\n", sid_str,
2871                                        group_rids[i], domain_name,
2872                                        names.names[i].string,
2873                                        SID_NAME_USER);
2874                         } else {
2875                                 printf("%s\\%s\n", domain_name,
2876                                         names.names[i].string);
2877                         }
2878                 }
2879
2880                 num_members -= this_time;
2881                 group_rids += 512;
2882         }
2883
2884         return NT_STATUS_OK;
2885 }
2886
2887 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2888                                         struct rpc_pipe_client *pipe_hnd,
2889                                         TALLOC_CTX *mem_ctx,
2890                                         struct policy_handle *domain_pol,
2891                                         uint32 rid)
2892 {
2893         NTSTATUS result, status;
2894         struct rpc_pipe_client *lsa_pipe;
2895         struct policy_handle alias_pol, lsa_pol;
2896         uint32 num_members;
2897         struct dom_sid *alias_sids;
2898         char **domains;
2899         char **names;
2900         enum lsa_SidType *types;
2901         int i;
2902         struct lsa_SidArray sid_array;
2903         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
2904
2905         status = dcerpc_samr_OpenAlias(b, mem_ctx,
2906                                        domain_pol,
2907                                        MAXIMUM_ALLOWED_ACCESS,
2908                                        rid,
2909                                        &alias_pol,
2910                                        &result);
2911         if (!NT_STATUS_IS_OK(status)) {
2912                 return status;
2913         }
2914         if (!NT_STATUS_IS_OK(result)) {
2915                 return result;
2916         }
2917
2918         status = dcerpc_samr_GetMembersInAlias(b, mem_ctx,
2919                                                &alias_pol,
2920                                                &sid_array,
2921                                                &result);
2922         if (!NT_STATUS_IS_OK(status)) {
2923                 d_fprintf(stderr, _("Couldn't list alias members\n"));
2924                 return status;
2925         }
2926         if (!NT_STATUS_IS_OK(result)) {
2927                 d_fprintf(stderr, _("Couldn't list alias members\n"));
2928                 return result;
2929         }
2930
2931         num_members = sid_array.num_sids;
2932
2933         if (num_members == 0) {
2934                 return NT_STATUS_OK;
2935         }
2936
2937         result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2938                                           &ndr_table_lsarpc.syntax_id,
2939                                           &lsa_pipe);
2940         if (!NT_STATUS_IS_OK(result)) {
2941                 d_fprintf(stderr, _("Couldn't open LSA pipe. Error was %s\n"),
2942                         nt_errstr(result) );
2943                 return result;
2944         }
2945
2946         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2947                                      SEC_FLAG_MAXIMUM_ALLOWED, &lsa_pol);
2948
2949         if (!NT_STATUS_IS_OK(result)) {
2950                 d_fprintf(stderr, _("Couldn't open LSA policy handle\n"));
2951                 TALLOC_FREE(lsa_pipe);
2952                 return result;
2953         }
2954
2955         alias_sids = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, num_members);
2956         if (!alias_sids) {
2957                 d_fprintf(stderr, _("Out of memory\n"));
2958                 TALLOC_FREE(lsa_pipe);
2959                 return NT_STATUS_NO_MEMORY;
2960         }
2961
2962         for (i=0; i<num_members; i++) {
2963                 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2964         }
2965
2966         result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
2967                                      num_members,  alias_sids,
2968                                      &domains, &names, &types);
2969
2970         if (!NT_STATUS_IS_OK(result) &&
2971             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2972                 d_fprintf(stderr, _("Couldn't lookup SIDs\n"));
2973                 TALLOC_FREE(lsa_pipe);
2974                 return result;
2975         }
2976
2977         for (i = 0; i < num_members; i++) {
2978                 fstring sid_str;
2979                 sid_to_fstring(sid_str, &alias_sids[i]);
2980
2981                 if (c->opt_long_list_entries) {
2982                         printf("%s %s\\%s %d\n", sid_str,
2983                                domains[i] ? domains[i] : _("*unknown*"),
2984                                names[i] ? names[i] : _("*unknown*"), types[i]);
2985                 } else {
2986                         if (domains[i])
2987                                 printf("%s\\%s\n", domains[i], names[i]);
2988                         else
2989                                 printf("%s\n", sid_str);
2990                 }
2991         }
2992
2993         TALLOC_FREE(lsa_pipe);
2994         return NT_STATUS_OK;
2995 }
2996
2997 static NTSTATUS rpc_group_members_internals(struct net_context *c,
2998                                         const struct dom_sid *domain_sid,
2999                                         const char *domain_name,
3000                                         struct cli_state *cli,
3001                                         struct rpc_pipe_client *pipe_hnd,
3002                                         TALLOC_CTX *mem_ctx,
3003                                         int argc,
3004                                         const char **argv)
3005 {
3006         NTSTATUS result, status;
3007         struct policy_handle connect_pol, domain_pol;
3008         struct samr_Ids rids, rid_types;
3009         struct lsa_String lsa_acct_name;
3010         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3011
3012         /* Get sam policy handle */
3013
3014         status = dcerpc_samr_Connect2(b, mem_ctx,
3015                                       pipe_hnd->desthost,
3016                                       MAXIMUM_ALLOWED_ACCESS,
3017                                       &connect_pol,
3018                                       &result);
3019         if (!NT_STATUS_IS_OK(status)) {
3020                 return status;
3021         }
3022         if (!NT_STATUS_IS_OK(result)) {
3023                 return result;
3024         }
3025
3026         /* Get domain policy handle */
3027
3028         status = dcerpc_samr_OpenDomain(b, mem_ctx,
3029                                         &connect_pol,
3030                                         MAXIMUM_ALLOWED_ACCESS,
3031                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
3032                                         &domain_pol,
3033                                         &result);
3034         if (!NT_STATUS_IS_OK(status)) {
3035                 return status;
3036         }
3037         if (!NT_STATUS_IS_OK(result)) {
3038                 return result;
3039         }
3040
3041         init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
3042
3043         status = dcerpc_samr_LookupNames(b, mem_ctx,
3044                                          &domain_pol,
3045                                          1,
3046                                          &lsa_acct_name,
3047                                          &rids,
3048                                          &rid_types,
3049                                          &result);
3050         if (!NT_STATUS_IS_OK(status)) {
3051                 return status;
3052         }
3053
3054         if (!NT_STATUS_IS_OK(result)) {
3055
3056                 /* Ok, did not find it in the global sam, try with builtin */
3057
3058                 struct dom_sid sid_Builtin;
3059
3060                 dcerpc_samr_Close(b, mem_ctx, &domain_pol, &result);
3061
3062                 sid_copy(&sid_Builtin, &global_sid_Builtin);
3063
3064                 status = dcerpc_samr_OpenDomain(b, mem_ctx,
3065                                                 &connect_pol,
3066                                                 MAXIMUM_ALLOWED_ACCESS,
3067                                                 &sid_Builtin,
3068                                                 &domain_pol,
3069                                                 &result);
3070                 if (!NT_STATUS_IS_OK(status)) {
3071                         return status;
3072                 }
3073                 if (!NT_STATUS_IS_OK(result)) {
3074                         d_fprintf(stderr, _("Couldn't find group %s\n"),
3075                                   argv[0]);
3076                         return result;
3077                 }
3078
3079                 status = dcerpc_samr_LookupNames(b, mem_ctx,
3080                                                  &domain_pol,
3081                                                  1,
3082                                                  &lsa_acct_name,
3083                                                  &rids,
3084                                                  &rid_types,
3085                                                  &result);
3086                 if (!NT_STATUS_IS_OK(status)) {
3087                         return status;
3088                 }
3089                 if (!NT_STATUS_IS_OK(result)) {
3090                         d_fprintf(stderr, _("Couldn't find group %s\n"),
3091                                   argv[0]);
3092                         return result;
3093                 }
3094         }
3095
3096         if (rids.count != 1) {
3097                 d_fprintf(stderr, _("Couldn't find group %s\n"),
3098                           argv[0]);
3099                 return result;
3100         }
3101
3102         if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
3103                 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
3104                                               domain_sid, &domain_pol,
3105                                               rids.ids[0]);
3106         }
3107
3108         if (rid_types.ids[0] == SID_NAME_ALIAS) {
3109                 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
3110                                               rids.ids[0]);
3111         }
3112
3113         return NT_STATUS_NO_SUCH_GROUP;
3114 }
3115
3116 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
3117 {
3118         if (argc != 1 || c->display_usage) {
3119                 return rpc_group_usage(c, argc, argv);
3120         }
3121
3122         return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
3123                                rpc_group_members_internals,
3124                                argc, argv);
3125 }
3126
3127 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
3128 {
3129         NET_API_STATUS status;
3130         struct GROUP_INFO_0 g0;
3131         uint32_t parm_err;
3132
3133         if (argc != 2) {
3134                 d_printf(_("Usage:\n"));
3135                 d_printf("net rpc group rename group newname\n");
3136                 return -1;
3137         }
3138
3139         g0.grpi0_name = argv[1];
3140
3141         status = NetGroupSetInfo(c->opt_host,
3142                                  argv[0],
3143                                  0,
3144                                  (uint8_t *)&g0,
3145                                  &parm_err);
3146
3147         if (status != 0) {
3148                 d_fprintf(stderr, _("Renaming group %s failed with: %s\n"),
3149                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
3150                         status));
3151                 return -1;
3152         }
3153
3154         return 0;
3155 }
3156
3157 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
3158 {
3159         if (argc != 2 || c->display_usage) {
3160                 return rpc_group_usage(c, argc, argv);
3161         }
3162
3163         return rpc_group_rename_internals(c, argc, argv);
3164 }
3165
3166 /**
3167  * 'net rpc group' entrypoint.
3168  * @param argc  Standard main() style argc.
3169  * @param argv  Standard main() style argv. Initial components are already
3170  *              stripped.
3171  **/
3172
3173 int net_rpc_group(struct net_context *c, int argc, const char **argv)
3174 {
3175         NET_API_STATUS status;
3176
3177         struct functable func[] = {
3178                 {
3179                         "add",
3180                         rpc_group_add,
3181                         NET_TRANSPORT_RPC,
3182                         N_("Create specified group"),
3183                         N_("net rpc group add\n"
3184                            "    Create specified group")
3185                 },
3186                 {
3187                         "delete",
3188                         rpc_group_delete,
3189                         NET_TRANSPORT_RPC,
3190                         N_("Delete specified group"),
3191                         N_("net rpc group delete\n"
3192                            "    Delete specified group")
3193                 },
3194                 {
3195                         "addmem",
3196                         rpc_group_addmem,
3197                         NET_TRANSPORT_RPC,
3198                         N_("Add member to group"),
3199                         N_("net rpc group addmem\n"
3200                            "    Add member to group")
3201                 },
3202                 {
3203                         "delmem",
3204                         rpc_group_delmem,
3205                         NET_TRANSPORT_RPC,
3206                         N_("Remove member from group"),
3207                         N_("net rpc group delmem\n"
3208                            "    Remove member from group")
3209                 },
3210                 {
3211                         "list",
3212                         rpc_group_list,
3213                         NET_TRANSPORT_RPC,
3214                         N_("List groups"),
3215                         N_("net rpc group list\n"
3216                            "    List groups")
3217                 },
3218                 {
3219                         "members",
3220                         rpc_group_members,
3221                         NET_TRANSPORT_RPC,
3222                         N_("List group members"),
3223                         N_("net rpc group members\n"
3224                            "    List group members")
3225                 },
3226                 {
3227                         "rename",
3228                         rpc_group_rename,
3229                         NET_TRANSPORT_RPC,
3230                         N_("Rename group"),
3231                         N_("net rpc group rename\n"
3232                            "    Rename group")
3233                 },
3234                 {NULL, NULL, 0, NULL, NULL}
3235         };
3236
3237         status = libnetapi_net_init(&c->netapi_ctx);
3238         if (status != 0) {
3239                 return -1;
3240         }
3241         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
3242         libnetapi_set_password(c->netapi_ctx, c->opt_password);
3243         if (c->opt_kerberos) {
3244                 libnetapi_set_use_kerberos(c->netapi_ctx);
3245         }
3246
3247         if (argc == 0) {
3248                 if (c->display_usage) {
3249                         d_printf(_("Usage:\n"));
3250                         d_printf(_("net rpc group\n"
3251                                    "    Alias for net rpc group list global "
3252                                    "local builtin\n"));
3253                         net_display_usage_from_functable(func);
3254                         return 0;
3255                 }
3256
3257                 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
3258                                        rpc_group_list_internals,
3259                                        argc, argv);
3260         }
3261
3262         return net_run_function(c, argc, argv, "net rpc group", func);
3263 }
3264
3265 /****************************************************************************/
3266
3267 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
3268 {
3269         return net_share_usage(c, argc, argv);
3270 }
3271
3272 /**
3273  * Add a share on a remote RPC server.
3274  *
3275  * @param argc  Standard main() style argc.
3276  * @param argv  Standard main() style argv. Initial components are already
3277  *              stripped.
3278  *
3279  * @return A shell status integer (0 for success).
3280  **/
3281
3282 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3283 {
3284         NET_API_STATUS status;
3285         char *sharename;
3286         char *path;
3287         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3288         uint32 num_users=0, perms=0;
3289         char *password=NULL; /* don't allow a share password */
3290         struct SHARE_INFO_2 i2;
3291         uint32_t parm_error = 0;
3292
3293         if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3294                 return rpc_share_usage(c, argc, argv);
3295         }
3296
3297         if ((sharename = talloc_strdup(c, argv[0])) == NULL) {
3298                 return -1;
3299         }
3300
3301         path = strchr(sharename, '=');
3302         if (!path) {
3303                 return -1;
3304         }
3305
3306         *path++ = '\0';
3307
3308         i2.shi2_netname         = sharename;
3309         i2.shi2_type            = type;
3310         i2.shi2_remark          = c->opt_comment;
3311         i2.shi2_permissions     = perms;
3312         i2.shi2_max_uses        = c->opt_maxusers;
3313         i2.shi2_current_uses    = num_users;
3314         i2.shi2_path            = path;
3315         i2.shi2_passwd          = password;
3316
3317         status = NetShareAdd(c->opt_host,
3318                              2,
3319                              (uint8_t *)&i2,
3320                              &parm_error);
3321         if (status != 0) {
3322                 printf(_("NetShareAdd failed with: %s\n"),
3323                         libnetapi_get_error_string(c->netapi_ctx, status));
3324         }
3325
3326         return status;
3327 }
3328
3329 /**
3330  * Delete a share on a remote RPC server.
3331  *
3332  * @param domain_sid The domain sid acquired from the remote server.
3333  * @param argc  Standard main() style argc.
3334  * @param argv  Standard main() style argv. Initial components are already
3335  *              stripped.
3336  *
3337  * @return A shell status integer (0 for success).
3338  **/
3339 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3340 {
3341         if (argc < 1 || c->display_usage) {
3342                 return rpc_share_usage(c, argc, argv);
3343         }
3344
3345         return NetShareDel(c->opt_host, argv[0], 0);
3346 }
3347
3348 /**
3349  * Formatted print of share info
3350  *
3351  * @param r  pointer to SHARE_INFO_1 to format
3352  **/
3353
3354 static void display_share_info_1(struct net_context *c,
3355                                  struct SHARE_INFO_1 *r)
3356 {
3357         if (c->opt_long_list_entries) {
3358                 d_printf("%-12s %-8.8s %-50s\n",
3359                          r->shi1_netname,
3360                          net_share_type_str(r->shi1_type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)),
3361                          r->shi1_remark);
3362         } else {
3363                 d_printf("%s\n", r->shi1_netname);
3364         }
3365 }
3366
3367 static WERROR get_share_info(struct net_context *c,
3368                              struct rpc_pipe_client *pipe_hnd,
3369                              TALLOC_CTX *mem_ctx,
3370                              uint32 level,
3371                              int argc,
3372                              const char **argv,
3373                              struct srvsvc_NetShareInfoCtr *info_ctr)
3374 {
3375         WERROR result;
3376         NTSTATUS status;
3377         union srvsvc_NetShareInfo info;
3378         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
3379
3380         /* no specific share requested, enumerate all */
3381         if (argc == 0) {
3382
3383                 uint32_t preferred_len = 0xffffffff;
3384                 uint32_t total_entries = 0;
3385                 uint32_t resume_handle = 0;
3386
3387                 info_ctr->level = level;
3388
3389                 status = dcerpc_srvsvc_NetShareEnumAll(b, mem_ctx,
3390                                                        pipe_hnd->desthost,
3391                                                        info_ctr,
3392                                                        preferred_len,
3393                                                        &total_entries,
3394                                                        &resume_handle,
3395                                                        &result);
3396                 if (!NT_STATUS_IS_OK(status)) {
3397                         return ntstatus_to_werror(status);
3398                 }
3399                 return result;
3400         }
3401
3402         /* request just one share */
3403         status = dcerpc_srvsvc_NetShareGetInfo(b, mem_ctx,
3404                                                pipe_hnd->desthost,
3405                                                argv[0],
3406                                                level,
3407                                                &info,
3408                                                &result);
3409
3410         if (!NT_STATUS_IS_OK(status)) {
3411                 result = ntstatus_to_werror(status);
3412                 goto done;
3413         }
3414
3415         if (!W_ERROR_IS_OK(result)) {
3416                 goto done;
3417         }
3418
3419         /* construct ctr */
3420         ZERO_STRUCTP(info_ctr);
3421
3422         info_ctr->level = level;
3423
3424         switch (level) {
3425         case 1:
3426         {
3427                 struct srvsvc_NetShareCtr1 *ctr1;
3428
3429                 ctr1 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr1);
3430                 W_ERROR_HAVE_NO_MEMORY(ctr1);
3431
3432                 ctr1->count = 1;
3433                 ctr1->array = info.info1;
3434
3435                 info_ctr->ctr.ctr1 = ctr1;
3436
3437                 break;
3438         }
3439         case 2:
3440         {
3441                 struct srvsvc_NetShareCtr2 *ctr2;
3442
3443                 ctr2 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr2);
3444                 W_ERROR_HAVE_NO_MEMORY(ctr2);
3445
3446                 ctr2->count = 1;
3447                 ctr2->array = info.info2;
3448
3449                 info_ctr->ctr.ctr2 = ctr2;
3450
3451                 break;
3452         }
3453         case 502:
3454         {
3455                 struct srvsvc_NetShareCtr502 *ctr502;
3456
3457                 ctr502 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr502);
3458                 W_ERROR_HAVE_NO_MEMORY(ctr502);
3459
3460                 ctr502->count = 1;
3461                 ctr502->array = info.info502;
3462
3463                 info_ctr->ctr.ctr502 = ctr502;
3464
3465                 break;
3466         }
3467         } /* switch */
3468 done:
3469         return result;
3470 }
3471
3472 /***
3473  * 'net rpc share list' entrypoint.
3474  * @param argc  Standard main() style argc.
3475  * @param argv  Standard main() style argv. Initial components are already
3476  *              stripped.
3477  **/
3478 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3479 {
3480         NET_API_STATUS status;
3481         struct SHARE_INFO_1 *i1 = NULL;
3482         uint32_t entries_read = 0;
3483         uint32_t total_entries = 0;
3484         uint32_t resume_handle = 0;
3485         uint32_t i, level = 1;
3486
3487         if (c->display_usage) {
3488                 d_printf(  "%s\n"
3489                            "net rpc share list\n"
3490                            "    %s\n",
3491                          _("Usage:"),
3492                          _("List shares on remote server"));
3493                 return 0;
3494         }
3495
3496         status = NetShareEnum(c->opt_host,
3497                               level,
3498                               (uint8_t **)(void *)&i1,
3499                               (uint32_t)-1,
3500                               &entries_read,
3501                               &total_entries,
3502                               &resume_handle);
3503         if (status != 0) {
3504                 goto done;
3505         }
3506
3507         /* Display results */
3508
3509         if (c->opt_long_list_entries) {
3510                 d_printf(_(
3511         "\nEnumerating shared resources (exports) on remote server:\n\n"
3512         "\nShare name   Type     Description\n"
3513         "----------   ----     -----------\n"));
3514         }
3515         for (i = 0; i < entries_read; i++)
3516                 display_share_info_1(c, &i1[i]);
3517  done:
3518         return status;
3519 }
3520
3521 static bool check_share_availability(struct cli_state *cli, const char *netname)
3522 {
3523         NTSTATUS status;
3524
3525         status = cli_tcon_andx(cli, netname, "A:", "", 0);
3526         if (!NT_STATUS_IS_OK(status)) {
3527                 d_printf(_("skipping   [%s]: not a file share.\n"), netname);
3528                 return false;
3529         }
3530
3531         status = cli_tdis(cli);
3532         if (!NT_STATUS_IS_OK(status)) {
3533                 d_printf(_("cli_tdis returned %s\n"), nt_errstr(status));
3534                 return false;
3535         }
3536
3537         return true;
3538 }
3539
3540 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3541                                const char *netname, uint32 type)
3542 {
3543         /* only support disk shares */
3544         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3545                 printf(_("share [%s] is not a diskshare (type: %x)\n"), netname,
3546                        type);
3547                 return false;
3548         }
3549
3550         /* skip builtin shares */
3551         /* FIXME: should print$ be added too ? */
3552         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3553             strequal(netname,"global"))
3554                 return false;
3555
3556         if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3557                 printf(_("excluding  [%s]\n"), netname);
3558                 return false;
3559         }
3560
3561         return check_share_availability(cli, netname);
3562 }
3563
3564 /**
3565  * Migrate shares from a remote RPC server to the local RPC server.
3566  *
3567  * All parameters are provided by the run_rpc_command function, except for
3568  * argc, argv which are passed through.
3569  *
3570  * @param domain_sid The domain sid acquired from the remote server.
3571  * @param cli A cli_state connected to the server.
3572  * @param mem_ctx Talloc context, destroyed on completion of the function.
3573  * @param argc  Standard main() style argc.
3574  * @param argv  Standard main() style argv. Initial components are already
3575  *              stripped.
3576  *
3577  * @return Normal NTSTATUS return.
3578  **/
3579
3580 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3581                                                 const struct dom_sid *domain_sid,
3582                                                 const char *domain_name,
3583                                                 struct cli_state *cli,
3584                                                 struct rpc_pipe_client *pipe_hnd,
3585                                                 TALLOC_CTX *mem_ctx,
3586                                                 int argc,
3587                                                 const char **argv)
3588 {
3589         WERROR result;
3590         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3591         struct srvsvc_NetShareInfoCtr ctr_src;
3592         uint32 i;
3593         struct rpc_pipe_client *srvsvc_pipe = NULL;
3594         struct cli_state *cli_dst = NULL;
3595         uint32 level = 502; /* includes secdesc */
3596         uint32_t parm_error = 0;
3597         struct dcerpc_binding_handle *b;
3598
3599         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3600                                 &ctr_src);
3601         if (!W_ERROR_IS_OK(result))
3602                 goto done;
3603
3604         /* connect destination PI_SRVSVC */
3605         nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3606                                      &ndr_table_srvsvc.syntax_id);
3607         if (!NT_STATUS_IS_OK(nt_status))
3608                 return nt_status;
3609
3610         b = srvsvc_pipe->binding_handle;
3611
3612         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3613
3614                 union srvsvc_NetShareInfo info;
3615                 struct srvsvc_NetShareInfo502 info502 =
3616                         ctr_src.ctr.ctr502->array[i];
3617
3618                 /* reset error-code */
3619                 nt_status = NT_STATUS_UNSUCCESSFUL;
3620
3621                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3622                         continue;
3623
3624                 /* finally add the share on the dst server */
3625
3626                 printf(_("migrating: [%s], path: %s, comment: %s, without "
3627                          "share-ACLs\n"),
3628                         info502.name, info502.path, info502.comment);
3629
3630                 info.info502 = &info502;
3631
3632                 nt_status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
3633                                                       srvsvc_pipe->desthost,
3634                                                       502,
3635                                                       &info,
3636                                                       &parm_error,
3637                                                       &result);
3638                 if (!NT_STATUS_IS_OK(nt_status)) {
3639                         printf(_("cannot add share: %s\n"),
3640                                 nt_errstr(nt_status));
3641                         goto done;
3642                 }
3643                 if (W_ERROR_V(result) == W_ERROR_V(WERR_FILE_EXISTS)) {
3644                         printf(_("           [%s] does already exist\n"),
3645                                 info502.name);
3646                         continue;
3647                 }
3648
3649                 if (!W_ERROR_IS_OK(result)) {
3650                         nt_status = werror_to_ntstatus(result);
3651                         printf(_("cannot add share: %s\n"),
3652                                 win_errstr(result));
3653                         goto done;
3654                 }
3655
3656         }
3657
3658         nt_status = NT_STATUS_OK;
3659
3660 done:
3661         if (cli_dst) {
3662                 cli_shutdown(cli_dst);
3663         }
3664
3665         return nt_status;
3666
3667 }
3668
3669 /**
3670  * Migrate shares from a RPC server to another.
3671  *
3672  * @param argc  Standard main() style argc.
3673  * @param argv  Standard main() style argv. Initial components are already
3674  *              stripped.
3675  *
3676  * @return A shell status integer (0 for success).
3677  **/