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