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