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