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