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