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