Refactoring: Change calling conventions for cli_rpc_pipe_open_ntlmssp
[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
26 static int net_mode_share;
27 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask);
28
29 /**
30  * @file net_rpc.c
31  *
32  * @brief RPC based subcommands for the 'net' utility.
33  *
34  * This file should contain much of the functionality that used to
35  * be found in rpcclient, execpt that the commands should change
36  * less often, and the fucntionality should be sane (the user is not
37  * expected to know a rid/sid before they conduct an operation etc.)
38  *
39  * @todo Perhaps eventually these should be split out into a number
40  * of files, as this could get quite big.
41  **/
42
43
44 /**
45  * Many of the RPC functions need the domain sid.  This function gets
46  *  it at the start of every run
47  *
48  * @param cli A cli_state already connected to the remote machine
49  *
50  * @return The Domain SID of the remote machine.
51  **/
52
53 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
54                                    DOM_SID **domain_sid,
55                                    const char **domain_name)
56 {
57         struct rpc_pipe_client *lsa_pipe;
58         POLICY_HND pol;
59         NTSTATUS result = NT_STATUS_OK;
60         union lsa_PolicyInformation *info = NULL;
61
62         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
63                                           &lsa_pipe);
64         if (!NT_STATUS_IS_OK(result)) {
65                 d_fprintf(stderr, "Could not initialise lsa pipe\n");
66                 return result;
67         }
68
69         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
70                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
71                                      &pol);
72         if (!NT_STATUS_IS_OK(result)) {
73                 d_fprintf(stderr, "open_policy failed: %s\n",
74                           nt_errstr(result));
75                 return result;
76         }
77
78         result = rpccli_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx,
79                                             &pol,
80                                             LSA_POLICY_INFO_ACCOUNT_DOMAIN,
81                                             &info);
82         if (!NT_STATUS_IS_OK(result)) {
83                 d_fprintf(stderr, "lsaquery failed: %s\n",
84                           nt_errstr(result));
85                 return result;
86         }
87
88         *domain_name = info->account_domain.name.string;
89         *domain_sid = info->account_domain.sid;
90
91         rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
92         TALLOC_FREE(lsa_pipe);
93
94         return NT_STATUS_OK;
95 }
96
97 /**
98  * Run a single RPC command, from start to finish.
99  *
100  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
101  * @param conn_flag a NET_FLAG_ combination.  Passed to
102  *                   net_make_ipc_connection.
103  * @param argc  Standard main() style argc.
104  * @param argv  Standard main() style argv. Initial components are already
105  *              stripped.
106  * @return A shell status integer (0 for success).
107  */
108
109 int run_rpc_command(struct net_context *c,
110                         struct cli_state *cli_arg,
111                         const int pipe_idx,
112                         int conn_flags,
113                         rpc_command_fn fn,
114                         int argc,
115                         const char **argv)
116 {
117         struct cli_state *cli = NULL;
118         struct rpc_pipe_client *pipe_hnd = NULL;
119         TALLOC_CTX *mem_ctx;
120         NTSTATUS nt_status;
121         DOM_SID *domain_sid;
122         const char *domain_name;
123
124         /* make use of cli_state handed over as an argument, if possible */
125         if (!cli_arg) {
126                 nt_status = net_make_ipc_connection(c, conn_flags, &cli);
127                 if (!NT_STATUS_IS_OK(nt_status)) {
128                         DEBUG(1, ("failed to make ipc connection: %s\n",
129                                   nt_errstr(nt_status)));
130                         return -1;
131                 }
132         } else {
133                 cli = cli_arg;
134         }
135
136         if (!cli) {
137                 return -1;
138         }
139
140         /* Create mem_ctx */
141
142         if (!(mem_ctx = talloc_init("run_rpc_command"))) {
143                 DEBUG(0, ("talloc_init() failed\n"));
144                 cli_shutdown(cli);
145                 return -1;
146         }
147
148         nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
149                                               &domain_name);
150         if (!NT_STATUS_IS_OK(nt_status)) {
151                 cli_shutdown(cli);
152                 return -1;
153         }
154
155         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
156                 if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) {
157                         /* Always try and create an schannel netlogon pipe. */
158                         pipe_hnd = cli_rpc_pipe_open_schannel(cli, pipe_idx,
159                                                         PIPE_AUTH_LEVEL_PRIVACY,
160                                                         domain_name,
161                                                         &nt_status);
162                         if (!pipe_hnd) {
163                                 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
164                                         nt_errstr(nt_status) ));
165                                 cli_shutdown(cli);
166                                 return -1;
167                         }
168                 } else {
169                         if (conn_flags & NET_FLAGS_SEAL) {
170                                 nt_status = cli_rpc_pipe_open_ntlmssp(
171                                         cli, cli_get_iface(pipe_idx),
172                                         PIPE_AUTH_LEVEL_PRIVACY,
173                                         lp_workgroup(), c->opt_user_name,
174                                         c->opt_password, &pipe_hnd);
175                         } else {
176                                 nt_status = cli_rpc_pipe_open_noauth(
177                                         cli, cli_get_iface(pipe_idx),
178                                         &pipe_hnd);
179                         }
180                         if (!NT_STATUS_IS_OK(nt_status)) {
181                                 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
182                                         cli_get_pipe_name(pipe_idx),
183                                         nt_errstr(nt_status) ));
184                                 cli_shutdown(cli);
185                                 return -1;
186                         }
187                 }
188         }
189
190         nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
191
192         if (!NT_STATUS_IS_OK(nt_status)) {
193                 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
194         } else {
195                 DEBUG(5, ("rpc command function succedded\n"));
196         }
197
198         if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
199                 if (pipe_hnd) {
200                         TALLOC_FREE(pipe_hnd);
201                 }
202         }
203
204         /* close the connection only if it was opened here */
205         if (!cli_arg) {
206                 cli_shutdown(cli);
207         }
208
209         talloc_destroy(mem_ctx);
210         return (!NT_STATUS_IS_OK(nt_status));
211 }
212
213 /**
214  * Force a change of the trust acccount password.
215  *
216  * All parameters are provided by the run_rpc_command function, except for
217  * argc, argv which are passed through.
218  *
219  * @param domain_sid The domain sid acquired from the remote server.
220  * @param cli A cli_state connected to the server.
221  * @param mem_ctx Talloc context, destroyed on completion of the function.
222  * @param argc  Standard main() style argc.
223  * @param argv  Standard main() style argv. Initial components are already
224  *              stripped.
225  *
226  * @return Normal NTSTATUS return.
227  **/
228
229 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
230                                         const DOM_SID *domain_sid,
231                                         const char *domain_name,
232                                         struct cli_state *cli,
233                                         struct rpc_pipe_client *pipe_hnd,
234                                         TALLOC_CTX *mem_ctx,
235                                         int argc,
236                                         const char **argv)
237 {
238
239         return trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
240 }
241
242 /**
243  * Force a change of the trust acccount password.
244  *
245  * @param argc  Standard main() style argc.
246  * @param argv  Standard main() style argv. Initial components are already
247  *              stripped.
248  *
249  * @return A shell status integer (0 for success).
250  **/
251
252 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
253 {
254         if (c->display_usage) {
255                 d_printf("Usage:\n"
256                          "net rpc changetrustpw\n"
257                          "    Change the machine trust password\n");
258                 return 0;
259         }
260
261         return run_rpc_command(c, NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
262                                rpc_changetrustpw_internals,
263                                argc, argv);
264 }
265
266 /**
267  * Join a domain, the old way.
268  *
269  * This uses 'machinename' as the inital password, and changes it.
270  *
271  * The password should be created with 'server manager' or equiv first.
272  *
273  * All parameters are provided by the run_rpc_command function, except for
274  * argc, argv which are passed through.
275  *
276  * @param domain_sid The domain sid acquired from the remote server.
277  * @param cli A cli_state connected to the server.
278  * @param mem_ctx Talloc context, destroyed on completion of the function.
279  * @param argc  Standard main() style argc.
280  * @param argv  Standard main() style argv. Initial components are already
281  *              stripped.
282  *
283  * @return Normal NTSTATUS return.
284  **/
285
286 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
287                                         const DOM_SID *domain_sid,
288                                         const char *domain_name,
289                                         struct cli_state *cli,
290                                         struct rpc_pipe_client *pipe_hnd,
291                                         TALLOC_CTX *mem_ctx,
292                                         int argc,
293                                         const char **argv)
294 {
295
296         fstring trust_passwd;
297         unsigned char orig_trust_passwd_hash[16];
298         NTSTATUS result;
299         uint32 sec_channel_type;
300
301         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
302                                           &pipe_hnd);
303         if (!NT_STATUS_IS_OK(result)) {
304                 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
305                         "error was %s\n",
306                         cli->desthost,
307                         nt_errstr(result) ));
308                 return result;
309         }
310
311         /*
312            check what type of join - if the user want's to join as
313            a BDC, the server must agree that we are a BDC.
314         */
315         if (argc >= 0) {
316                 sec_channel_type = get_sec_channel_type(argv[0]);
317         } else {
318                 sec_channel_type = get_sec_channel_type(NULL);
319         }
320
321         fstrcpy(trust_passwd, global_myname());
322         strlower_m(trust_passwd);
323
324         /*
325          * Machine names can be 15 characters, but the max length on
326          * a password is 14.  --jerry
327          */
328
329         trust_passwd[14] = '\0';
330
331         E_md4hash(trust_passwd, orig_trust_passwd_hash);
332
333         result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
334                                               orig_trust_passwd_hash,
335                                               sec_channel_type);
336
337         if (NT_STATUS_IS_OK(result))
338                 printf("Joined domain %s.\n", c->opt_target_workgroup);
339
340
341         if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
342                 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
343                 result = NT_STATUS_UNSUCCESSFUL;
344         }
345
346         return result;
347 }
348
349 /**
350  * Join a domain, the old way.
351  *
352  * @param argc  Standard main() style argc.
353  * @param argv  Standard main() style argv. Initial components are already
354  *              stripped.
355  *
356  * @return A shell status integer (0 for success).
357  **/
358
359 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
360 {
361         return run_rpc_command(c, NULL, PI_NETLOGON,
362                                NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
363                                rpc_oldjoin_internals,
364                                argc, argv);
365 }
366
367 /**
368  * Join a domain, the old way.  This function exists to allow
369  * the message to be displayed when oldjoin was explicitly
370  * requested, but not when it was implied by "net rpc join".
371  *
372  * @param argc  Standard main() style argc.
373  * @param argv  Standard main() style argv. Initial components are already
374  *              stripped.
375  *
376  * @return A shell status integer (0 for success).
377  **/
378
379 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
380 {
381         int rc = -1;
382
383         if (c->display_usage) {
384                 d_printf("Usage:\n"
385                          "net rpc oldjoin\n"
386                          "    Join a domain the old way\n");
387                 return 0;
388         }
389
390         rc = net_rpc_perform_oldjoin(c, argc, argv);
391
392         if (rc) {
393                 d_fprintf(stderr, "Failed to join domain\n");
394         }
395
396         return rc;
397 }
398
399 /**
400  * 'net rpc join' entrypoint.
401  * @param argc  Standard main() style argc.
402  * @param argv  Standard main() style argv. Initial components are already
403  *              stripped
404  *
405  * Main 'net_rpc_join()' (where the admin username/password is used) is
406  * in net_rpc_join.c.
407  * Try to just change the password, but if that doesn't work, use/prompt
408  * for a username/password.
409  **/
410
411 int net_rpc_join(struct net_context *c, int argc, const char **argv)
412 {
413         if (c->display_usage) {
414                 d_printf("Usage:\n"
415                          "net rpc join -U <username>[%%password] <type>\n"
416                          "  Join a domain\n"
417                          "    username\tName of the admin user"
418                          "    password\tPassword of the admin user, will "
419                          "prompt if not specified\n"
420                          "    type\tCan be one of the following:\n"
421                          "\t\tMEMBER\tJoin as member server (default)\n"
422                          "\t\tBDC\tJoin as BDC\n"
423                          "\t\tPDC\tJoin as PDC\n");
424                 return 0;
425         }
426
427         if (lp_server_role() == ROLE_STANDALONE) {
428                 d_printf("cannot join as standalone machine\n");
429                 return -1;
430         }
431
432         if (strlen(global_myname()) > 15) {
433                 d_printf("Our netbios name can be at most 15 chars long, "
434                          "\"%s\" is %u chars long\n",
435                          global_myname(), (unsigned int)strlen(global_myname()));
436                 return -1;
437         }
438
439         if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
440                 return 0;
441
442         return net_rpc_join_newstyle(c, argc, argv);
443 }
444
445 /**
446  * display info about a rpc domain
447  *
448  * All parameters are provided by the run_rpc_command function, except for
449  * argc, argv which are passed through.
450  *
451  * @param domain_sid The domain sid acquired from the remote server
452  * @param cli A cli_state connected to the server.
453  * @param mem_ctx Talloc context, destroyed on completion of the function.
454  * @param argc  Standard main() style argc.
455  * @param argv  Standard main() style argv. Initial components are already
456  *              stripped.
457  *
458  * @return Normal NTSTATUS return.
459  **/
460
461 NTSTATUS rpc_info_internals(struct net_context *c,
462                         const DOM_SID *domain_sid,
463                         const char *domain_name,
464                         struct cli_state *cli,
465                         struct rpc_pipe_client *pipe_hnd,
466                         TALLOC_CTX *mem_ctx,
467                         int argc,
468                         const char **argv)
469 {
470         POLICY_HND connect_pol, domain_pol;
471         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
472         union samr_DomainInfo *info = NULL;
473         fstring sid_str;
474
475         sid_to_fstring(sid_str, domain_sid);
476
477         /* Get sam policy handle */
478         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
479                                       pipe_hnd->desthost,
480                                       MAXIMUM_ALLOWED_ACCESS,
481                                       &connect_pol);
482         if (!NT_STATUS_IS_OK(result)) {
483                 d_fprintf(stderr, "Could not connect to SAM: %s\n", nt_errstr(result));
484                 goto done;
485         }
486
487         /* Get domain policy handle */
488         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
489                                         &connect_pol,
490                                         MAXIMUM_ALLOWED_ACCESS,
491                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
492                                         &domain_pol);
493         if (!NT_STATUS_IS_OK(result)) {
494                 d_fprintf(stderr, "Could not open domain: %s\n", nt_errstr(result));
495                 goto done;
496         }
497
498         result = rpccli_samr_QueryDomainInfo(pipe_hnd, mem_ctx,
499                                              &domain_pol,
500                                              2,
501                                              &info);
502         if (NT_STATUS_IS_OK(result)) {
503                 d_printf("Domain Name: %s\n", info->info2.domain_name.string);
504                 d_printf("Domain SID: %s\n", sid_str);
505                 d_printf("Sequence number: %llu\n",
506                         (unsigned long long)info->info2.sequence_num);
507                 d_printf("Num users: %u\n", info->info2.num_users);
508                 d_printf("Num domain groups: %u\n", info->info2.num_groups);
509                 d_printf("Num local groups: %u\n", info->info2.num_aliases);
510         }
511
512  done:
513         return result;
514 }
515
516 /**
517  * 'net rpc info' entrypoint.
518  * @param argc  Standard main() style argc.
519  * @param argv  Standard main() style argv. Initial components are already
520  *              stripped.
521  **/
522
523 int net_rpc_info(struct net_context *c, int argc, const char **argv)
524 {
525         if (c->display_usage) {
526                 d_printf("Usage:\n"
527                          "net rpc info\n"
528                          "  Display information about the domain\n");
529                 return 0;
530         }
531
532         return run_rpc_command(c, NULL, PI_SAMR, NET_FLAGS_PDC,
533                                rpc_info_internals,
534                                argc, argv);
535 }
536
537 /**
538  * Fetch domain SID into the local secrets.tdb.
539  *
540  * All parameters are provided by the run_rpc_command function, except for
541  * argc, argv which are passed through.
542  *
543  * @param domain_sid The domain sid acquired from the remote server.
544  * @param cli A cli_state connected to the server.
545  * @param mem_ctx Talloc context, destroyed on completion of the function.
546  * @param argc  Standard main() style argc.
547  * @param argv  Standard main() style argv. Initial components are already
548  *              stripped.
549  *
550  * @return Normal NTSTATUS return.
551  **/
552
553 static NTSTATUS rpc_getsid_internals(struct net_context *c,
554                         const DOM_SID *domain_sid,
555                         const char *domain_name,
556                         struct cli_state *cli,
557                         struct rpc_pipe_client *pipe_hnd,
558                         TALLOC_CTX *mem_ctx,
559                         int argc,
560                         const char **argv)
561 {
562         fstring sid_str;
563
564         sid_to_fstring(sid_str, domain_sid);
565         d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
566                  sid_str, domain_name);
567
568         if (!secrets_store_domain_sid(domain_name, domain_sid)) {
569                 DEBUG(0,("Can't store domain SID\n"));
570                 return NT_STATUS_UNSUCCESSFUL;
571         }
572
573         return NT_STATUS_OK;
574 }
575
576 /**
577  * 'net rpc getsid' entrypoint.
578  * @param argc  Standard main() style argc.
579  * @param argv  Standard main() style argv. Initial components are already
580  *              stripped.
581  **/
582
583 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
584 {
585         if (c->display_usage) {
586                 d_printf("Usage:\n"
587                          "net rpc getsid\n"
588                          "    Fetch domain SID into local secrets.tdb\n");
589                 return 0;
590         }
591
592         return run_rpc_command(c, NULL, PI_SAMR,
593                                NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
594                                rpc_getsid_internals,
595                                argc, argv);
596 }
597
598 /****************************************************************************/
599
600 /**
601  * Basic usage function for 'net rpc user'.
602  * @param argc  Standard main() style argc.
603  * @param argv  Standard main() style argv. Initial components are already
604  *              stripped.
605  **/
606
607 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
608 {
609         return net_user_usage(c, argc, argv);
610 }
611
612 /**
613  * Add a new user to a remote RPC server.
614  *
615  * @param argc  Standard main() style argc.
616  * @param argv  Standard main() style argv. Initial components are already
617  *              stripped.
618  *
619  * @return A shell status integer (0 for success).
620  **/
621
622 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
623 {
624         NET_API_STATUS status;
625         struct USER_INFO_1 info1;
626         uint32_t parm_error = 0;
627
628         if (argc < 1 || c->display_usage) {
629                 rpc_user_usage(c, argc, argv);
630                 return 0;
631         }
632
633         ZERO_STRUCT(info1);
634
635         info1.usri1_name = argv[0];
636         if (argc == 2) {
637                 info1.usri1_password = argv[1];
638         }
639
640         status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
641
642         if (status != 0) {
643                 d_fprintf(stderr, "Failed to add user '%s' with: %s.\n",
644                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
645                                                             status));
646                 return -1;
647         } else {
648                 d_printf("Added user '%s'.\n", argv[0]);
649         }
650
651         return 0;
652 }
653
654 /**
655  * Rename a user on a remote RPC server.
656  *
657  * All parameters are provided by the run_rpc_command function, except for
658  * argc, argv which are passed through.
659  *
660  * @param domain_sid The domain sid acquired from the remote server.
661  * @param cli A cli_state connected to the server.
662  * @param mem_ctx Talloc context, destroyed on completion of the function.
663  * @param argc  Standard main() style argc.
664  * @param argv  Standard main() style argv. Initial components are already
665  *              stripped.
666  *
667  * @return Normal NTSTATUS return.
668  **/
669
670 static NTSTATUS rpc_user_rename_internals(struct net_context *c,
671                                         const DOM_SID *domain_sid,
672                                         const char *domain_name,
673                                         struct cli_state *cli,
674                                         struct rpc_pipe_client *pipe_hnd,
675                                         TALLOC_CTX *mem_ctx,
676                                         int argc,
677                                         const char **argv)
678 {
679         POLICY_HND connect_pol, domain_pol, user_pol;
680         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
681         uint32 info_level = 7;
682         const char *old_name, *new_name;
683         struct samr_Ids user_rids, name_types;
684         struct lsa_String lsa_acct_name;
685         union samr_UserInfo *info = NULL;
686
687         if (argc != 2 || c->display_usage) {
688                 rpc_user_usage(c, argc, argv);
689                 return NT_STATUS_OK;
690         }
691
692         old_name = argv[0];
693         new_name = argv[1];
694
695         /* Get sam policy handle */
696
697         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
698                                       pipe_hnd->desthost,
699                                       MAXIMUM_ALLOWED_ACCESS,
700                                       &connect_pol);
701
702         if (!NT_STATUS_IS_OK(result)) {
703                 goto done;
704         }
705
706         /* Get domain policy handle */
707
708         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
709                                         &connect_pol,
710                                         MAXIMUM_ALLOWED_ACCESS,
711                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
712                                         &domain_pol);
713         if (!NT_STATUS_IS_OK(result)) {
714                 goto done;
715         }
716
717         init_lsa_String(&lsa_acct_name, old_name);
718
719         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
720                                          &domain_pol,
721                                          1,
722                                          &lsa_acct_name,
723                                          &user_rids,
724                                          &name_types);
725         if (!NT_STATUS_IS_OK(result)) {
726                 goto done;
727         }
728
729         /* Open domain user */
730         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
731                                       &domain_pol,
732                                       MAXIMUM_ALLOWED_ACCESS,
733                                       user_rids.ids[0],
734                                       &user_pol);
735
736         if (!NT_STATUS_IS_OK(result)) {
737                 goto done;
738         }
739
740         /* Query user info */
741         result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
742                                            &user_pol,
743                                            info_level,
744                                            &info);
745
746         if (!NT_STATUS_IS_OK(result)) {
747                 goto done;
748         }
749
750         init_samr_user_info7(&info->info7, new_name);
751
752         /* Set new name */
753         result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
754                                           &user_pol,
755                                           info_level,
756                                           info);
757
758         if (!NT_STATUS_IS_OK(result)) {
759                 goto done;
760         }
761
762  done:
763         if (!NT_STATUS_IS_OK(result)) {
764                 d_fprintf(stderr, "Failed to rename user from %s to %s - %s\n", old_name, new_name, 
765                          nt_errstr(result));
766         } else {
767                 d_printf("Renamed user from %s to %s\n", old_name, new_name);
768         }
769         return result;
770 }
771
772 /**
773  * Rename a user on a remote RPC server.
774  *
775  * @param argc  Standard main() style argc.
776  * @param argv  Standard main() style argv. Initial components are already
777  *              stripped.
778  *
779  * @return A shell status integer (0 for success).
780  **/
781
782 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
783 {
784         return run_rpc_command(c, NULL, PI_SAMR, 0, rpc_user_rename_internals,
785                                argc, argv);
786 }
787
788 /**
789  * Delete a user from a remote RPC server.
790  *
791  * @param argc  Standard main() style argc.
792  * @param argv  Standard main() style argv. Initial components are already
793  *              stripped.
794  *
795  * @return A shell status integer (0 for success).
796  **/
797
798 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
799 {
800         NET_API_STATUS status;
801
802         if (argc < 1 || c->display_usage) {
803                 rpc_user_usage(c, argc, argv);
804                 return 0;
805         }
806
807         status = NetUserDel(c->opt_host, argv[0]);
808
809         if (status != 0) {
810                 d_fprintf(stderr, "Failed to delete user '%s' with: %s.\n",
811                           argv[0],
812                           libnetapi_get_error_string(c->netapi_ctx, status));
813                 return -1;
814         } else {
815                 d_printf("Deleted user '%s'.\n", argv[0]);
816         }
817
818         return 0;
819 }
820
821 /**
822  * Set a password for a user on a remote RPC server.
823  *
824  * All parameters are provided by the run_rpc_command function, except for
825  * argc, argv which are passed through.
826  *
827  * @param domain_sid The domain sid acquired from the remote server.
828  * @param cli A cli_state connected to the server.
829  * @param mem_ctx Talloc context, destroyed on completion of the function.
830  * @param argc  Standard main() style argc.
831  * @param argv  Standard main() style argv. Initial components are already
832  *              stripped.
833  *
834  * @return Normal NTSTATUS return.
835  **/
836
837 static NTSTATUS rpc_user_password_internals(struct net_context *c,
838                                         const DOM_SID *domain_sid,
839                                         const char *domain_name,
840                                         struct cli_state *cli,
841                                         struct rpc_pipe_client *pipe_hnd,
842                                         TALLOC_CTX *mem_ctx,
843                                         int argc,
844                                         const char **argv)
845 {
846         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
847         POLICY_HND connect_pol, domain_pol, user_pol;
848         uchar pwbuf[516];
849         const char *user;
850         const char *new_password;
851         char *prompt = NULL;
852         union samr_UserInfo info;
853
854         if (argc < 1 || c->display_usage) {
855                 rpc_user_usage(c, argc, argv);
856                 return NT_STATUS_OK;
857         }
858
859         user = argv[0];
860
861         if (argv[1]) {
862                 new_password = argv[1];
863         } else {
864                 asprintf(&prompt, "Enter new password for %s:", user);
865                 new_password = getpass(prompt);
866                 SAFE_FREE(prompt);
867         }
868
869         /* Get sam policy and domain handles */
870
871         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
872                                       pipe_hnd->desthost,
873                                       MAXIMUM_ALLOWED_ACCESS,
874                                       &connect_pol);
875
876         if (!NT_STATUS_IS_OK(result)) {
877                 goto done;
878         }
879
880         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
881                                         &connect_pol,
882                                         MAXIMUM_ALLOWED_ACCESS,
883                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
884                                         &domain_pol);
885
886         if (!NT_STATUS_IS_OK(result)) {
887                 goto done;
888         }
889
890         /* Get handle on user */
891
892         {
893                 struct samr_Ids user_rids, name_types;
894                 struct lsa_String lsa_acct_name;
895
896                 init_lsa_String(&lsa_acct_name, user);
897
898                 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
899                                                  &domain_pol,
900                                                  1,
901                                                  &lsa_acct_name,
902                                                  &user_rids,
903                                                  &name_types);
904                 if (!NT_STATUS_IS_OK(result)) {
905                         goto done;
906                 }
907
908                 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
909                                               &domain_pol,
910                                               MAXIMUM_ALLOWED_ACCESS,
911                                               user_rids.ids[0],
912                                               &user_pol);
913
914                 if (!NT_STATUS_IS_OK(result)) {
915                         goto done;
916                 }
917         }
918
919         /* Set password on account */
920
921         encode_pw_buffer(pwbuf, new_password, STR_UNICODE);
922
923         init_samr_user_info24(&info.info24, pwbuf, 24);
924
925         SamOEMhashBlob(info.info24.password.data, 516,
926                        &cli->user_session_key);
927
928         result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
929                                           &user_pol,
930                                           24,
931                                           &info);
932
933         if (!NT_STATUS_IS_OK(result)) {
934                 goto done;
935         }
936
937         /* Display results */
938
939  done:
940         return result;
941
942 }
943
944 /**
945  * Set a user's password on a remote RPC server.
946  *
947  * @param argc  Standard main() style argc.
948  * @param argv  Standard main() style argv. Initial components are already
949  *              stripped.
950  *
951  * @return A shell status integer (0 for success).
952  **/
953
954 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
955 {
956         return run_rpc_command(c, NULL, PI_SAMR, 0, rpc_user_password_internals,
957                                argc, argv);
958 }
959
960 /**
961  * List user's groups on a remote RPC server.
962  *
963  * All parameters are provided by the run_rpc_command function, except for
964  * argc, argv which are passed through.
965  *
966  * @param domain_sid The domain sid acquired from the remote server.
967  * @param cli A cli_state connected to the server.
968  * @param mem_ctx Talloc context, destroyed on completion of the function.
969  * @param argc  Standard main() style argc.
970  * @param argv  Standard main() style argv. Initial components are already
971  *              stripped.
972  *
973  * @return Normal NTSTATUS return.
974  **/
975
976 static NTSTATUS rpc_user_info_internals(struct net_context *c,
977                         const DOM_SID *domain_sid,
978                         const char *domain_name,
979                         struct cli_state *cli,
980                         struct rpc_pipe_client *pipe_hnd,
981                         TALLOC_CTX *mem_ctx,
982                         int argc,
983                         const char **argv)
984 {
985         POLICY_HND connect_pol, domain_pol, user_pol;
986         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
987         int i;
988         struct samr_RidWithAttributeArray *rid_array = NULL;
989         struct lsa_Strings names;
990         struct samr_Ids types;
991         uint32_t *lrids = NULL;
992         struct samr_Ids rids, name_types;
993         struct lsa_String lsa_acct_name;
994
995
996         if (argc < 1 || c->display_usage) {
997                 rpc_user_usage(c, argc, argv);
998                 return NT_STATUS_OK;
999         }
1000         /* Get sam policy handle */
1001
1002         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1003                                       pipe_hnd->desthost,
1004                                       MAXIMUM_ALLOWED_ACCESS,
1005                                       &connect_pol);
1006         if (!NT_STATUS_IS_OK(result)) goto done;
1007
1008         /* Get domain policy handle */
1009
1010         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1011                                         &connect_pol,
1012                                         MAXIMUM_ALLOWED_ACCESS,
1013                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1014                                         &domain_pol);
1015         if (!NT_STATUS_IS_OK(result)) goto done;
1016
1017         /* Get handle on user */
1018
1019         init_lsa_String(&lsa_acct_name, argv[0]);
1020
1021         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1022                                          &domain_pol,
1023                                          1,
1024                                          &lsa_acct_name,
1025                                          &rids,
1026                                          &name_types);
1027
1028         if (!NT_STATUS_IS_OK(result)) goto done;
1029
1030         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1031                                       &domain_pol,
1032                                       MAXIMUM_ALLOWED_ACCESS,
1033                                       rids.ids[0],
1034                                       &user_pol);
1035         if (!NT_STATUS_IS_OK(result)) goto done;
1036
1037         result = rpccli_samr_GetGroupsForUser(pipe_hnd, mem_ctx,
1038                                               &user_pol,
1039                                               &rid_array);
1040
1041         if (!NT_STATUS_IS_OK(result)) goto done;
1042
1043         /* Look up rids */
1044
1045         if (rid_array->count) {
1046                 if ((lrids = TALLOC_ARRAY(mem_ctx, uint32, rid_array->count)) == NULL) {
1047                         result = NT_STATUS_NO_MEMORY;
1048                         goto done;
1049                 }
1050
1051                 for (i = 0; i < rid_array->count; i++)
1052                         lrids[i] = rid_array->rids[i].rid;
1053
1054                 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
1055                                                 &domain_pol,
1056                                                 rid_array->count,
1057                                                 lrids,
1058                                                 &names,
1059                                                 &types);
1060
1061                 if (!NT_STATUS_IS_OK(result)) {
1062                         goto done;
1063                 }
1064
1065                 /* Display results */
1066
1067                 for (i = 0; i < names.count; i++)
1068                         printf("%s\n", names.names[i].string);
1069         }
1070  done:
1071         return result;
1072 }
1073
1074 /**
1075  * List a user's groups from a remote RPC server.
1076  *
1077  * @param argc  Standard main() style argc.
1078  * @param argv  Standard main() style argv. Initial components are already
1079  *              stripped.
1080  *
1081  * @return A shell status integer (0 for success)
1082  **/
1083
1084 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
1085 {
1086         return run_rpc_command(c, NULL, PI_SAMR, 0, rpc_user_info_internals,
1087                                argc, argv);
1088 }
1089
1090 /**
1091  * List users on a remote RPC server.
1092  *
1093  * All parameters are provided by the run_rpc_command function, except for
1094  * argc, argv which are passed through.
1095  *
1096  * @param domain_sid The domain sid acquired from the remote server.
1097  * @param cli A cli_state connected to the server.
1098  * @param mem_ctx Talloc context, destroyed on completion of the function.
1099  * @param argc  Standard main() style argc.
1100  * @param argv  Standard main() style argv. Initial components are already
1101  *              stripped.
1102  *
1103  * @return Normal NTSTATUS return.
1104  **/
1105
1106 static NTSTATUS rpc_user_list_internals(struct net_context *c,
1107                                         const DOM_SID *domain_sid,
1108                                         const char *domain_name,
1109                                         struct cli_state *cli,
1110                                         struct rpc_pipe_client *pipe_hnd,
1111                                         TALLOC_CTX *mem_ctx,
1112                                         int argc,
1113                                         const char **argv)
1114 {
1115         POLICY_HND connect_pol, domain_pol;
1116         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1117         uint32 start_idx=0, num_entries, i, loop_count = 0;
1118
1119         /* Get sam policy handle */
1120
1121         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1122                                       pipe_hnd->desthost,
1123                                       MAXIMUM_ALLOWED_ACCESS,
1124                                       &connect_pol);
1125         if (!NT_STATUS_IS_OK(result)) {
1126                 goto done;
1127         }
1128
1129         /* Get domain policy handle */
1130
1131         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1132                                         &connect_pol,
1133                                         MAXIMUM_ALLOWED_ACCESS,
1134                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1135                                         &domain_pol);
1136         if (!NT_STATUS_IS_OK(result)) {
1137                 goto done;
1138         }
1139
1140         /* Query domain users */
1141         if (c->opt_long_list_entries)
1142                 d_printf("\nUser name             Comment"
1143                          "\n-----------------------------\n");
1144         do {
1145                 const char *user = NULL;
1146                 const char *desc = NULL;
1147                 uint32 max_entries, max_size;
1148                 uint32_t total_size, returned_size;
1149                 union samr_DispInfo info;
1150
1151                 get_query_dispinfo_params(
1152                         loop_count, &max_entries, &max_size);
1153
1154                 result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
1155                                                       &domain_pol,
1156                                                       1,
1157                                                       start_idx,
1158                                                       max_entries,
1159                                                       max_size,
1160                                                       &total_size,
1161                                                       &returned_size,
1162                                                       &info);
1163                 loop_count++;
1164                 start_idx += info.info1.count;
1165                 num_entries = info.info1.count;
1166
1167                 for (i = 0; i < num_entries; i++) {
1168                         user = info.info1.entries[i].account_name.string;
1169                         if (c->opt_long_list_entries)
1170                                 desc = info.info1.entries[i].description.string;
1171                         if (c->opt_long_list_entries)
1172                                 printf("%-21.21s %s\n", user, desc);
1173                         else
1174                                 printf("%s\n", user);
1175                 }
1176         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1177
1178  done:
1179         return result;
1180 }
1181
1182 /**
1183  * 'net rpc user' entrypoint.
1184  * @param argc  Standard main() style argc.
1185  * @param argv  Standard main() style argv. Initial components are already
1186  *              stripped.
1187  **/
1188
1189 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1190 {
1191         NET_API_STATUS status;
1192
1193         struct functable func[] = {
1194                 {
1195                         "add",
1196                         rpc_user_add,
1197                         NET_TRANSPORT_RPC,
1198                         "Add specified user",
1199                         "net rpc user add\n"
1200                         "    Add specified user"
1201                 },
1202                 {
1203                         "info",
1204                         rpc_user_info,
1205                         NET_TRANSPORT_RPC,
1206                         "List domain groups of user",
1207                         "net rpc user info\n"
1208                         "    Lis domain groups of user"
1209                 },
1210                 {
1211                         "delete",
1212                         rpc_user_delete,
1213                         NET_TRANSPORT_RPC,
1214                         "Remove specified user",
1215                         "net rpc user delete\n"
1216                         "    Remove specified user"
1217                 },
1218                 {
1219                         "password",
1220                         rpc_user_password,
1221                         NET_TRANSPORT_RPC,
1222                         "Change user password",
1223                         "net rpc user password\n"
1224                         "    Change user password"
1225                 },
1226                 {
1227                         "rename",
1228                         rpc_user_rename,
1229                         NET_TRANSPORT_RPC,
1230                         "Rename specified user",
1231                         "net rpc user rename\n"
1232                         "    Rename specified user"
1233                 },
1234                 {NULL, NULL, 0, NULL, NULL}
1235         };
1236
1237         status = libnetapi_init(&c->netapi_ctx);
1238         if (status != 0) {
1239                 return -1;
1240         }
1241         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1242         libnetapi_set_password(c->netapi_ctx, c->opt_password);
1243
1244         if (argc == 0) {
1245                 if (c->display_usage) {
1246                         d_printf("Usage:\n");
1247                         d_printf("net rpc user\n"
1248                                  "    List all users\n");
1249                         net_display_usage_from_functable(func);
1250                         return 0;
1251                 }
1252
1253                 return run_rpc_command(c, NULL,PI_SAMR, 0,
1254                                        rpc_user_list_internals,
1255                                        argc, argv);
1256         }
1257
1258         return net_run_function(c, argc, argv, "net rpc user", func);
1259 }
1260
1261 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1262                                  TALLOC_CTX *mem_ctx,
1263                                  struct rpc_sh_ctx *ctx,
1264                                  struct rpc_pipe_client *pipe_hnd,
1265                                  int argc, const char **argv)
1266 {
1267         return rpc_user_list_internals(c, ctx->domain_sid, ctx->domain_name,
1268                                        ctx->cli, pipe_hnd, mem_ctx,
1269                                        argc, argv);
1270 }
1271
1272 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1273                                  TALLOC_CTX *mem_ctx,
1274                                  struct rpc_sh_ctx *ctx,
1275                                  struct rpc_pipe_client *pipe_hnd,
1276                                  int argc, const char **argv)
1277 {
1278         return rpc_user_info_internals(c, ctx->domain_sid, ctx->domain_name,
1279                                        ctx->cli, pipe_hnd, mem_ctx,
1280                                        argc, argv);
1281 }
1282
1283 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1284                                    TALLOC_CTX *mem_ctx,
1285                                    struct rpc_sh_ctx *ctx,
1286                                    struct rpc_pipe_client *pipe_hnd,
1287                                    int argc, const char **argv,
1288                                    NTSTATUS (*fn)(
1289                                            struct net_context *c,
1290                                            TALLOC_CTX *mem_ctx,
1291                                            struct rpc_sh_ctx *ctx,
1292                                            struct rpc_pipe_client *pipe_hnd,
1293                                            POLICY_HND *user_hnd,
1294                                            int argc, const char **argv))
1295 {
1296         POLICY_HND connect_pol, domain_pol, user_pol;
1297         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1298         DOM_SID sid;
1299         uint32 rid;
1300         enum lsa_SidType type;
1301
1302         if (argc == 0) {
1303                 d_fprintf(stderr, "usage: %s <username>\n", ctx->whoami);
1304                 return NT_STATUS_INVALID_PARAMETER;
1305         }
1306
1307         ZERO_STRUCT(connect_pol);
1308         ZERO_STRUCT(domain_pol);
1309         ZERO_STRUCT(user_pol);
1310
1311         result = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1312                                      argv[0], NULL, NULL, &sid, &type);
1313         if (!NT_STATUS_IS_OK(result)) {
1314                 d_fprintf(stderr, "Could not lookup %s: %s\n", argv[0],
1315                           nt_errstr(result));
1316                 goto done;
1317         }
1318
1319         if (type != SID_NAME_USER) {
1320                 d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
1321                           sid_type_lookup(type));
1322                 result = NT_STATUS_NO_SUCH_USER;
1323                 goto done;
1324         }
1325
1326         if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1327                 d_fprintf(stderr, "%s is not in our domain\n", argv[0]);
1328                 result = NT_STATUS_NO_SUCH_USER;
1329                 goto done;
1330         }
1331
1332         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1333                                       pipe_hnd->desthost,
1334                                       MAXIMUM_ALLOWED_ACCESS,
1335                                       &connect_pol);
1336         if (!NT_STATUS_IS_OK(result)) {
1337                 goto done;
1338         }
1339
1340         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1341                                         &connect_pol,
1342                                         MAXIMUM_ALLOWED_ACCESS,
1343                                         ctx->domain_sid,
1344                                         &domain_pol);
1345         if (!NT_STATUS_IS_OK(result)) {
1346                 goto done;
1347         }
1348
1349         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1350                                       &domain_pol,
1351                                       MAXIMUM_ALLOWED_ACCESS,
1352                                       rid,
1353                                       &user_pol);
1354         if (!NT_STATUS_IS_OK(result)) {
1355                 goto done;
1356         }
1357
1358         result = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1359
1360  done:
1361         if (is_valid_policy_hnd(&user_pol)) {
1362                 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1363         }
1364         if (is_valid_policy_hnd(&domain_pol)) {
1365                 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
1366         }
1367         if (is_valid_policy_hnd(&connect_pol)) {
1368                 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1369         }
1370         return result;
1371 }
1372
1373 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1374                                            TALLOC_CTX *mem_ctx,
1375                                            struct rpc_sh_ctx *ctx,
1376                                            struct rpc_pipe_client *pipe_hnd,
1377                                            POLICY_HND *user_hnd,
1378                                            int argc, const char **argv)
1379 {
1380         NTSTATUS result;
1381         union samr_UserInfo *info = NULL;
1382
1383         if (argc != 0) {
1384                 d_fprintf(stderr, "usage: %s show <username>\n", ctx->whoami);
1385                 return NT_STATUS_INVALID_PARAMETER;
1386         }
1387
1388         result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1389                                            user_hnd,
1390                                            21,
1391                                            &info);
1392         if (!NT_STATUS_IS_OK(result)) {
1393                 return result;
1394         }
1395
1396         d_printf("user rid: %d, group rid: %d\n",
1397                 info->info21.rid,
1398                 info->info21.primary_gid);
1399
1400         return result;
1401 }
1402
1403 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1404                                  TALLOC_CTX *mem_ctx,
1405                                  struct rpc_sh_ctx *ctx,
1406                                  struct rpc_pipe_client *pipe_hnd,
1407                                  int argc, const char **argv)
1408 {
1409         return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1410                                   rpc_sh_user_show_internals);
1411 }
1412
1413 #define FETCHSTR(name, rec) \
1414 do { if (strequal(ctx->thiscmd, name)) { \
1415         oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1416 } while (0);
1417
1418 #define SETSTR(name, rec, flag) \
1419 do { if (strequal(ctx->thiscmd, name)) { \
1420         init_lsa_String(&(info->info21.rec), argv[0]); \
1421         info->info21.fields_present |= SAMR_FIELD_##flag; } \
1422 } while (0);
1423
1424 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1425                                                TALLOC_CTX *mem_ctx,
1426                                                struct rpc_sh_ctx *ctx,
1427                                                struct rpc_pipe_client *pipe_hnd,
1428                                                POLICY_HND *user_hnd,
1429                                                int argc, const char **argv)
1430 {
1431         NTSTATUS result;
1432         const char *username;
1433         const char *oldval = "";
1434         union samr_UserInfo *info = NULL;
1435
1436         if (argc > 1) {
1437                 d_fprintf(stderr, "usage: %s <username> [new value|NULL]\n",
1438                           ctx->whoami);
1439                 return NT_STATUS_INVALID_PARAMETER;
1440         }
1441
1442         result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1443                                            user_hnd,
1444                                            21,
1445                                            &info);
1446         if (!NT_STATUS_IS_OK(result)) {
1447                 return result;
1448         }
1449
1450         username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1451
1452         FETCHSTR("fullname", full_name);
1453         FETCHSTR("homedir", home_directory);
1454         FETCHSTR("homedrive", home_drive);
1455         FETCHSTR("logonscript", logon_script);
1456         FETCHSTR("profilepath", profile_path);
1457         FETCHSTR("description", description);
1458
1459         if (argc == 0) {
1460                 d_printf("%s's %s: [%s]\n", username, ctx->thiscmd, oldval);
1461                 goto done;
1462         }
1463
1464         if (strcmp(argv[0], "NULL") == 0) {
1465                 argv[0] = "";
1466         }
1467
1468         ZERO_STRUCT(info->info21);
1469
1470         SETSTR("fullname", full_name, FULL_NAME);
1471         SETSTR("homedir", home_directory, HOME_DIRECTORY);
1472         SETSTR("homedrive", home_drive, HOME_DRIVE);
1473         SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1474         SETSTR("profilepath", profile_path, PROFILE_PATH);
1475         SETSTR("description", description, DESCRIPTION);
1476
1477         result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1478                                          user_hnd,
1479                                          21,
1480                                          info);
1481
1482         d_printf("Set %s's %s from [%s] to [%s]\n", username,
1483                  ctx->thiscmd, oldval, argv[0]);
1484
1485  done:
1486
1487         return result;
1488 }
1489
1490 #define HANDLEFLG(name, rec) \
1491 do { if (strequal(ctx->thiscmd, name)) { \
1492         oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1493         if (newval) { \
1494                 newflags = oldflags | ACB_##rec; \
1495         } else { \
1496                 newflags = oldflags & ~ACB_##rec; \
1497         } } } while (0);
1498
1499 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1500                                      TALLOC_CTX *mem_ctx,
1501                                      struct rpc_sh_ctx *ctx,
1502                                      struct rpc_pipe_client *pipe_hnd,
1503                                      int argc, const char **argv)
1504 {
1505         return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1506                                   rpc_sh_user_str_edit_internals);
1507 }
1508
1509 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1510                                                 TALLOC_CTX *mem_ctx,
1511                                                 struct rpc_sh_ctx *ctx,
1512                                                 struct rpc_pipe_client *pipe_hnd,
1513                                                 POLICY_HND *user_hnd,
1514                                                 int argc, const char **argv)
1515 {
1516         NTSTATUS result;
1517         const char *username;
1518         const char *oldval = "unknown";
1519         uint32 oldflags, newflags;
1520         bool newval;
1521         union samr_UserInfo *info = NULL;
1522
1523         if ((argc > 1) ||
1524             ((argc == 1) && !strequal(argv[0], "yes") &&
1525              !strequal(argv[0], "no"))) {
1526                 d_fprintf(stderr, "usage: %s <username> [yes|no]\n",
1527                           ctx->whoami);
1528                 return NT_STATUS_INVALID_PARAMETER;
1529         }
1530
1531         newval = strequal(argv[0], "yes");
1532
1533         result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1534                                            user_hnd,
1535                                            21,
1536                                            &info);
1537         if (!NT_STATUS_IS_OK(result)) {
1538                 return result;
1539         }
1540
1541         username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1542         oldflags = info->info21.acct_flags;
1543         newflags = info->info21.acct_flags;
1544
1545         HANDLEFLG("disabled", DISABLED);
1546         HANDLEFLG("pwnotreq", PWNOTREQ);
1547         HANDLEFLG("autolock", AUTOLOCK);
1548         HANDLEFLG("pwnoexp", PWNOEXP);
1549
1550         if (argc == 0) {
1551                 d_printf("%s's %s flag: %s\n", username, ctx->thiscmd, oldval);
1552                 goto done;
1553         }
1554
1555         ZERO_STRUCT(info->info21);
1556
1557         info->info21.acct_flags = newflags;
1558         info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1559
1560         result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1561                                          user_hnd,
1562                                          21,
1563                                          info);
1564
1565         if (NT_STATUS_IS_OK(result)) {
1566                 d_printf("Set %s's %s flag from [%s] to [%s]\n", username,
1567                          ctx->thiscmd, oldval, argv[0]);
1568         }
1569
1570  done:
1571
1572         return result;
1573 }
1574
1575 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1576                                       TALLOC_CTX *mem_ctx,
1577                                       struct rpc_sh_ctx *ctx,
1578                                       struct rpc_pipe_client *pipe_hnd,
1579                                       int argc, const char **argv)
1580 {
1581         return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1582                                   rpc_sh_user_flag_edit_internals);
1583 }
1584
1585 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1586                                           TALLOC_CTX *mem_ctx,
1587                                           struct rpc_sh_ctx *ctx)
1588 {
1589         static struct rpc_sh_cmd cmds[] = {
1590
1591                 { "fullname", NULL, PI_SAMR, rpc_sh_user_str_edit,
1592                   "Show/Set a user's full name" },
1593
1594                 { "homedir", NULL, PI_SAMR, rpc_sh_user_str_edit,
1595                   "Show/Set a user's home directory" },
1596
1597                 { "homedrive", NULL, PI_SAMR, rpc_sh_user_str_edit,
1598                   "Show/Set a user's home drive" },
1599
1600                 { "logonscript", NULL, PI_SAMR, rpc_sh_user_str_edit,
1601                   "Show/Set a user's logon script" },
1602
1603                 { "profilepath", NULL, PI_SAMR, rpc_sh_user_str_edit,
1604                   "Show/Set a user's profile path" },
1605
1606                 { "description", NULL, PI_SAMR, rpc_sh_user_str_edit,
1607                   "Show/Set a user's description" },
1608
1609                 { "disabled", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1610                   "Show/Set whether a user is disabled" },
1611
1612                 { "autolock", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1613                   "Show/Set whether a user locked out" },
1614
1615                 { "pwnotreq", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1616                   "Show/Set whether a user does not need a password" },
1617
1618                 { "pwnoexp", NULL, PI_SAMR, rpc_sh_user_flag_edit,
1619                   "Show/Set whether a user's password does not expire" },
1620
1621                 { NULL, NULL, 0, NULL, NULL }
1622         };
1623
1624         return cmds;
1625 }
1626
1627 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1628                                      TALLOC_CTX *mem_ctx,
1629                                      struct rpc_sh_ctx *ctx)
1630 {
1631         static struct rpc_sh_cmd cmds[] = {
1632
1633                 { "list", NULL, PI_SAMR, rpc_sh_user_list,
1634                   "List available users" },
1635
1636                 { "info", NULL, PI_SAMR, rpc_sh_user_info,
1637                   "List the domain groups a user is member of" },
1638
1639                 { "show", NULL, PI_SAMR, rpc_sh_user_show,
1640                   "Show info about a user" },
1641
1642                 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1643                   "Show/Modify a user's fields" },
1644
1645                 { NULL, NULL, 0, NULL, NULL }
1646         };
1647
1648         return cmds;
1649 }
1650
1651 /****************************************************************************/
1652
1653 /**
1654  * Basic usage function for 'net rpc group'.
1655  * @param argc  Standard main() style argc.
1656  * @param argv  Standard main() style argv. Initial components are already
1657  *              stripped.
1658  **/
1659
1660 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1661 {
1662         return net_group_usage(c, argc, argv);
1663 }
1664
1665 /**
1666  * Delete group on a remote RPC server.
1667  *
1668  * All parameters are provided by the run_rpc_command function, except for
1669  * argc, argv which are passed through.
1670  *
1671  * @param domain_sid The domain sid acquired from the remote server.
1672  * @param cli A cli_state connected to the server.
1673  * @param mem_ctx Talloc context, destroyed on completion of the function.
1674  * @param argc  Standard main() style argc.
1675  * @param argv  Standard main() style argv. Initial components are already
1676  *              stripped.
1677  *
1678  * @return Normal NTSTATUS return.
1679  **/
1680
1681 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1682                                         const DOM_SID *domain_sid,
1683                                         const char *domain_name,
1684                                         struct cli_state *cli,
1685                                         struct rpc_pipe_client *pipe_hnd,
1686                                         TALLOC_CTX *mem_ctx,
1687                                         int argc,
1688                                         const char **argv)
1689 {
1690         POLICY_HND connect_pol, domain_pol, group_pol, user_pol;
1691         bool group_is_primary = false;
1692         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1693         uint32_t group_rid;
1694         struct samr_RidTypeArray *rids = NULL;
1695         /* char **names; */
1696         int i;
1697         /* DOM_GID *user_gids; */
1698
1699         struct samr_Ids group_rids, name_types;
1700         struct lsa_String lsa_acct_name;
1701         union samr_UserInfo *info = NULL;
1702
1703         if (argc < 1 || c->display_usage) {
1704                 rpc_group_usage(c, argc,argv);
1705                 return NT_STATUS_OK; /* ok? */
1706         }
1707
1708         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1709                                       pipe_hnd->desthost,
1710                                       MAXIMUM_ALLOWED_ACCESS,
1711                                       &connect_pol);
1712
1713         if (!NT_STATUS_IS_OK(result)) {
1714                 d_fprintf(stderr, "Request samr_Connect2 failed\n");
1715                 goto done;
1716         }
1717
1718         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1719                                         &connect_pol,
1720                                         MAXIMUM_ALLOWED_ACCESS,
1721                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1722                                         &domain_pol);
1723
1724         if (!NT_STATUS_IS_OK(result)) {
1725                 d_fprintf(stderr, "Request open_domain failed\n");
1726                 goto done;
1727         }
1728
1729         init_lsa_String(&lsa_acct_name, argv[0]);
1730
1731         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1732                                          &domain_pol,
1733                                          1,
1734                                          &lsa_acct_name,
1735                                          &group_rids,
1736                                          &name_types);
1737         if (!NT_STATUS_IS_OK(result)) {
1738                 d_fprintf(stderr, "Lookup of '%s' failed\n",argv[0]);
1739                 goto done;
1740         }
1741
1742         switch (name_types.ids[0])
1743         {
1744         case SID_NAME_DOM_GRP:
1745                 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1746                                                &domain_pol,
1747                                                MAXIMUM_ALLOWED_ACCESS,
1748                                                group_rids.ids[0],
1749                                                &group_pol);
1750                 if (!NT_STATUS_IS_OK(result)) {
1751                         d_fprintf(stderr, "Request open_group failed");
1752                         goto done;
1753                 }
1754
1755                 group_rid = group_rids.ids[0];
1756
1757                 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
1758                                                       &group_pol,
1759                                                       &rids);
1760
1761                 if (!NT_STATUS_IS_OK(result)) {
1762                         d_fprintf(stderr, "Unable to query group members of %s",argv[0]);
1763                         goto done;
1764                 }
1765
1766                 if (c->opt_verbose) {
1767                         d_printf("Domain Group %s (rid: %d) has %d members\n",
1768                                 argv[0],group_rid, rids->count);
1769                 }
1770
1771                 /* Check if group is anyone's primary group */
1772                 for (i = 0; i < rids->count; i++)
1773                 {
1774                         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1775                                                       &domain_pol,
1776                                                       MAXIMUM_ALLOWED_ACCESS,
1777                                                       rids->rids[i],
1778                                                       &user_pol);
1779
1780                         if (!NT_STATUS_IS_OK(result)) {
1781                                 d_fprintf(stderr, "Unable to open group member %d\n",
1782                                         rids->rids[i]);
1783                                 goto done;
1784                         }
1785
1786                         result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1787                                                            &user_pol,
1788                                                            21,
1789                                                            &info);
1790
1791                         if (!NT_STATUS_IS_OK(result)) {
1792                                 d_fprintf(stderr, "Unable to lookup userinfo for group member %d\n",
1793                                         rids->rids[i]);
1794                                 goto done;
1795                         }
1796
1797                         if (info->info21.primary_gid == group_rid) {
1798                                 if (c->opt_verbose) {
1799                                         d_printf("Group is primary group of %s\n",
1800                                                 info->info21.account_name.string);
1801                                 }
1802                                 group_is_primary = true;
1803                         }
1804
1805                         rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1806                 }
1807
1808                 if (group_is_primary) {
1809                         d_fprintf(stderr, "Unable to delete group because some "
1810                                  "of it's members have it as primary group\n");
1811                         result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1812                         goto done;
1813                 }
1814
1815                 /* remove all group members */
1816                 for (i = 0; i < rids->count; i++)
1817                 {
1818                         if (c->opt_verbose)
1819                                 d_printf("Remove group member %d...",
1820                                         rids->rids[i]);
1821                         result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
1822                                                                &group_pol,
1823                                                                rids->rids[i]);
1824
1825                         if (NT_STATUS_IS_OK(result)) {
1826                                 if (c->opt_verbose)
1827                                         d_printf("ok\n");
1828                         } else {
1829                                 if (c->opt_verbose)
1830                                         d_printf("failed\n");
1831                                 goto done;
1832                         }
1833                 }
1834
1835                 result = rpccli_samr_DeleteDomainGroup(pipe_hnd, mem_ctx,
1836                                                        &group_pol);
1837
1838                 break;
1839         /* removing a local group is easier... */
1840         case SID_NAME_ALIAS:
1841                 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1842                                                &domain_pol,
1843                                                MAXIMUM_ALLOWED_ACCESS,
1844                                                group_rids.ids[0],
1845                                                &group_pol);
1846
1847                 if (!NT_STATUS_IS_OK(result)) {
1848                         d_fprintf(stderr, "Request open_alias failed\n");
1849                         goto done;
1850                 }
1851
1852                 result = rpccli_samr_DeleteDomAlias(pipe_hnd, mem_ctx,
1853                                                     &group_pol);
1854                 break;
1855         default:
1856                 d_fprintf(stderr, "%s is of type %s. This command is only for deleting local or global groups\n",
1857                         argv[0],sid_type_lookup(name_types.ids[0]));
1858                 result = NT_STATUS_UNSUCCESSFUL;
1859                 goto done;
1860         }
1861
1862         if (NT_STATUS_IS_OK(result)) {
1863                 if (c->opt_verbose)
1864                         d_printf("Deleted %s '%s'\n",sid_type_lookup(name_types.ids[0]),argv[0]);
1865         } else {
1866                 d_fprintf(stderr, "Deleting of %s failed: %s\n",argv[0],
1867                         get_friendly_nt_error_msg(result));
1868         }
1869
1870  done:
1871         return result;
1872
1873 }
1874
1875 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1876 {
1877         return run_rpc_command(c, NULL, PI_SAMR, 0, rpc_group_delete_internals,
1878                                argc,argv);
1879 }
1880
1881 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1882 {
1883         NET_API_STATUS status;
1884         struct GROUP_INFO_1 info1;
1885         uint32_t parm_error = 0;
1886
1887         if (argc != 1 || c->display_usage) {
1888                 rpc_group_usage(c, argc, argv);
1889                 return 0;
1890         }
1891
1892         ZERO_STRUCT(info1);
1893
1894         info1.grpi1_name = argv[0];
1895         if (c->opt_comment && strlen(c->opt_comment) > 0) {
1896                 info1.grpi1_comment = c->opt_comment;
1897         }
1898
1899         status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1900
1901         if (status != 0) {
1902                 d_fprintf(stderr, "Failed to add group '%s' with: %s.\n",
1903                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
1904                                                             status));
1905                 return -1;
1906         } else {
1907                 d_printf("Added group '%s'.\n", argv[0]);
1908         }
1909
1910         return 0;
1911 }
1912
1913 static NTSTATUS rpc_alias_add_internals(struct net_context *c,
1914                                         const DOM_SID *domain_sid,
1915                                         const char *domain_name,
1916                                         struct cli_state *cli,
1917                                         struct rpc_pipe_client *pipe_hnd,
1918                                         TALLOC_CTX *mem_ctx,
1919                                         int argc,
1920                                         const char **argv)
1921 {
1922         POLICY_HND connect_pol, domain_pol, alias_pol;
1923         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1924         union samr_AliasInfo alias_info;
1925         struct lsa_String alias_name;
1926         uint32_t rid = 0;
1927
1928         if (argc != 1 || c->display_usage) {
1929                 rpc_group_usage(c, argc, argv);
1930                 return NT_STATUS_OK;
1931         }
1932
1933         init_lsa_String(&alias_name, argv[0]);
1934
1935         /* Get sam policy handle */
1936
1937         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1938                                       pipe_hnd->desthost,
1939                                       MAXIMUM_ALLOWED_ACCESS,
1940                                       &connect_pol);
1941         if (!NT_STATUS_IS_OK(result)) goto done;
1942
1943         /* Get domain policy handle */
1944
1945         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1946                                         &connect_pol,
1947                                         MAXIMUM_ALLOWED_ACCESS,
1948                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
1949                                         &domain_pol);
1950         if (!NT_STATUS_IS_OK(result)) goto done;
1951
1952         /* Create the group */
1953
1954         result = rpccli_samr_CreateDomAlias(pipe_hnd, mem_ctx,
1955                                             &domain_pol,
1956                                             &alias_name,
1957                                             MAXIMUM_ALLOWED_ACCESS,
1958                                             &alias_pol,
1959                                             &rid);
1960         if (!NT_STATUS_IS_OK(result)) goto done;
1961
1962         if (strlen(c->opt_comment) == 0) goto done;
1963
1964         /* We've got a comment to set */
1965
1966         init_lsa_String(&alias_info.description, c->opt_comment);
1967
1968         result = rpccli_samr_SetAliasInfo(pipe_hnd, mem_ctx,
1969                                           &alias_pol,
1970                                           3,
1971                                           &alias_info);
1972
1973         if (!NT_STATUS_IS_OK(result)) goto done;
1974
1975  done:
1976         if (NT_STATUS_IS_OK(result))
1977                 DEBUG(5, ("add alias succeeded\n"));
1978         else
1979                 d_fprintf(stderr, "add alias failed: %s\n", nt_errstr(result));
1980
1981         return result;
1982 }
1983
1984 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1985 {
1986         if (c->opt_localgroup)
1987                 return run_rpc_command(c, NULL, PI_SAMR, 0,
1988                                        rpc_alias_add_internals,
1989                                        argc, argv);
1990
1991         return rpc_group_add_internals(c, argc, argv);
1992 }
1993
1994 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1995                                 TALLOC_CTX *mem_ctx,
1996                                 const char *name,
1997                                 DOM_SID *sid,
1998                                 enum lsa_SidType *type)
1999 {
2000         DOM_SID *sids = NULL;
2001         enum lsa_SidType *types = NULL;
2002         struct rpc_pipe_client *pipe_hnd;
2003         POLICY_HND lsa_pol;
2004         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2005
2006         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
2007                                           &pipe_hnd);
2008         if (!NT_STATUS_IS_OK(result)) {
2009                 goto done;
2010         }
2011
2012         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
2013                                      SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
2014
2015         if (!NT_STATUS_IS_OK(result)) {
2016                 goto done;
2017         }
2018
2019         result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
2020                                       &name, NULL, 1, &sids, &types);
2021
2022         if (NT_STATUS_IS_OK(result)) {
2023                 sid_copy(sid, &sids[0]);
2024                 *type = types[0];
2025         }
2026
2027         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
2028
2029  done:
2030         if (pipe_hnd) {
2031                 TALLOC_FREE(pipe_hnd);
2032         }
2033
2034         if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
2035
2036                 /* Try as S-1-5-whatever */
2037
2038                 DOM_SID tmp_sid;
2039
2040                 if (string_to_sid(&tmp_sid, name)) {
2041                         sid_copy(sid, &tmp_sid);
2042                         *type = SID_NAME_UNKNOWN;
2043                         result = NT_STATUS_OK;
2044                 }
2045         }
2046
2047         return result;
2048 }
2049
2050 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
2051                                 TALLOC_CTX *mem_ctx,
2052                                 const DOM_SID *group_sid,
2053                                 const char *member)
2054 {
2055         POLICY_HND connect_pol, domain_pol;
2056         NTSTATUS result;
2057         uint32 group_rid;
2058         POLICY_HND group_pol;
2059
2060         struct samr_Ids rids, rid_types;
2061         struct lsa_String lsa_acct_name;
2062
2063         DOM_SID sid;
2064
2065         sid_copy(&sid, group_sid);
2066
2067         if (!sid_split_rid(&sid, &group_rid)) {
2068                 return NT_STATUS_UNSUCCESSFUL;
2069         }
2070
2071         /* Get sam policy handle */
2072         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2073                                       pipe_hnd->desthost,
2074                                       MAXIMUM_ALLOWED_ACCESS,
2075                                       &connect_pol);
2076         if (!NT_STATUS_IS_OK(result)) {
2077                 return result;
2078         }
2079
2080         /* Get domain policy handle */
2081         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2082                                         &connect_pol,
2083                                         MAXIMUM_ALLOWED_ACCESS,
2084                                         &sid,
2085                                         &domain_pol);
2086         if (!NT_STATUS_IS_OK(result)) {
2087                 return result;
2088         }
2089
2090         init_lsa_String(&lsa_acct_name, member);
2091
2092         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2093                                          &domain_pol,
2094                                          1,
2095                                          &lsa_acct_name,
2096                                          &rids,
2097                                          &rid_types);
2098
2099         if (!NT_STATUS_IS_OK(result)) {
2100                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2101                 goto done;
2102         }
2103
2104         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2105                                        &domain_pol,
2106                                        MAXIMUM_ALLOWED_ACCESS,
2107                                        group_rid,
2108                                        &group_pol);
2109
2110         if (!NT_STATUS_IS_OK(result)) {
2111                 goto done;
2112         }
2113
2114         result = rpccli_samr_AddGroupMember(pipe_hnd, mem_ctx,
2115                                             &group_pol,
2116                                             rids.ids[0],
2117                                             0x0005); /* unknown flags */
2118
2119  done:
2120         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2121         return result;
2122 }
2123
2124 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
2125                                 TALLOC_CTX *mem_ctx,
2126                                 const DOM_SID *alias_sid,
2127                                 const char *member)
2128 {
2129         POLICY_HND connect_pol, domain_pol;
2130         NTSTATUS result;
2131         uint32 alias_rid;
2132         POLICY_HND alias_pol;
2133
2134         DOM_SID member_sid;
2135         enum lsa_SidType member_type;
2136
2137         DOM_SID sid;
2138
2139         sid_copy(&sid, alias_sid);
2140
2141         if (!sid_split_rid(&sid, &alias_rid)) {
2142                 return NT_STATUS_UNSUCCESSFUL;
2143         }
2144
2145         result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2146                                    member, &member_sid, &member_type);
2147
2148         if (!NT_STATUS_IS_OK(result)) {
2149                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2150                 return result;
2151         }
2152
2153         /* Get sam policy handle */
2154         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2155                                       pipe_hnd->desthost,
2156                                       MAXIMUM_ALLOWED_ACCESS,
2157                                       &connect_pol);
2158         if (!NT_STATUS_IS_OK(result)) {
2159                 goto done;
2160         }
2161
2162         /* Get domain policy handle */
2163         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2164                                         &connect_pol,
2165                                         MAXIMUM_ALLOWED_ACCESS,
2166                                         &sid,
2167                                         &domain_pol);
2168         if (!NT_STATUS_IS_OK(result)) {
2169                 goto done;
2170         }
2171
2172         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2173                                        &domain_pol,
2174                                        MAXIMUM_ALLOWED_ACCESS,
2175                                        alias_rid,
2176                                        &alias_pol);
2177
2178         if (!NT_STATUS_IS_OK(result)) {
2179                 return result;
2180         }
2181
2182         result = rpccli_samr_AddAliasMember(pipe_hnd, mem_ctx,
2183                                             &alias_pol,
2184                                             &member_sid);
2185
2186         if (!NT_STATUS_IS_OK(result)) {
2187                 return result;
2188         }
2189
2190  done:
2191         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2192         return result;
2193 }
2194
2195 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2196                                         const DOM_SID *domain_sid,
2197                                         const char *domain_name,
2198                                         struct cli_state *cli,
2199                                         struct rpc_pipe_client *pipe_hnd,
2200                                         TALLOC_CTX *mem_ctx,
2201                                         int argc,
2202                                         const char **argv)
2203 {
2204         DOM_SID group_sid;
2205         enum lsa_SidType group_type;
2206
2207         if (argc != 2 || c->display_usage) {
2208                 d_printf("Usage:\n"
2209                          "net rpc group addmem <group> <member>\n"
2210                          "  Add a member to a group\n"
2211                          "    group\tGroup to add member to\n"
2212                          "    member\tMember to add to group\n");
2213                 return NT_STATUS_UNSUCCESSFUL;
2214         }
2215
2216         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2217                                                &group_sid, &group_type))) {
2218                 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2219                 return NT_STATUS_UNSUCCESSFUL;
2220         }
2221
2222         if (group_type == SID_NAME_DOM_GRP) {
2223                 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2224                                                    &group_sid, argv[1]);
2225
2226                 if (!NT_STATUS_IS_OK(result)) {
2227                         d_fprintf(stderr, "Could not add %s to %s: %s\n",
2228                                  argv[1], argv[0], nt_errstr(result));
2229                 }
2230                 return result;
2231         }
2232
2233         if (group_type == SID_NAME_ALIAS) {
2234                 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2235                                                    &group_sid, argv[1]);
2236
2237                 if (!NT_STATUS_IS_OK(result)) {
2238                         d_fprintf(stderr, "Could not add %s to %s: %s\n",
2239                                  argv[1], argv[0], nt_errstr(result));
2240                 }
2241                 return result;
2242         }
2243
2244         d_fprintf(stderr, "Can only add members to global or local groups "
2245                  "which %s is not\n", argv[0]);
2246
2247         return NT_STATUS_UNSUCCESSFUL;
2248 }
2249
2250 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2251 {
2252         return run_rpc_command(c, NULL, PI_SAMR, 0,
2253                                rpc_group_addmem_internals,
2254                                argc, argv);
2255 }
2256
2257 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2258                                 struct rpc_pipe_client *pipe_hnd,
2259                                 TALLOC_CTX *mem_ctx,
2260                                 const DOM_SID *group_sid,
2261                                 const char *member)
2262 {
2263         POLICY_HND connect_pol, domain_pol;
2264         NTSTATUS result;
2265         uint32 group_rid;
2266         POLICY_HND group_pol;
2267
2268         struct samr_Ids rids, rid_types;
2269         struct lsa_String lsa_acct_name;
2270
2271         DOM_SID sid;
2272
2273         sid_copy(&sid, group_sid);
2274
2275         if (!sid_split_rid(&sid, &group_rid))
2276                 return NT_STATUS_UNSUCCESSFUL;
2277
2278         /* Get sam policy handle */
2279         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2280                                       pipe_hnd->desthost,
2281                                       MAXIMUM_ALLOWED_ACCESS,
2282                                       &connect_pol);
2283         if (!NT_STATUS_IS_OK(result))
2284                 return result;
2285
2286         /* Get domain policy handle */
2287         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2288                                         &connect_pol,
2289                                         MAXIMUM_ALLOWED_ACCESS,
2290                                         &sid,
2291                                         &domain_pol);
2292         if (!NT_STATUS_IS_OK(result))
2293                 return result;
2294
2295         init_lsa_String(&lsa_acct_name, member);
2296
2297         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2298                                          &domain_pol,
2299                                          1,
2300                                          &lsa_acct_name,
2301                                          &rids,
2302                                          &rid_types);
2303         if (!NT_STATUS_IS_OK(result)) {
2304                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2305                 goto done;
2306         }
2307
2308         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2309                                        &domain_pol,
2310                                        MAXIMUM_ALLOWED_ACCESS,
2311                                        group_rid,
2312                                        &group_pol);
2313
2314         if (!NT_STATUS_IS_OK(result))
2315                 goto done;
2316
2317         result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
2318                                                &group_pol,
2319                                                rids.ids[0]);
2320
2321  done:
2322         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2323         return result;
2324 }
2325
2326 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2327                                 TALLOC_CTX *mem_ctx,
2328                                 const DOM_SID *alias_sid,
2329                                 const char *member)
2330 {
2331         POLICY_HND connect_pol, domain_pol;
2332         NTSTATUS result;
2333         uint32 alias_rid;
2334         POLICY_HND alias_pol;
2335
2336         DOM_SID member_sid;
2337         enum lsa_SidType member_type;
2338
2339         DOM_SID sid;
2340
2341         sid_copy(&sid, alias_sid);
2342
2343         if (!sid_split_rid(&sid, &alias_rid))
2344                 return NT_STATUS_UNSUCCESSFUL;
2345
2346         result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2347                                    member, &member_sid, &member_type);
2348
2349         if (!NT_STATUS_IS_OK(result)) {
2350                 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2351                 return result;
2352         }
2353
2354         /* Get sam policy handle */
2355         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2356                                       pipe_hnd->desthost,
2357                                       MAXIMUM_ALLOWED_ACCESS,
2358                                       &connect_pol);
2359         if (!NT_STATUS_IS_OK(result)) {
2360                 goto done;
2361         }
2362
2363         /* Get domain policy handle */
2364         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2365                                         &connect_pol,
2366                                         MAXIMUM_ALLOWED_ACCESS,
2367                                         &sid,
2368                                         &domain_pol);
2369         if (!NT_STATUS_IS_OK(result)) {
2370                 goto done;
2371         }
2372
2373         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2374                                        &domain_pol,
2375                                        MAXIMUM_ALLOWED_ACCESS,
2376                                        alias_rid,
2377                                        &alias_pol);
2378
2379         if (!NT_STATUS_IS_OK(result))
2380                 return result;
2381
2382         result = rpccli_samr_DeleteAliasMember(pipe_hnd, mem_ctx,
2383                                                &alias_pol,
2384                                                &member_sid);
2385
2386         if (!NT_STATUS_IS_OK(result))
2387                 return result;
2388
2389  done:
2390         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2391         return result;
2392 }
2393
2394 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2395                                         const DOM_SID *domain_sid,
2396                                         const char *domain_name,
2397                                         struct cli_state *cli,
2398                                         struct rpc_pipe_client *pipe_hnd,
2399                                         TALLOC_CTX *mem_ctx,
2400                                         int argc,
2401                                         const char **argv)
2402 {
2403         DOM_SID group_sid;
2404         enum lsa_SidType group_type;
2405
2406         if (argc != 2 || c->display_usage) {
2407                 d_printf("Usage:\n"
2408                          "net rpc group delmem <group> <member>\n"
2409                          "  Delete a member from a group\n"
2410                          "    group\tGroup to delete member from\n"
2411                          "    member\tMember to delete from group\n");
2412                 return NT_STATUS_UNSUCCESSFUL;
2413         }
2414
2415         if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2416                                                &group_sid, &group_type))) {
2417                 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2418                 return NT_STATUS_UNSUCCESSFUL;
2419         }
2420
2421         if (group_type == SID_NAME_DOM_GRP) {
2422                 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2423                                                    &group_sid, argv[1]);
2424
2425                 if (!NT_STATUS_IS_OK(result)) {
2426                         d_fprintf(stderr, "Could not del %s from %s: %s\n",
2427                                  argv[1], argv[0], nt_errstr(result));
2428                 }
2429                 return result;
2430         }
2431
2432         if (group_type == SID_NAME_ALIAS) {
2433                 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2434                                                    &group_sid, argv[1]);
2435
2436                 if (!NT_STATUS_IS_OK(result)) {
2437                         d_fprintf(stderr, "Could not del %s from %s: %s\n",
2438                                  argv[1], argv[0], nt_errstr(result));
2439                 }
2440                 return result;
2441         }
2442
2443         d_fprintf(stderr, "Can only delete members from global or local groups "
2444                  "which %s is not\n", argv[0]);
2445
2446         return NT_STATUS_UNSUCCESSFUL;
2447 }
2448
2449 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2450 {
2451         return run_rpc_command(c, NULL, PI_SAMR, 0,
2452                                rpc_group_delmem_internals,
2453                                argc, argv);
2454 }
2455
2456 /**
2457  * List groups on a remote RPC server.
2458  *
2459  * All parameters are provided by the run_rpc_command function, except for
2460  * argc, argv which are passes through.
2461  *
2462  * @param domain_sid The domain sid acquired from the remote server.
2463  * @param cli A cli_state connected to the server.
2464  * @param mem_ctx Talloc context, destroyed on completion of the function.
2465  * @param argc  Standard main() style argc.
2466  * @param argv  Standard main() style argv. Initial components are already
2467  *              stripped.
2468  *
2469  * @return Normal NTSTATUS return.
2470  **/
2471
2472 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2473                                         const DOM_SID *domain_sid,
2474                                         const char *domain_name,
2475                                         struct cli_state *cli,
2476                                         struct rpc_pipe_client *pipe_hnd,
2477                                         TALLOC_CTX *mem_ctx,
2478                                         int argc,
2479                                         const char **argv)
2480 {
2481         POLICY_HND connect_pol, domain_pol;
2482         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2483         uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2484         struct samr_SamArray *groups = NULL;
2485         bool global = false;
2486         bool local = false;
2487         bool builtin = false;
2488
2489         if (c->display_usage) {
2490                 d_printf("Usage:\n"
2491                          "net rpc group list [global] [local] [builtin]\n"
2492                          "  List groups on RPC server\n"
2493                          "    global\tList global groups\n"
2494                          "    local\tList local groups\n"
2495                          "    builtin\tList builtin groups\n"
2496                          "    If none of global, local or builtin is "
2497                          "specified, all three options are considered set\n");
2498                 return NT_STATUS_OK;
2499         }
2500
2501         if (argc == 0) {
2502                 global = true;
2503                 local = true;
2504                 builtin = true;
2505         }
2506
2507         for (i=0; i<argc; i++) {
2508                 if (strequal(argv[i], "global"))
2509                         global = true;
2510
2511                 if (strequal(argv[i], "local"))
2512                         local = true;
2513
2514                 if (strequal(argv[i], "builtin"))
2515                         builtin = true;
2516         }
2517
2518         /* Get sam policy handle */
2519
2520         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2521                                       pipe_hnd->desthost,
2522                                       MAXIMUM_ALLOWED_ACCESS,
2523                                       &connect_pol);
2524         if (!NT_STATUS_IS_OK(result)) {
2525                 goto done;
2526         }
2527
2528         /* Get domain policy handle */
2529
2530         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2531                                         &connect_pol,
2532                                         MAXIMUM_ALLOWED_ACCESS,
2533                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2534                                         &domain_pol);
2535         if (!NT_STATUS_IS_OK(result)) {
2536                 goto done;
2537         }
2538
2539         /* Query domain groups */
2540         if (c->opt_long_list_entries)
2541                 d_printf("\nGroup name            Comment"
2542                          "\n-----------------------------\n");
2543         do {
2544                 uint32_t max_size, total_size, returned_size;
2545                 union samr_DispInfo info;
2546
2547                 if (!global) break;
2548
2549                 get_query_dispinfo_params(
2550                         loop_count, &max_entries, &max_size);
2551
2552                 result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
2553                                                       &domain_pol,
2554                                                       3,
2555                                                       start_idx,
2556                                                       max_entries,
2557                                                       max_size,
2558                                                       &total_size,
2559                                                       &returned_size,
2560                                                       &info);
2561                 num_entries = info.info3.count;
2562                 start_idx += info.info3.count;
2563
2564                 if (!NT_STATUS_IS_OK(result) &&
2565                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2566                         break;
2567
2568                 for (i = 0; i < num_entries; i++) {
2569
2570                         const char *group = NULL;
2571                         const char *desc = NULL;
2572
2573                         group = info.info3.entries[i].account_name.string;
2574                         desc = info.info3.entries[i].description.string;
2575
2576                         if (c->opt_long_list_entries)
2577                                 printf("%-21.21s %-50.50s\n",
2578                                        group, desc);
2579                         else
2580                                 printf("%s\n", group);
2581                 }
2582         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2583         /* query domain aliases */
2584         start_idx = 0;
2585         do {
2586                 if (!local) break;
2587
2588                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2589                                                        &domain_pol,
2590                                                        &start_idx,
2591                                                        &groups,
2592                                                        0xffff,
2593                                                        &num_entries);
2594                 if (!NT_STATUS_IS_OK(result) &&
2595                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2596                         break;
2597
2598                 for (i = 0; i < num_entries; i++) {
2599
2600                         const char *description = NULL;
2601
2602                         if (c->opt_long_list_entries) {
2603
2604                                 POLICY_HND alias_pol;
2605                                 union samr_AliasInfo *info = NULL;
2606
2607                                 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2608                                                                            &domain_pol,
2609                                                                            0x8,
2610                                                                            groups->entries[i].idx,
2611                                                                            &alias_pol))) &&
2612                                     (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2613                                                                                 &alias_pol,
2614                                                                                 3,
2615                                                                                 &info))) &&
2616                                     (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2617                                                                     &alias_pol)))) {
2618                                         description = info->description.string;
2619                                 }
2620                         }
2621
2622                         if (description != NULL) {
2623                                 printf("%-21.21s %-50.50s\n",
2624                                        groups->entries[i].name.string,
2625                                        description);
2626                         } else {
2627                                 printf("%s\n", groups->entries[i].name.string);
2628                         }
2629                 }
2630         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2631         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2632         /* Get builtin policy handle */
2633
2634         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2635                                         &connect_pol,
2636                                         MAXIMUM_ALLOWED_ACCESS,
2637                                         CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2638                                         &domain_pol);
2639         if (!NT_STATUS_IS_OK(result)) {
2640                 goto done;
2641         }
2642         /* query builtin aliases */
2643         start_idx = 0;
2644         do {
2645                 if (!builtin) break;
2646
2647                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2648                                                        &domain_pol,
2649                                                        &start_idx,
2650                                                        &groups,
2651                                                        max_entries,
2652                                                        &num_entries);
2653                 if (!NT_STATUS_IS_OK(result) &&
2654                     !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2655                         break;
2656
2657                 for (i = 0; i < num_entries; i++) {
2658
2659                         const char *description = NULL;
2660
2661                         if (c->opt_long_list_entries) {
2662
2663                                 POLICY_HND alias_pol;
2664                                 union samr_AliasInfo *info = NULL;
2665
2666                                 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2667                                                                            &domain_pol,
2668                                                                            0x8,
2669                                                                            groups->entries[i].idx,
2670                                                                            &alias_pol))) &&
2671                                     (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2672                                                                                 &alias_pol,
2673                                                                                 3,
2674                                                                                 &info))) &&
2675                                     (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2676                                                                     &alias_pol)))) {
2677                                         description = info->description.string;
2678                                 }
2679                         }
2680
2681                         if (description != NULL) {
2682                                 printf("%-21.21s %-50.50s\n",
2683                                        groups->entries[i].name.string,
2684                                        description);
2685                         } else {
2686                                 printf("%s\n", groups->entries[i].name.string);
2687                         }
2688                 }
2689         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2690
2691  done:
2692         return result;
2693 }
2694
2695 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2696 {
2697         return run_rpc_command(c, NULL, PI_SAMR, 0,
2698                                rpc_group_list_internals,
2699                                argc, argv);
2700 }
2701
2702 static NTSTATUS rpc_list_group_members(struct net_context *c,
2703                                         struct rpc_pipe_client *pipe_hnd,
2704                                         TALLOC_CTX *mem_ctx,
2705                                         const char *domain_name,
2706                                         const DOM_SID *domain_sid,
2707                                         POLICY_HND *domain_pol,
2708                                         uint32 rid)
2709 {
2710         NTSTATUS result;
2711         POLICY_HND group_pol;
2712         uint32 num_members, *group_rids;
2713         int i;
2714         struct samr_RidTypeArray *rids = NULL;
2715         struct lsa_Strings names;
2716         struct samr_Ids types;
2717
2718         fstring sid_str;
2719         sid_to_fstring(sid_str, domain_sid);
2720
2721         result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2722                                        domain_pol,
2723                                        MAXIMUM_ALLOWED_ACCESS,
2724                                        rid,
2725                                        &group_pol);
2726
2727         if (!NT_STATUS_IS_OK(result))
2728                 return result;
2729
2730         result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
2731                                               &group_pol,
2732                                               &rids);
2733
2734         if (!NT_STATUS_IS_OK(result))
2735                 return result;
2736
2737         num_members = rids->count;
2738         group_rids = rids->rids;
2739
2740         while (num_members > 0) {
2741                 int this_time = 512;
2742
2743                 if (num_members < this_time)
2744                         this_time = num_members;
2745
2746                 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
2747                                                 domain_pol,
2748                                                 this_time,
2749                                                 group_rids,
2750                                                 &names,
2751                                                 &types);
2752
2753                 if (!NT_STATUS_IS_OK(result))
2754                         return result;
2755
2756                 /* We only have users as members, but make the output
2757                    the same as the output of alias members */
2758
2759                 for (i = 0; i < this_time; i++) {
2760
2761                         if (c->opt_long_list_entries) {
2762                                 printf("%s-%d %s\\%s %d\n", sid_str,
2763                                        group_rids[i], domain_name,
2764                                        names.names[i].string,
2765                                        SID_NAME_USER);
2766                         } else {
2767                                 printf("%s\\%s\n", domain_name,
2768                                         names.names[i].string);
2769                         }
2770                 }
2771
2772                 num_members -= this_time;
2773                 group_rids += 512;
2774         }
2775
2776         return NT_STATUS_OK;
2777 }
2778
2779 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2780                                         struct rpc_pipe_client *pipe_hnd,
2781                                         TALLOC_CTX *mem_ctx,
2782                                         POLICY_HND *domain_pol,
2783                                         uint32 rid)
2784 {
2785         NTSTATUS result;
2786         struct rpc_pipe_client *lsa_pipe;
2787         POLICY_HND alias_pol, lsa_pol;
2788         uint32 num_members;
2789         DOM_SID *alias_sids;
2790         char **domains;
2791         char **names;
2792         enum lsa_SidType *types;
2793         int i;
2794         struct lsa_SidArray sid_array;
2795
2796         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2797                                        domain_pol,
2798                                        MAXIMUM_ALLOWED_ACCESS,
2799                                        rid,
2800                                        &alias_pol);
2801
2802         if (!NT_STATUS_IS_OK(result))
2803                 return result;
2804
2805         result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
2806                                                &alias_pol,
2807                                                &sid_array);
2808
2809         if (!NT_STATUS_IS_OK(result)) {
2810                 d_fprintf(stderr, "Couldn't list alias members\n");
2811                 return result;
2812         }
2813
2814         num_members = sid_array.num_sids;
2815
2816         if (num_members == 0) {
2817                 return NT_STATUS_OK;
2818         }
2819
2820         result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2821                                           &ndr_table_lsarpc.syntax_id,
2822                                           &lsa_pipe);
2823         if (!NT_STATUS_IS_OK(result)) {
2824                 d_fprintf(stderr, "Couldn't open LSA pipe. Error was %s\n",
2825                         nt_errstr(result) );
2826                 return result;
2827         }
2828
2829         result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2830                                      SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
2831
2832         if (!NT_STATUS_IS_OK(result)) {
2833                 d_fprintf(stderr, "Couldn't open LSA policy handle\n");
2834                 TALLOC_FREE(lsa_pipe);
2835                 return result;
2836         }
2837
2838         alias_sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_members);
2839         if (!alias_sids) {
2840                 d_fprintf(stderr, "Out of memory\n");
2841                 TALLOC_FREE(lsa_pipe);
2842                 return NT_STATUS_NO_MEMORY;
2843         }
2844
2845         for (i=0; i<num_members; i++) {
2846                 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2847         }
2848
2849         result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
2850                                      num_members,  alias_sids,
2851                                      &domains, &names, &types);
2852
2853         if (!NT_STATUS_IS_OK(result) &&
2854             !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2855                 d_fprintf(stderr, "Couldn't lookup SIDs\n");
2856                 TALLOC_FREE(lsa_pipe);
2857                 return result;
2858         }
2859
2860         for (i = 0; i < num_members; i++) {
2861                 fstring sid_str;
2862                 sid_to_fstring(sid_str, &alias_sids[i]);
2863
2864                 if (c->opt_long_list_entries) {
2865                         printf("%s %s\\%s %d\n", sid_str,
2866                                domains[i] ? domains[i] : "*unknown*",
2867                                names[i] ? names[i] : "*unknown*", types[i]);
2868                 } else {
2869                         if (domains[i])
2870                                 printf("%s\\%s\n", domains[i], names[i]);
2871                         else
2872                                 printf("%s\n", sid_str);
2873                 }
2874         }
2875
2876         TALLOC_FREE(lsa_pipe);
2877         return NT_STATUS_OK;
2878 }
2879
2880 static NTSTATUS rpc_group_members_internals(struct net_context *c,
2881                                         const DOM_SID *domain_sid,
2882                                         const char *domain_name,
2883                                         struct cli_state *cli,
2884                                         struct rpc_pipe_client *pipe_hnd,
2885                                         TALLOC_CTX *mem_ctx,
2886                                         int argc,
2887                                         const char **argv)
2888 {
2889         NTSTATUS result;
2890         POLICY_HND connect_pol, domain_pol;
2891         struct samr_Ids rids, rid_types;
2892         struct lsa_String lsa_acct_name;
2893
2894         /* Get sam policy handle */
2895
2896         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2897                                       pipe_hnd->desthost,
2898                                       MAXIMUM_ALLOWED_ACCESS,
2899                                       &connect_pol);
2900
2901         if (!NT_STATUS_IS_OK(result))
2902                 return result;
2903
2904         /* Get domain policy handle */
2905
2906         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2907                                         &connect_pol,
2908                                         MAXIMUM_ALLOWED_ACCESS,
2909                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
2910                                         &domain_pol);
2911
2912         if (!NT_STATUS_IS_OK(result))
2913                 return result;
2914
2915         init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
2916
2917         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2918                                          &domain_pol,
2919                                          1,
2920                                          &lsa_acct_name,
2921                                          &rids,
2922                                          &rid_types);
2923
2924         if (!NT_STATUS_IS_OK(result)) {
2925
2926                 /* Ok, did not find it in the global sam, try with builtin */
2927
2928                 DOM_SID sid_Builtin;
2929
2930                 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2931
2932                 sid_copy(&sid_Builtin, &global_sid_Builtin);
2933
2934                 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2935                                                 &connect_pol,
2936                                                 MAXIMUM_ALLOWED_ACCESS,
2937                                                 &sid_Builtin,
2938                                                 &domain_pol);
2939
2940                 if (!NT_STATUS_IS_OK(result)) {
2941                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2942                         return result;
2943                 }
2944
2945                 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2946                                                  &domain_pol,
2947                                                  1,
2948                                                  &lsa_acct_name,
2949                                                  &rids,
2950                                                  &rid_types);
2951
2952                 if (!NT_STATUS_IS_OK(result)) {
2953                         d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2954                         return result;
2955                 }
2956         }
2957
2958         if (rids.count != 1) {
2959                 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2960                 return result;
2961         }
2962
2963         if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
2964                 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
2965                                               domain_sid, &domain_pol,
2966                                               rids.ids[0]);
2967         }
2968
2969         if (rid_types.ids[0] == SID_NAME_ALIAS) {
2970                 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
2971                                               rids.ids[0]);
2972         }
2973
2974         return NT_STATUS_NO_SUCH_GROUP;
2975 }
2976
2977 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
2978 {
2979         if (argc != 1 || c->display_usage) {
2980                 return rpc_group_usage(c, argc, argv);
2981         }
2982
2983         return run_rpc_command(c, NULL, PI_SAMR, 0,
2984                                rpc_group_members_internals,
2985                                argc, argv);
2986 }
2987
2988 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
2989 {
2990         NET_API_STATUS status;
2991         struct GROUP_INFO_0 g0;
2992         uint32_t parm_err;
2993
2994         if (argc != 2) {
2995                 d_printf("Usage: 'net rpc group rename group newname'\n");
2996                 return -1;
2997         }
2998
2999         g0.grpi0_name = argv[1];
3000
3001         status = NetGroupSetInfo(c->opt_host,
3002                                  argv[0],
3003                                  0,
3004                                  (uint8_t *)&g0,
3005                                  &parm_err);
3006
3007         if (status != 0) {
3008                 d_fprintf(stderr, "Renaming group %s failed with: %s\n",
3009                         argv[0], libnetapi_get_error_string(c->netapi_ctx,
3010                         status));
3011                 return -1;
3012         }
3013
3014         return 0;
3015 }
3016
3017 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
3018 {
3019         if (argc != 2 || c->display_usage) {
3020                 return rpc_group_usage(c, argc, argv);
3021         }
3022
3023         return rpc_group_rename_internals(c, argc, argv);
3024 }
3025
3026 /**
3027  * 'net rpc group' entrypoint.
3028  * @param argc  Standard main() style argc.
3029  * @param argv  Standard main() style argv. Initial components are already
3030  *              stripped.
3031  **/
3032
3033 int net_rpc_group(struct net_context *c, int argc, const char **argv)
3034 {
3035         NET_API_STATUS status;
3036
3037         struct functable func[] = {
3038                 {
3039                         "add",
3040                         rpc_group_add,
3041                         NET_TRANSPORT_RPC,
3042                         "Create specified group",
3043                         "net rpc group add\n"
3044                         "    Create specified group"
3045                 },
3046                 {
3047                         "delete",
3048                         rpc_group_delete,
3049                         NET_TRANSPORT_RPC,
3050                         "Delete specified group",
3051                         "net rpc group delete\n"
3052                         "    Delete specified group"
3053                 },
3054                 {
3055                         "addmem",
3056                         rpc_group_addmem,
3057                         NET_TRANSPORT_RPC,
3058                         "Add member to group",
3059                         "net rpc group addmem\n"
3060                         "    Add member to group"
3061                 },
3062                 {
3063                         "delmem",
3064                         rpc_group_delmem,
3065                         NET_TRANSPORT_RPC,
3066                         "Remove member from group",
3067                         "net rpc group delmem\n"
3068                         "    Remove member from group"
3069                 },
3070                 {
3071                         "list",
3072                         rpc_group_list,
3073                         NET_TRANSPORT_RPC,
3074                         "List groups",
3075                         "net rpc group list\n"
3076                         "    List groups"
3077                 },
3078                 {
3079                         "members",
3080                         rpc_group_members,
3081                         NET_TRANSPORT_RPC,
3082                         "List group members",
3083                         "net rpc group members\n"
3084                         "    List group members"
3085                 },
3086                 {
3087                         "rename",
3088                         rpc_group_rename,
3089                         NET_TRANSPORT_RPC,
3090                         "Rename group",
3091                         "net rpc group rename\n"
3092                         "    Rename group"
3093                 },
3094                 {NULL, NULL, 0, NULL, NULL}
3095         };
3096
3097         status = libnetapi_init(&c->netapi_ctx);
3098         if (status != 0) {
3099                 return -1;
3100         }
3101         libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
3102         libnetapi_set_password(c->netapi_ctx, c->opt_password);
3103
3104         if (argc == 0) {
3105                 if (c->display_usage) {
3106                         d_printf("Usage:\n");
3107                         d_printf("net rpc group\n"
3108                                  "    Alias for net rpc group list global local "
3109                                  "builtin\n");
3110                         net_display_usage_from_functable(func);
3111                         return 0;
3112                 }
3113
3114                 return run_rpc_command(c, NULL, PI_SAMR, 0,
3115                                        rpc_group_list_internals,
3116                                        argc, argv);
3117         }
3118
3119         return net_run_function(c, argc, argv, "net rpc group", func);
3120 }
3121
3122 /****************************************************************************/
3123
3124 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
3125 {
3126         return net_share_usage(c, argc, argv);
3127 }
3128
3129 /**
3130  * Add a share on a remote RPC server.
3131  *
3132  * All parameters are provided by the run_rpc_command function, except for
3133  * argc, argv which are passed through.
3134  *
3135  * @param domain_sid The domain sid acquired from the remote server.
3136  * @param cli A cli_state connected to the server.
3137  * @param mem_ctx Talloc context, destroyed on completion of the function.
3138  * @param argc  Standard main() style argc.
3139  * @param argv  Standard main() style argv. Initial components are already
3140  *              stripped.
3141  *
3142  * @return Normal NTSTATUS return.
3143  **/
3144 static NTSTATUS rpc_share_add_internals(struct net_context *c,
3145                                         const DOM_SID *domain_sid,
3146                                         const char *domain_name,
3147                                         struct cli_state *cli,
3148                                         struct rpc_pipe_client *pipe_hnd,
3149                                         TALLOC_CTX *mem_ctx,int argc,
3150                                         const char **argv)
3151 {
3152         WERROR result;
3153         NTSTATUS status;
3154         char *sharename;
3155         char *path;
3156         uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3157         uint32 num_users=0, perms=0;
3158         char *password=NULL; /* don't allow a share password */
3159         uint32 level = 2;
3160         union srvsvc_NetShareInfo info;
3161         struct srvsvc_NetShareInfo2 info2;
3162         uint32_t parm_error = 0;
3163
3164         if ((sharename = talloc_strdup(mem_ctx, argv[0])) == NULL) {
3165                 return NT_STATUS_NO_MEMORY;
3166         }
3167
3168         path = strchr(sharename, '=');
3169         if (!path)
3170                 return NT_STATUS_UNSUCCESSFUL;
3171         *path++ = '\0';
3172
3173         info2.name              = sharename;
3174         info2.type              = type;
3175         info2.comment           = c->opt_comment;
3176         info2.permissions       = perms;
3177         info2.max_users         = c->opt_maxusers;
3178         info2.current_users     = num_users;
3179         info2.path              = path;
3180         info2.password          = password;
3181
3182         info.info2 = &info2;
3183
3184         status = rpccli_srvsvc_NetShareAdd(pipe_hnd, mem_ctx,
3185                                            pipe_hnd->desthost,
3186                                            level,
3187                                            &info,
3188                                            &parm_error,
3189                                            &result);
3190         return status;
3191 }
3192
3193 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3194 {
3195         if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3196                 return rpc_share_usage(c, argc, argv);
3197         }
3198         return run_rpc_command(c, NULL, PI_SRVSVC, 0,
3199                                rpc_share_add_internals,
3200                                argc, argv);
3201 }
3202
3203 /**
3204  * Delete a share on a remote RPC server.
3205  *
3206  * All parameters are provided by the run_rpc_command function, except for
3207  * argc, argv which are passed through.
3208  *
3209  * @param domain_sid The domain sid acquired from the remote server.
3210  * @param cli A cli_state connected to the server.
3211  * @param mem_ctx Talloc context, destroyed on completion of the function.
3212  * @param argc  Standard main() style argc.
3213  * @param argv  Standard main() style argv. Initial components are already
3214  *              stripped.
3215  *
3216  * @return Normal NTSTATUS return.
3217  **/
3218 static NTSTATUS rpc_share_del_internals(struct net_context *c,
3219                                         const DOM_SID *domain_sid,
3220                                         const char *domain_name,
3221                                         struct cli_state *cli,
3222                                         struct rpc_pipe_client *pipe_hnd,
3223                                         TALLOC_CTX *mem_ctx,
3224                                         int argc,
3225                                         const char **argv)
3226 {
3227         WERROR result;
3228
3229         return rpccli_srvsvc_NetShareDel(pipe_hnd, mem_ctx,
3230                                          pipe_hnd->desthost,
3231                                          argv[0],
3232                                          0,
3233                                          &result);
3234 }
3235
3236 /**
3237  * Delete a share on a remote RPC server.
3238  *
3239  * @param domain_sid The domain sid acquired from the remote server.
3240  * @param argc  Standard main() style argc.
3241  * @param argv  Standard main() style argv. Initial components are already
3242  *              stripped.
3243  *
3244  * @return A shell status integer (0 for success).
3245  **/
3246 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3247 {
3248         if (argc < 1 || c->display_usage) {
3249                 return rpc_share_usage(c, argc, argv);
3250         }
3251         return run_rpc_command(c, NULL, PI_SRVSVC, 0,
3252                                rpc_share_del_internals,
3253                                argc, argv);
3254 }
3255
3256 /**
3257  * Formatted print of share info
3258  *
3259  * @param info1  pointer to SRV_SHARE_INFO_1 to format
3260  **/
3261
3262 static void display_share_info_1(struct net_context *c,
3263                                  struct srvsvc_NetShareInfo1 *r)
3264 {
3265         if (c->opt_long_list_entries) {
3266                 d_printf("%-12s %-8.8s %-50s\n",
3267                          r->name,
3268                          c->share_type[r->type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)],
3269                          r->comment);
3270         } else {
3271                 d_printf("%s\n", r->name);
3272         }
3273 }
3274
3275 static WERROR get_share_info(struct net_context *c,
3276                              struct rpc_pipe_client *pipe_hnd,
3277                              TALLOC_CTX *mem_ctx,
3278                              uint32 level,
3279                              int argc,
3280                              const char **argv,
3281                              struct srvsvc_NetShareInfoCtr *info_ctr)
3282 {
3283         WERROR result;
3284         NTSTATUS status;
3285         union srvsvc_NetShareInfo info;
3286
3287         /* no specific share requested, enumerate all */
3288         if (argc == 0) {
3289
3290                 uint32_t preferred_len = 0xffffffff;
3291                 uint32_t total_entries = 0;
3292                 uint32_t resume_handle = 0;
3293
3294                 info_ctr->level = level;
3295
3296                 status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, mem_ctx,
3297                                                        pipe_hnd->desthost,
3298                                                        info_ctr,
3299                                                        preferred_len,
3300                                                        &total_entries,
3301                                                        &resume_handle,
3302                                                        &result);
3303                 return result;
3304         }
3305
3306         /* request just one share */
3307         status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
3308                                                pipe_hnd->desthost,
3309                                                argv[0],
3310                                                level,
3311                                                &info,
3312                                                &result);
3313
3314         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
3315                 goto done;
3316         }
3317
3318         /* construct ctr */
3319         ZERO_STRUCTP(info_ctr);
3320
3321         info_ctr->level = level;
3322
3323         switch (level) {
3324         case 1:
3325         {
3326                 struct srvsvc_NetShareCtr1 *ctr1;
3327
3328                 ctr1 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr1);
3329                 W_ERROR_HAVE_NO_MEMORY(ctr1);
3330
3331                 ctr1->count = 1;
3332                 ctr1->array = info.info1;
3333
3334                 info_ctr->ctr.ctr1 = ctr1;
3335         }
3336         case 2:
3337         {
3338                 struct srvsvc_NetShareCtr2 *ctr2;
3339
3340                 ctr2 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr2);
3341                 W_ERROR_HAVE_NO_MEMORY(ctr2);
3342
3343                 ctr2->count = 1;
3344                 ctr2->array = info.info2;
3345
3346                 info_ctr->ctr.ctr2 = ctr2;
3347         }
3348         case 502:
3349         {
3350                 struct srvsvc_NetShareCtr502 *ctr502;
3351
3352                 ctr502 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr502);
3353                 W_ERROR_HAVE_NO_MEMORY(ctr502);
3354
3355                 ctr502->count = 1;
3356                 ctr502->array = info.info502;
3357
3358                 info_ctr->ctr.ctr502 = ctr502;
3359         }
3360         } /* switch */
3361 done:
3362         return result;
3363 }
3364
3365 /**
3366  * List shares on a remote RPC server.
3367  *
3368  * All parameters are provided by the run_rpc_command function, except for
3369  * argc, argv which are passed through.
3370  *
3371  * @param domain_sid The domain sid acquired from the remote server.
3372  * @param cli A cli_state connected to the server.
3373  * @param mem_ctx Talloc context, destroyed on completion of the function.
3374  * @param argc  Standard main() style argc.
3375  * @param argv  Standard main() style argv. Initial components are already
3376  *              stripped.
3377  *
3378  * @return Normal NTSTATUS return.
3379  **/
3380
3381 static NTSTATUS rpc_share_list_internals(struct net_context *c,
3382                                         const DOM_SID *domain_sid,
3383                                         const char *domain_name,
3384                                         struct cli_state *cli,
3385                                         struct rpc_pipe_client *pipe_hnd,
3386                                         TALLOC_CTX *mem_ctx,
3387                                         int argc,
3388                                         const char **argv)
3389 {
3390         struct srvsvc_NetShareInfoCtr info_ctr;
3391         struct srvsvc_NetShareCtr1 ctr1;
3392         WERROR result;
3393         uint32 i, level = 1;
3394
3395         ZERO_STRUCT(info_ctr);
3396         ZERO_STRUCT(ctr1);
3397
3398         info_ctr.level = 1;
3399         info_ctr.ctr.ctr1 = &ctr1;
3400
3401         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3402                                 &info_ctr);
3403         if (!W_ERROR_IS_OK(result))
3404                 goto done;
3405
3406         /* Display results */
3407
3408         if (c->opt_long_list_entries) {
3409                 d_printf(
3410         "\nEnumerating shared resources (exports) on remote server:\n\n"
3411         "\nShare name   Type     Description\n"
3412         "----------   ----     -----------\n");
3413         }
3414         for (i = 0; i < info_ctr.ctr.ctr1->count; i++)
3415                 display_share_info_1(c, &info_ctr.ctr.ctr1->array[i]);
3416  done:
3417         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3418 }
3419
3420 /***
3421  * 'net rpc share list' entrypoint.
3422  * @param argc  Standard main() style argc.
3423  * @param argv  Standard main() style argv. Initial components are already
3424  *              stripped.
3425  **/
3426 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3427 {
3428         if (c->display_usage) {
3429                 d_printf("Usage\n"
3430                          "net rpc share list\n"
3431                          "    List shares on remote server\n");
3432                 return 0;
3433         }
3434
3435         return run_rpc_command(c, NULL, PI_SRVSVC, 0, rpc_share_list_internals,
3436                                argc, argv);
3437 }
3438
3439 static bool check_share_availability(struct cli_state *cli, const char *netname)
3440 {
3441         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
3442                 d_printf("skipping   [%s]: not a file share.\n", netname);
3443                 return false;
3444         }
3445
3446         if (!cli_tdis(cli))
3447                 return false;
3448
3449         return true;
3450 }
3451
3452 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3453                                const char *netname, uint32 type)
3454 {
3455         /* only support disk shares */
3456         if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3457                 printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
3458                 return false;
3459         }
3460
3461         /* skip builtin shares */
3462         /* FIXME: should print$ be added too ? */
3463         if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3464             strequal(netname,"global"))
3465                 return false;
3466
3467         if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3468                 printf("excluding  [%s]\n", netname);
3469                 return false;
3470         }
3471
3472         return check_share_availability(cli, netname);
3473 }
3474
3475 /**
3476  * Migrate shares from a remote RPC server to the local RPC server.
3477  *
3478  * All parameters are provided by the run_rpc_command function, except for
3479  * argc, argv which are passed through.
3480  *
3481  * @param domain_sid The domain sid acquired from the remote server.
3482  * @param cli A cli_state connected to the server.
3483  * @param mem_ctx Talloc context, destroyed on completion of the function.
3484  * @param argc  Standard main() style argc.
3485  * @param argv  Standard main() style argv. Initial components are already
3486  *              stripped.
3487  *
3488  * @return Normal NTSTATUS return.
3489  **/
3490
3491 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3492                                                 const DOM_SID *domain_sid,
3493                                                 const char *domain_name,
3494                                                 struct cli_state *cli,
3495                                                 struct rpc_pipe_client *pipe_hnd,
3496                                                 TALLOC_CTX *mem_ctx,
3497                                                 int argc,
3498                                                 const char **argv)
3499 {
3500         WERROR result;
3501         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3502         struct srvsvc_NetShareInfoCtr ctr_src;
3503         uint32 i;
3504         struct rpc_pipe_client *srvsvc_pipe = NULL;
3505         struct cli_state *cli_dst = NULL;
3506         uint32 level = 502; /* includes secdesc */
3507         uint32_t parm_error = 0;
3508
3509         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3510                                 &ctr_src);
3511         if (!W_ERROR_IS_OK(result))
3512                 goto done;
3513
3514         /* connect destination PI_SRVSVC */
3515         nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe, PI_SRVSVC);
3516         if (!NT_STATUS_IS_OK(nt_status))
3517                 return nt_status;
3518
3519
3520         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3521
3522                 union srvsvc_NetShareInfo info;
3523                 struct srvsvc_NetShareInfo502 info502 =
3524                         ctr_src.ctr.ctr502->array[i];
3525
3526                 /* reset error-code */
3527                 nt_status = NT_STATUS_UNSUCCESSFUL;
3528
3529                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3530                         continue;
3531
3532                 /* finally add the share on the dst server */
3533
3534                 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n", 
3535                         info502.name, info502.path, info502.comment);
3536
3537                 info.info502 = &info502;
3538
3539                 nt_status = rpccli_srvsvc_NetShareAdd(srvsvc_pipe, mem_ctx,
3540                                                       srvsvc_pipe->desthost,
3541                                                       502,
3542                                                       &info,
3543                                                       &parm_error,
3544                                                       &result);
3545
3546                 if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
3547                         printf("           [%s] does already exist\n",
3548                                 info502.name);
3549                         continue;
3550                 }
3551
3552                 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3553                         printf("cannot add share: %s\n", dos_errstr(result));
3554                         goto done;
3555                 }
3556
3557         }
3558
3559         nt_status = NT_STATUS_OK;
3560
3561 done:
3562         if (cli_dst) {
3563                 cli_shutdown(cli_dst);
3564         }
3565
3566         return nt_status;
3567
3568 }
3569
3570 /**
3571  * Migrate shares from a RPC server to another.
3572  *
3573  * @param argc  Standard main() style argc.
3574  * @param argv  Standard main() style argv. Initial components are already
3575  *              stripped.
3576  *
3577  * @return A shell status integer (0 for success).
3578  **/
3579 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3580                                     const char **argv)
3581 {
3582         if (c->display_usage) {
3583                 d_printf("Usage:\n"
3584                          "net rpc share migrate shares\n"
3585                          "    Migrate shares to local server\n");
3586                 return 0;
3587         }
3588
3589         if (!c->opt_host) {
3590                 printf("no server to migrate\n");
3591                 return -1;
3592         }
3593
3594         return run_rpc_command(c, NULL, PI_SRVSVC, 0,
3595                                rpc_share_migrate_shares_internals,
3596                                argc, argv);
3597 }
3598
3599 /**
3600  * Copy a file/dir
3601  *
3602  * @param f     file_info
3603  * @param mask  current search mask
3604  * @param state arg-pointer
3605  *
3606  **/
3607 static void copy_fn(const char *mnt, file_info *f,
3608                     const char *mask, void *state)
3609 {
3610         static NTSTATUS nt_status;
3611         static struct copy_clistate *local_state;
3612         static fstring filename, new_mask;
3613         fstring dir;
3614         char *old_dir;
3615         struct net_context *c;
3616
3617         local_state = (struct copy_clistate *)state;
3618         nt_status = NT_STATUS_UNSUCCESSFUL;
3619
3620         c = local_state->c;
3621
3622         if (strequal(f->name, ".") || strequal(f->name, ".."))
3623                 return;
3624
3625         DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3626
3627         /* DIRECTORY */
3628         if (f->mode & aDIR) {
3629
3630                 DEBUG(3,("got dir: %s\n", f->name));
3631
3632                 fstrcpy(dir, local_state->cwd);
3633                 fstrcat(dir, "\\");
3634                 fstrcat(dir, f->name);
3635
3636                 switch (net_mode_share)
3637                 {
3638                 case NET_MODE_SHARE_MIGRATE:
3639                         /* create that directory */
3640                         nt_status = net_copy_file(c, local_state->mem_ctx,
3641                                                   local_state->cli_share_src,
3642                                                   local_state->cli_share_dst,
3643                                                   dir, dir,
3644                                                   c->opt_acls? true : false,
3645                                                   c->opt_attrs? true : false,
3646                                                   c->opt_timestamps? true:false,
3647                                                   false);
3648                         break;
3649                 default:
3650                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3651                         return;
3652                 }
3653
3654                 if (!NT_STATUS_IS_OK(nt_status))
3655                         printf("could not handle dir %s: %s\n",
3656                                 dir, nt_errstr(nt_status));
3657
3658                 /* search below that directory */
3659                 fstrcpy(new_mask, dir);
3660                 fstrcat(new_mask, "\\*");
3661
3662                 old_dir = local_state->cwd;
3663                 local_state->cwd = dir;
3664                 if (!sync_files(local_state, new_mask))
3665                         printf("could not handle files\n");
3666                 local_state->cwd = old_dir;
3667
3668                 return;
3669         }
3670
3671
3672         /* FILE */
3673         fstrcpy(filename, local_state->cwd);
3674         fstrcat(filename, "\\");
3675         fstrcat(filename, f->name);
3676
3677         DEBUG(3,("got file: %s\n", filename));
3678
3679         switch (net_mode_share)
3680         {
3681         case NET_MODE_SHARE_MIGRATE:
3682                 nt_status = net_copy_file(c, local_state->mem_ctx,
3683                                           local_state->cli_share_src,
3684                                           local_state->cli_share_dst,
3685                                           filename, filename,
3686                                           c->opt_acls? true : false,
3687                                           c->opt_attrs? true : false,
3688                                           c->opt_timestamps? true: false,
3689                                           true);
3690                 break;
3691         default:
3692                 d_fprintf(stderr, "Unsupported file mode %d\n", net_mode_share);
3693                 return;
3694         }
3695
3696         if (!NT_STATUS_IS_OK(nt_status))
3697                 printf("could not handle file %s: %s\n",
3698                         filename, nt_errstr(nt_status));
3699
3700 }
3701
3702 /**
3703  * sync files, can be called recursivly to list files
3704  * and then call copy_fn for each file
3705  *
3706  * @param cp_clistate   pointer to the copy_clistate we work with
3707  * @param mask          the current search mask
3708  *
3709  * @return              Boolean result
3710  **/
3711 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask)
3712 {
3713         struct cli_state *targetcli;
3714         char *targetpath = NULL;
3715
3716         DEBUG(3,("calling cli_list with mask: %s\n", mask));
3717
3718         if ( !cli_resolve_path(talloc_tos(), "", cp_clistate->cli_share_src,
3719                                 mask, &targetcli, &targetpath ) ) {
3720                 d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n", 
3721                         mask, cli_errstr(cp_clistate->cli_share_src));
3722                 return false;
3723         }
3724
3725         if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3726                 d_fprintf(stderr, "listing %s failed with error: %s\n",
3727                         mask, cli_errstr(targetcli));
3728                 return false;
3729         }
3730
3731         return true;
3732 }
3733
3734
3735 /**
3736  * Set the top level directory permissions before we do any further copies.
3737  * Should set up ACL inheritance.
3738  **/
3739
3740 bool copy_top_level_perms(struct net_context *c,
3741                                 struct copy_clistate *cp_clistate,
3742                                 const char *sharename)
3743 {
3744         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3745
3746         switch (net_mode_share) {
3747         case NET_MODE_SHARE_MIGRATE:
3748                 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3749                 nt_status = net_copy_fileattr(c,
3750                                                 cp_clistate->mem_ctx,
3751                                                 cp_clistate->cli_share_src,
3752                                                 cp_clistate->cli_share_dst,
3753                                                 "\\", "\\",
3754                                                 c->opt_acls? true : false,
3755                                                 c->opt_attrs? true : false,
3756                                                 c->opt_timestamps? true: false,
3757                                                 false);
3758                 break;
3759         default:
3760                 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3761                 break;
3762         }
3763
3764         if (!NT_STATUS_IS_OK(nt_status))  {
3765                 printf("Could handle directory attributes for top level directory of share %s. Error %s\n", 
3766                         sharename, nt_errstr(nt_status));
3767                 return false;
3768         }
3769
3770         return true;
3771 }
3772
3773 /**
3774  * Sync all files inside a remote share to another share (over smb).
3775  *
3776  * All parameters are provided by the run_rpc_command function, except for
3777  * argc, argv which are passed through.
3778  *
3779  * @param domain_sid The domain sid acquired from the remote server.
3780  * @param cli A cli_state connected to the server.
3781  * @param mem_ctx Talloc context, destroyed on completion of the function.
3782  * @param argc  Standard main() style argc.
3783  * @param argv  Standard main() style argv. Initial components are already
3784  *              stripped.
3785  *
3786  * @return Normal NTSTATUS return.
3787  **/
3788
3789 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
3790                                                 const DOM_SID *domain_sid,
3791                                                 const char *domain_name,
3792                                                 struct cli_state *cli,
3793                                                 struct rpc_pipe_client *pipe_hnd,
3794                                                 TALLOC_CTX *mem_ctx,
3795                                                 int argc,
3796                                                 const char **argv)
3797 {
3798         WERROR result;
3799         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3800         struct srvsvc_NetShareInfoCtr ctr_src;
3801         uint32 i;
3802         uint32 level = 502;
3803         struct copy_clistate cp_clistate;
3804         bool got_src_share = false;
3805         bool got_dst_share = false;
3806         const char *mask = "\\*";
3807         char *dst = NULL;
3808
3809         dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3810         if (dst == NULL) {
3811                 nt_status = NT_STATUS_NO_MEMORY;
3812                 goto done;
3813         }
3814
3815         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3816                                 &ctr_src);
3817
3818         if (!W_ERROR_IS_OK(result))
3819                 goto done;
3820
3821         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3822
3823                 struct srvsvc_NetShareInfo502 info502 =
3824                         ctr_src.ctr.ctr502->array[i];
3825
3826                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3827                         continue;
3828
3829                 /* one might not want to mirror whole discs :) */
3830                 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3831                         d_printf("skipping   [%s]: builtin/hidden share\n", info502.name);
3832                         continue;
3833                 }
3834
3835                 switch (net_mode_share)
3836                 {
3837                 case NET_MODE_SHARE_MIGRATE:
3838                         printf("syncing");
3839                         break;
3840                 default:
3841                         d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3842                         break;
3843                 }
3844                 printf("    [%s] files and directories %s ACLs, %s DOS Attributes %s\n", 
3845                         info502.name,
3846                         c->opt_acls ? "including" : "without",
3847                         c->opt_attrs ? "including" : "without",
3848                         c->opt_timestamps ? "(preserving timestamps)" : "");
3849
3850                 cp_clistate.mem_ctx = mem_ctx;
3851                 cp_clistate.cli_share_src = NULL;
3852                 cp_clistate.cli_share_dst = NULL;
3853                 cp_clistate.cwd = NULL;
3854                 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3855                 cp_clistate.c = c;
3856
3857                 /* open share source */
3858                 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
3859                                                &cli->dest_ss, cli->desthost,
3860                                                info502.name, "A:");
3861                 if (!NT_STATUS_IS_OK(nt_status))
3862                         goto done;
3863
3864                 got_src_share = true;
3865
3866                 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3867                         /* open share destination */
3868                         nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
3869                                                        NULL, dst, info502.name, "A:");
3870                         if (!NT_STATUS_IS_OK(nt_status))
3871                                 goto done;
3872
3873                         got_dst_share = true;
3874                 }
3875
3876                 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
3877                         d_fprintf(stderr, "Could not handle the top level directory permissions for the share: %s\n", info502.name);
3878                         nt_status = NT_STATUS_UNSUCCESSFUL;
3879                         goto done;
3880                 }
3881
3882                 if (!sync_files(&cp_clistate, mask)) {
3883                         d_fprintf(stderr, "could not handle files for share: %s\n", info502.name);
3884                         nt_status = NT_STATUS_UNSUCCESSFUL;
3885                         goto done;
3886                 }
3887         }
3888
3889         nt_status = NT_STATUS_OK;
3890
3891 done:
3892
3893         if (got_src_share)
3894                 cli_shutdown(cp_clistate.cli_share_src);
3895
3896         if (got_dst_share)
3897                 cli_shutdown(cp_clistate.cli_share_dst);
3898
3899         SAFE_FREE(dst);
3900         return nt_status;
3901
3902 }
3903
3904 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
3905 {
3906         if (c->display_usage) {
3907                 d_printf("Usage:\n"
3908                          "net share migrate files\n"
3909                          "    Migrate files to local server\n");
3910                 return 0;
3911         }
3912
3913         if (!c->opt_host) {
3914                 d_printf("no server to migrate\n");
3915                 return -1;
3916         }
3917
3918         return run_rpc_command(c, NULL, PI_SRVSVC, 0,
3919                                rpc_share_migrate_files_internals,
3920                                argc, argv);
3921 }
3922
3923 /**
3924  * Migrate share-ACLs from a remote RPC server to the local RPC server.
3925  *
3926  * All parameters are provided by the run_rpc_command function, except for
3927  * argc, argv which are passed through.
3928  *
3929  * @param domain_sid The domain sid acquired from the remote server.
3930  * @param cli A cli_state connected to the server.
3931  * @param mem_ctx Talloc context, destroyed on completion of the function.
3932  * @param argc  Standard main() style argc.
3933  * @param argv  Standard main() style argv. Initial components are already
3934  *              stripped.
3935  *
3936  * @return Normal NTSTATUS return.
3937  **/
3938
3939 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
3940                                                 const DOM_SID *domain_sid,
3941                                                 const char *domain_name,
3942                                                 struct cli_state *cli,
3943                                                 struct rpc_pipe_client *pipe_hnd,
3944                                                 TALLOC_CTX *mem_ctx,
3945                                                 int argc,
3946                                                 const char **argv)
3947 {
3948         WERROR result;
3949         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3950         struct srvsvc_NetShareInfoCtr ctr_src;
3951         union srvsvc_NetShareInfo info;
3952         uint32 i;
3953         struct rpc_pipe_client *srvsvc_pipe = NULL;
3954         struct cli_state *cli_dst = NULL;
3955         uint32 level = 502; /* includes secdesc */
3956         uint32_t parm_error = 0;
3957
3958         result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3959                                 &ctr_src);
3960
3961         if (!W_ERROR_IS_OK(result))
3962                 goto done;
3963
3964         /* connect destination PI_SRVSVC */
3965         nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe, PI_SRVSVC);
3966         if (!NT_STATUS_IS_OK(nt_status))
3967                 return nt_status;
3968
3969
3970         for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3971
3972                 struct srvsvc_NetShareInfo502 info502 =
3973                         ctr_src.ctr.ctr502->array[i];
3974
3975                 /* reset error-code */
3976                 nt_status = NT_STATUS_UNSUCCESSFUL;
3977
3978                 if (!check_share_sanity(c, cli, info502.name, info502.type))
3979                         continue;
3980
3981                 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n", 
3982                         info502.name, info502.path, info502.comment);
3983
3984                 if (c->opt_verbose)
3985                         display_sec_desc(info502.sd_buf.sd);
3986
3987                 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3988                 info.info502 = &info502;
3989
3990                 /* finally modify the share on the dst server */
3991                 nt_status = rpccli_srvsvc_NetShareSetInfo(srvsvc_pipe, mem_ctx,
3992                                                           srvsvc_pipe->desthost,
3993                                                           info502.name,
3994                                                           level,
3995                                                           &info,
3996                                                           &parm_error,
3997                                                           &result);
3998                 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3999                         printf("cannot set share-acl: %s\n", dos_errstr(result));
4000                         goto done;
4001                 }
4002
4003         }
4004
4005         nt_status = NT_STATUS_OK;
4006
4007 done:
4008         if (cli_dst) {
4009                 cli_shutdown(cli_dst);
4010         }
4011
4012         return nt_status;
4013
4014 }
4015
4016 /**
4017  * Migrate share-acls from a RPC server to another.
4018  *
4019  * @param argc  Standard main() style argc.
4020  * @param argv  Standard main() style argv. Initial components are already
4021  *              stripped.
4022  *
4023  * @return A shell status integer (0 for success).
4024  **/
4025 static int rpc_share_migrate_security(struct net_context *c, int argc,
4026                                       const char **argv)
4027 {
4028         if (c->display_usage) {
4029                 d_printf("Usage:\n"
4030                          "net rpc share migrate security\n"
4031                          "    Migrate share-acls to local server\n");
4032                 return 0;
4033         }
4034
4035         if (!c->opt_host) {
4036                 d_printf("no server to migrate\n");
4037                 return -1;
4038         }
4039
4040         return run_rpc_command(c, NULL, PI_SRVSVC, 0,
4041                                rpc_share_migrate_security_internals,
4042                                argc, argv);
4043 }
4044
4045 /**
4046  * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
4047  * from one server to another.
4048  *
4049  * @param argc  Standard main() style argc.
4050  * @param argv  Standard main() style argv. Initial components are already
4051  *              stripped.
4052  *
4053  * @return A shell status integer (0 for success).
4054  *
4055  **/
4056 static int rpc_share_migrate_all(struct net_context *c, int argc,
4057                                  const char **argv)
4058 {
4059         int ret;
4060
4061         if (c->display_usage) {
4062                 d_printf("Usage:\n"
4063                          "net rpc share migrate all\n"
4064                          "    Migrates shares including all share settings\n");
4065                 return 0;
4066         }
4067
4068         if (!c->opt_host) {
4069                 d_printf("no server to migrate\n");
4070                 return -1;
4071         }
4072
4073         /* order is important. we don't want to be locked out by the share-acl
4074          * before copying files - gd */
4075
4076         ret = run_rpc_command(c, NULL, PI_SRVSVC, 0,
4077                               rpc_share_migrate_shares_internals, argc, argv);
4078         if (ret)
4079                 return ret;
4080
4081         ret = run_rpc_command(c, NULL, PI_SRVSVC, 0,
4082                               rpc_share_migrate_files_internals, argc, argv);
4083         if (ret)
4084                 return ret;
4085
4086         return run_rpc_command(c, NULL, PI_SRVSVC, 0,
4087                                rpc_share_migrate_security_internals, argc,
4088                                argv);
4089 }
4090
4091
4092 /**
4093  * 'net rpc share migrate' entrypoint.
4094  * @param argc  Standard main() style argc.
4095  * @param argv  Standard main() style argv. Initial components are already
4096  *              stripped.
4097  **/
4098 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
4099 {
4100
4101         struct functable func[] = {
4102                 {
4103                         "all",
4104                         rpc_share_migrate_all,
4105                         NET_TRANSPORT_RPC,
4106                         "Migrate shares from remote to local server",
4107                         "net rpc share migrate all\n"
4108                         "    Migrate shares from remote to local server"
4109                 },
4110                 {
4111                         "files",
4112                         rpc_share_migrate_files,
4113                         NET_TRANSPORT_RPC,
4114                         "Migrate files from remote to local server",
4115                         "net rpc share migrate files\n"
4116                         "    Migrate files from remote to local server"
4117                 },
4118                 {
4119                         "security",
4120                         rpc_share_migrate_security,
4121                         NET_TRANSPORT_RPC,
4122                         "Migrate share-ACLs from remote to local server",
4123                         "net rpc share migrate security\n"
4124                         "    Migrate share-ACLs from remote to local server"
4125                 },
4126                 {
4127                         "shares",
4128                         rpc_share_migrate_shares,
4129                         NET_TRANSPORT_RPC,
4130                         "Migrate shares from remote to local server",
4131                         "net rpc share migrate shares\n"
4132                         "    Migrate shares from remote to local server"
4133                 },
4134                 {NULL, NULL, 0, NULL, NULL}
4135         };
4136
4137         net_mode_share = NET_MODE_SHARE_MIGRATE;
4138
4139         return net_run_function(c, argc, argv, "net rpc share migrate", func);
4140 }
4141
4142 struct full_alias {
4143         DOM_SID sid;
4144         uint32 num_members;
4145         DOM_SID *members;
4146 };
4147
4148 static int num_server_aliases;
4149 static struct full_alias *server_aliases;
4150
4151 /*
4152  * Add an alias to the static list.
4153  */
4154 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
4155 {
4156         if (server_aliases == NULL)
4157                 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
4158
4159         server_aliases[num_server_aliases] = *alias;
4160         num_server_aliases += 1;
4161 }
4162
4163 /*
4164  * For a specific domain on the server, fetch all the aliases
4165  * and their members. Add all of them to the server_aliases.
4166  */
4167
4168 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4169                                         TALLOC_CTX *mem_ctx,
4170                                         POLICY_HND *connect_pol,
4171                                         const DOM_SID *domain_sid)
4172 {
4173         uint32 start_idx, max_entries, num_entries, i;
4174         struct samr_SamArray *groups = NULL;
4175         NTSTATUS result;
4176         POLICY_HND domain_pol;
4177
4178         /* Get domain policy handle */
4179
4180         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
4181                                         connect_pol,
4182                                         MAXIMUM_ALLOWED_ACCESS,
4183                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
4184                                         &domain_pol);
4185         if (!NT_STATUS_IS_OK(result))
4186                 return result;
4187
4188         start_idx = 0;
4189         max_entries = 250;
4190
4191         do {
4192                 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
4193                                                        &domain_pol,
4194                                                        &start_idx,
4195                                                        &groups,
4196                                                        max_entries,
4197                                                        &num_entries);
4198                 for (i = 0; i < num_entries; i++) {
4199
4200                         POLICY_HND alias_pol;
4201                         struct full_alias alias;
4202                         struct lsa_SidArray sid_array;
4203                         int j;
4204
4205                         result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
4206                                                        &domain_pol,
4207                                                        MAXIMUM_ALLOWED_ACCESS,
4208                                                        groups->entries[i].idx,
4209                                                        &alias_pol);
4210                         if (!NT_STATUS_IS_OK(result))
4211                                 goto done;
4212
4213                         result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
4214                                                                &alias_pol,
4215                                                                &sid_array);
4216                         if (!NT_STATUS_IS_OK(result))
4217                                 goto done;
4218
4219                         alias.num_members = sid_array.num_sids;
4220
4221                         result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
4222                         if (!NT_STATUS_IS_OK(result))
4223                                 goto done;
4224
4225                         alias.members = NULL;
4226
4227                         if (alias.num_members > 0) {
4228                                 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
4229
4230                                 for (j = 0; j < alias.num_members; j++)
4231                                         sid_copy(&alias.members[j],
4232                                                  sid_array.sids[j].sid);
4233                         }
4234
4235                         sid_copy(&alias.sid, domain_sid);
4236                         sid_append_rid(&alias.sid, groups->entries[i].idx);
4237
4238                         push_alias(mem_ctx, &alias);
4239                 }
4240         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4241
4242         result = NT_STATUS_OK;
4243
4244  done:
4245         rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
4246
4247         return result;
4248 }
4249
4250 /*
4251  * Dump server_aliases as names for debugging purposes.
4252  */
4253
4254 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4255                                 const DOM_SID *domain_sid,
4256                                 const char *domain_name,
4257                                 struct cli_state *cli,
4258                                 struct rpc_pipe_client *pipe_hnd,
4259                                 TALLOC_CTX *mem_ctx,
4260                                 int argc,
4261                                 const char **argv)
4262 {
4263         int i;
4264         NTSTATUS result;
4265         POLICY_HND lsa_pol;
4266
4267         result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4268                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
4269                                      &lsa_pol);
4270         if (!NT_STATUS_IS_OK(result))
4271                 return result;
4272
4273         for (i=0; i<num_server_aliases; i++) {
4274                 char **names;
4275                 char **domains;
4276                 enum lsa_SidType *types;
4277                 int j;
4278
4279                 struct full_alias *alias = &server_aliases[i];
4280
4281                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4282                                              &alias->sid,
4283                                              &domains, &names, &types);
4284                 if (!NT_STATUS_IS_OK(result))
4285                         continue;
4286
4287                 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4288
4289                 if (alias->num_members == 0) {
4290                         DEBUG(1, ("\n"));
4291                         continue;
4292                 }
4293
4294                 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4295                                              alias->num_members,
4296                                              alias->members,
4297                                              &domains, &names, &types);
4298
4299                 if (!NT_STATUS_IS_OK(result) &&
4300                     !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4301                         continue;
4302
4303                 for (j=0; j<alias->num_members; j++)
4304                         DEBUG(1, ("%s\\%s (%d); ",
4305                                   domains[j] ? domains[j] : "*unknown*", 
4306                                   names[j] ? names[j] : "*unknown*",types[j]));
4307                 DEBUG(1, ("\n"));
4308         }
4309
4310         rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
4311
4312         return NT_STATUS_OK;
4313 }
4314
4315 /*
4316  * Fetch a list of all server aliases and their members into
4317  * server_aliases.
4318  */
4319
4320 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4321                                         const DOM_SID *domain_sid,
4322                                         const char *domain_name,
4323                                         struct cli_state *cli,
4324                                         struct rpc_pipe_client *pipe_hnd,
4325                                         TALLOC_CTX *mem_ctx,
4326                                         int argc,
4327                                         const char **argv)
4328 {
4329         NTSTATUS result;
4330         POLICY_HND connect_pol;
4331
4332         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
4333                                       pipe_hnd->desthost,
4334                                       MAXIMUM_ALLOWED_ACCESS,
4335                                       &connect_pol);
4336
4337         if (!NT_STATUS_IS_OK(result))
4338                 goto done;
4339
4340         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4341                                           &global_sid_Builtin);
4342
4343         if (!NT_STATUS_IS_OK(result))
4344                 goto done;
4345
4346         result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4347                                           domain_sid);
4348
4349         rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
4350  done:
4351         return result;
4352 }
4353
4354 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
4355 {
4356         token->num_sids = 4;
4357
4358         if (!(token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4))) {
4359                 d_fprintf(stderr, "malloc failed\n");
4360                 token->num_sids = 0;
4361                 return;
4362         }
4363
4364         token->user_sids[0] = *user_sid;
4365         sid_copy(&token->user_sids[1], &global_sid_World);
4366         sid_copy(&token->user_sids[2], &global_sid_Network);
4367         sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
4368 }
4369
4370 static void free_user_token(NT_USER_TOKEN *token)
4371 {
4372         SAFE_FREE(token->user_sids);
4373 }
4374
4375 static bool is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
4376 {
4377         int i;
4378
4379         for (i=0; i<token->num_sids; i++) {
4380                 if (sid_compare(sid, &token->user_sids[i]) == 0)
4381                         return true;
4382         }
4383         return false;
4384 }
4385
4386 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
4387 {
4388         if (is_sid_in_token(token, sid))
4389                 return;
4390
4391         token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
4392         if (!token->user_sids) {
4393                 return;
4394         }
4395
4396         sid_copy(&token->user_sids[token->num_sids], sid);
4397
4398         token->num_sids += 1;
4399 }
4400
4401 struct user_token {
4402         fstring name;
4403         NT_USER_TOKEN token;
4404 };
4405
4406 static void dump_user_token(struct user_token *token)
4407 {
4408         int i;
4409
4410         d_printf("%s\n", token->name);
4411
4412         for (i=0; i<token->token.num_sids; i++) {
4413                 d_printf(" %s\n", sid_string_tos(&token->token.user_sids[i]));
4414         }
4415 }
4416
4417 static bool is_alias_member(DOM_SID *sid, struct full_alias *alias)
4418 {
4419         int i;
4420
4421         for (i=0; i<alias->num_members; i++) {
4422                 if (sid_compare(sid, &alias->members[i]) == 0)
4423                         return true;
4424         }
4425
4426         return false;
4427 }
4428
4429 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
4430 {
4431         int i;
4432
4433         for (i=0; i<num_server_aliases; i++) {
4434                 if (is_alias_member(&sid, &server_aliases[i]))
4435                         add_sid_to_token(token, &server_aliases[i].sid);
4436         }
4437 }
4438
4439 /*
4440  * We got a user token with all the SIDs we can know about without asking the
4441  * server directly. These are the user and domain group sids. All of these can
4442  * be members of aliases. So scan the list of aliases for each of the SIDs and
4443  * add them to the token.
4444  */
4445
4446 static void collect_alias_memberships(NT_USER_TOKEN *token)
4447 {
4448         int num_global_sids = token->num_sids;
4449         int i;
4450
4451         for (i=0; i<num_global_sids; i++) {
4452                 collect_sid_memberships(token, token->user_sids[i]);
4453         }
4454 }
4455
4456 static bool get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
4457 {
4458         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4459         enum wbcSidType type;
4460         fstring full_name;
4461         struct wbcDomainSid wsid;
4462         char *sid_str = NULL;
4463         DOM_SID user_sid;
4464         uint32_t num_groups;
4465         gid_t *groups = NULL;
4466         uint32_t i;
4467
4468         fstr_sprintf(full_name, "%s%c%s",
4469                      domain, *lp_winbind_separator(), user);
4470
4471         /* First let's find out the user sid */
4472
4473         wbc_status = wbcLookupName(domain, user, &wsid, &type);
4474
4475         if (!WBC_ERROR_IS_OK(wbc_status)) {
4476                 DEBUG(1, ("winbind could not find %s: %s\n",
4477                           full_name, wbcErrorString(wbc_status)));
4478                 return false;
4479         }
4480
4481         wbc_status = wbcSidToString(&wsid, &sid_str);
4482         if (!WBC_ERROR_IS_OK(wbc_status)) {
4483                 return false;
4484         }
4485
4486         if (type != SID_NAME_USER) {
4487                 wbcFreeMemory(sid_str);
4488                 DEBUG(1, ("%s is not a user\n", full_name));
4489                 return false;
4490         }
4491
4492         string_to_sid(&user_sid, sid_str);
4493         wbcFreeMemory(sid_str);
4494         sid_str = NULL;
4495
4496         init_user_token(token, &user_sid);
4497
4498         /* And now the groups winbind knows about */
4499
4500         wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4501         if (!WBC_ERROR_IS_OK(wbc_status)) {
4502                 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4503                         full_name, wbcErrorString(wbc_status)));
4504                 return false;
4505         }
4506
4507         for (i = 0; i < num_groups; i++) {
4508                 gid_t gid = groups[i];
4509                 DOM_SID sid;
4510
4511                 wbc_status = wbcGidToSid(gid, &wsid);
4512                 if (!WBC_ERROR_IS_OK(wbc_status)) {
4513                         DEBUG(1, ("winbind could not find SID of gid %d: %s\n",
4514                                   gid, wbcErrorString(wbc_status)));
4515                         wbcFreeMemory(groups);
4516                         return false;
4517                 }
4518
4519                 wbc_status = wbcSidToString(&wsid, &sid_str);
4520                 if (!WBC_ERROR_IS_OK(wbc_status)) {
4521                         wbcFreeMemory(groups);
4522                         return false;
4523                 }
4524
4525                 DEBUG(3, (" %s\n", sid_str));
4526
4527                 string_to_sid(&sid, sid_str);
4528                 wbcFreeMemory(sid_str);
4529                 sid_str = NULL;
4530
4531                 add_sid_to_token(token, &sid);
4532         }
4533         wbcFreeMemory(groups);
4534
4535         return true;
4536 }
4537
4538 /**
4539  * Get a list of all user tokens we want to look at
4540  **/
4541
4542 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4543                             struct user_token **user_tokens)
4544 {
4545         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4546         uint32_t i, num_users;
4547         const char **users;
4548         struct user_token *result;
4549         TALLOC_CTX *frame = NULL;
4550
4551         if (lp_winbind_use_default_domain() &&
4552             (c->opt_target_workgroup == NULL)) {
4553                 d_fprintf(stderr, "winbind use default domain = yes set, "
4554                          "please specify a workgroup\n");
4555                 return false;
4556         }
4557
4558         /* Send request to winbind daemon */
4559
4560         wbc_status = wbcListUsers(NULL, &num_users, &users);
4561         if (!WBC_ERROR_IS_OK(wbc_status)) {
4562                 DEBUG(1, ("winbind could not list users: %s\n",
4563                           wbcErrorString(wbc_status)));
4564                 return false;
4565         }
4566
4567         result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4568
4569         if (result == NULL) {
4570                 DEBUG(1, ("Could not malloc sid array\n"));
4571                 wbcFreeMemory(users);
4572                 return false;
4573         }
4574
4575         frame = talloc_stackframe();
4576         for (i=0; i < num_users; i++) {
4577                 fstring domain, user;
4578                 char *p;
4579
4580                 fstrcpy(result[i].name, users[i]);
4581
4582                 p = strchr(users[i], *lp_winbind_separator());
4583
4584                 DEBUG(3, ("%s\n", users[i]));
4585
4586                 if (p == NULL) {
4587                         fstrcpy(domain, c->opt_target_workgroup);
4588                         fstrcpy(user, users[i]);
4589                 } else {
4590                         *p++ = '\0';
4591                         fstrcpy(domain, users[i]);
4592                         strupper_m(domain);
4593                         fstrcpy(user, p);
4594                 }
4595
4596                 get_user_sids(domain, user, &(result[i].token));
4597                 i+=1;
4598         }
4599         TALLOC_FREE(frame);
4600         wbcFreeMemory(users);
4601
4602         *num_tokens = num_users;
4603         *user_tokens = result;
4604
4605         return true;
4606 }
4607
4608 static bool get_user_tokens_from_file(FILE *f,
4609                                       int *num_tokens,
4610                                       struct user_token **tokens)
4611 {
4612         struct user_token *token = NULL;
4613
4614         while (!feof(f)) {
4615                 fstring line;
4616
4617                 if (fgets(line, sizeof(line)-1, f) == NULL) {
4618                         return true;
4619                 }
4620
4621                 if (line[strlen(line)-1] == '\n')
4622                         line[strlen(line)-1] = '\0';
4623
4624                 if (line[0] == ' ') {
4625                         /* We have a SID */
4626
4627                         DOM_SID sid;
4628                         string_to_sid(&sid, &line[1]);
4629
4630                         if (token == NULL) {
4631                                 DEBUG(0, ("File does not begin with username"));
4632                                 return false;
4633                         }
4634
4635                         add_sid_to_token(&token->token, &sid);
4636                         continue;
4637                 }
4638
4639                 /* And a new user... */
4640
4641                 *num_tokens += 1;
4642                 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4643                 if (*tokens == NULL) {
4644                         DEBUG(0, ("Could not realloc tokens\n"));
4645                         return false;
4646                 }
4647
4648                 token = &((*tokens)[*num_tokens-1]);
4649
4650                 fstrcpy(token->name, line);
4651                 token->token.num_sids = 0;
4652                 token->token.user_sids = NULL;
4653                 continue;
4654         }
4655         
4656         return false;
4657 }
4658
4659
4660 /*
4661  * Show the list of all users that have access to a share
4662  */
4663
4664 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4665                         TALLOC_CTX *mem_ctx,
4666                         const char *netname,
4667                         int num_tokens,
4668                         struct user_token *tokens)
4669 {
4670         int fnum;
4671         SEC_DESC *share_sd = NULL;
4672         SEC_DESC *root_sd = NULL;
4673         struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4674         int i;
4675         union srvsvc_NetShareInfo info;
4676         WERROR result;
4677         NTSTATUS status;
4678         uint16 cnum;
4679
4680         status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4681                                                pipe_hnd->desthost,
4682                                                netname,
4683                                                502,
4684                                                &info,
4685                                                &result);
4686
4687         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4688                 DEBUG(1, ("Coult not query secdesc for share %s\n",
4689                           netname));
4690                 return;
4691         }
4692
4693         share_sd = info.info502->sd_buf.sd;
4694         if (share_sd == NULL) {
4695                 DEBUG(1, ("Got no secdesc for share %s\n",
4696                           netname));
4697         }
4698
4699         cnum = cli->cnum;
4700
4701         if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
4702                 return;
4703         }
4704
4705         fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
4706
4707         if (fnum != -1) {
4708                 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4709         }
4710
4711         for (i=0; i<num_tokens; i++) {
4712                 uint32 acc_granted;
4713
4714                 if (share_sd != NULL) {
4715                         if (!se_access_check(share_sd, &tokens[i].token,
4716                                              1, &acc_granted, &status)) {
4717                                 DEBUG(1, ("Could not check share_sd for "
4718                                           "user %s\n",
4719                                           tokens[i].name));
4720                                 continue;
4721                         }
4722
4723                         if (!NT_STATUS_IS_OK(status))
4724                                 continue;
4725                 }
4726
4727                 if (root_sd == NULL) {
4728                         d_printf(" %s\n", tokens[i].name);
4729                         continue;
4730                 }
4731
4732                 if (!se_access_check(root_sd, &tokens[i].token,
4733                                      1, &acc_granted, &status)) {
4734                         DEBUG(1, ("Could not check root_sd for user %s\n",
4735                                   tokens[i].name));
4736                         continue;
4737                 }
4738
4739                 if (!NT_STATUS_IS_OK(status))
4740                         continue;
4741
4742                 d_printf(" %s\n", tokens[i].name);
4743         }
4744
4745         if (fnum != -1)
4746                 cli_close(cli, fnum);
4747         cli_tdis(cli);
4748         cli->cnum = cnum;
4749         
4750         return;
4751 }
4752
4753 struct share_list {
4754         int num_shares;
4755         char **shares;
4756 };
4757
4758 static void collect_share(const char *name, uint32 m,
4759                           const char *comment, void *state)
4760 {
4761         struct share_list *share_list = (struct share_list *)state;
4762
4763         if (m != STYPE_DISKTREE)
4764                 return;
4765
4766         share_list->num_shares += 1;
4767         share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4768         if (!share_list->shares) {
4769                 share_list->num_shares = 0;
4770                 return;
4771         }
4772         share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4773 }
4774
4775 /**
4776  * List shares on a remote RPC server, including the security descriptors.
4777  *
4778  * All parameters are provided by the run_rpc_command function, except for
4779  * argc, argv which are passed through.
4780  *
4781  * @param domain_sid The domain sid acquired from the remote server.
4782  * @param cli A cli_state connected to the server.
4783  * @param mem_ctx Talloc context, destroyed on completion of the function.
4784  * @param argc  Standard main() style argc.
4785  * @param argv  Standard main() style argv. Initial components are already
4786  *              stripped.
4787  *
4788  * @return Normal NTSTATUS return.
4789  **/
4790
4791 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
4792                                                 const DOM_SID *domain_sid,
4793                                                 const char *domain_name,
4794                                                 struct cli_state *cli,
4795                                                 struct rpc_pipe_client *pipe_hnd,
4796                                                 TALLOC_CTX *mem_ctx,
4797                                                 int argc,
4798                                                 const char **argv)
4799 {
4800         int ret;
4801         bool r;
4802         ENUM_HND hnd;
4803         uint32 i;
4804         FILE *f;
4805
4806         struct user_token *tokens = NULL;
4807         int num_tokens = 0;
4808
4809         struct share_list share_list;
4810
4811         if (argc == 0) {
4812                 f = stdin;
4813         } else {
4814                 f = fopen(argv[0], "r");
4815         }
4816
4817         if (f == NULL) {
4818                 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4819                 return NT_STATUS_UNSUCCESSFUL;
4820         }
4821
4822         r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4823
4824         if (f != stdin)
4825                 fclose(f);
4826
4827         if (!r) {
4828                 DEBUG(0, ("Could not read users from file\n"));
4829                 return NT_STATUS_UNSUCCESSFUL;
4830         }
4831
4832         for (i=0; i<num_tokens; i++)
4833                 collect_alias_memberships(&tokens[i].token);
4834
4835         init_enum_hnd(&hnd, 0);
4836
4837         share_list.num_shares = 0;
4838         share_list.shares = NULL;
4839
4840         ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4841
4842         if (ret == -1) {
4843                 DEBUG(0, ("Error returning browse list: %s\n",
4844                           cli_errstr(cli)));
4845                 goto done;
4846         }
4847
4848         for (i = 0; i < share_list.num_shares; i++) {
4849                 char *netname = share_list.shares[i];
4850
4851                 if (netname[strlen(netname)-1] == '$')
4852                         continue;
4853
4854                 d_printf("%s\n", netname);
4855
4856                 show_userlist(pipe_hnd, mem_ctx, netname,
4857                               num_tokens, tokens);
4858         }
4859  done:
4860         for (i=0; i<num_tokens; i++) {
4861                 free_user_token(&tokens[i].token);
4862         }
4863         SAFE_FREE(tokens);
4864         SAFE_FREE(share_list.shares);
4865
4866         return NT_STATUS_OK;
4867 }
4868
4869 static int rpc_share_allowedusers(struct net_context *c, int argc,
4870                                   const char **argv)
4871 {
4872         int result;
4873
4874         if (c->display_usage) {
4875                 d_printf("Usage:\n"
4876                          "net rpc share allowedusers\n"
4877                          "    List allowed users\n");
4878                 return 0;
4879         }
4880
4881         result = run_rpc_command(c, NULL, PI_SAMR, 0,
4882                                  rpc_aliaslist_internals,
4883                                  argc, argv);
4884         if (result != 0)
4885                 return result;
4886
4887         result = run_rpc_command(c, NULL, PI_LSARPC, 0,
4888                                  rpc_aliaslist_dump,
4889                                  argc, argv);
4890         if (result != 0)
4891                 return result;
4892
4893         return run_rpc_command(c, NULL, PI_SRVSVC, 0,
4894                                rpc_share_allowedusers_internals,
4895                                argc, argv);
4896 }
4897
4898 int net_usersidlist(struct net_context *c, int argc, const char **argv)
4899 {
4900         int num_tokens = 0;
4901         struct user_token *tokens = NULL;
4902         int i;
4903
4904         if (argc != 0) {
4905                 net_usersidlist_usage(c, argc, argv);
4906                 return 0;
4907         }
4908
4909         if (!get_user_tokens(c, &num_tokens, &tokens)) {
4910                 DEBUG(0, ("Could not get the user/sid list\n"));
4911                 return 0;
4912         }
4913
4914         for (i=0; i<num_tokens; i++) {
4915                 dump_user_token(&tokens[i]);
4916                 free_user_token(&tokens[i].token);
4917         }
4918
4919         SAFE_FREE(tokens);
4920         return 1;
4921 }
4922
4923 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
4924 {
4925         d_printf("net usersidlist\n"
4926                  "\tprints out a list of all users the running winbind knows\n"
4927                  "\tabout, together with all their SIDs. This is used as\n"
4928                  "\tinput to the 'net rpc share allowedusers' command.\n\n");
4929
4930         net_common_flags_usage(c, argc, argv);
4931         return -1;
4932 }
4933
4934 /**
4935  * 'net rpc share' entrypoint.
4936  * @param argc  Standard main() style argc.
4937  * @param argv  Standard main() style argv. Initial components are already
4938  *              stripped.
4939  **/
4940
4941 int net_rpc_share(struct net_context *c, int argc, const char **argv)
4942 {
4943         struct functable func[] = {
4944                 {
4945                         "add",
4946                         rpc_share_add,
4947                         NET_TRANSPORT_RPC,
4948                         "Add share",
4949                         "net rpc share add\n"
4950                         "    Add share"
4951                 },
4952                 {
4953                         "delete",
4954                         rpc_share_delete,
4955                         NET_TRANSPORT_RPC,
4956                         "Remove share",
4957                         "net rpc share delete\n"
4958                         "    Remove share"
4959                 },
4960                 {
4961                         "allowedusers",
4962                         rpc_share_allowedusers,
4963                         NET_TRANSPORT_RPC,
4964                         "Modify allowed users",
4965                         "net rpc share allowedusers\n"
4966                         "    Modify allowed users"
4967                 },
4968                 {
4969                         "migrate",
4970                         rpc_share_migrate,
4971                         NET_TRANSPORT_RPC,
4972                         "Migrate share to local server",
4973                         "net rpc share migrate\n"
4974                         "    Migrate share to local server"
4975                 },
4976                 {
4977                         "list",
4978                         rpc_share_list,
4979                         NET_TRANSPORT_RPC,
4980                         "List shares",
4981                         "net rpc share list\n"
4982                         "    List shares"
4983                 },
4984                 {NULL, NULL, 0, NULL, NULL}
4985         };
4986
4987
4988         if (argc == 0) {
4989                 if (c->display_usage) {
4990                         d_printf("Usage:\n"
4991                                  "net rpc share\n"
4992                                  "    List shares\n"
4993                                  "    Alias for net rpc share list\n");
4994                         net_display_usage_from_functable(func);
4995                         return 0;
4996                 }
4997
4998                 return run_rpc_command(c, NULL, PI_SRVSVC, 0,
4999                                        rpc_share_list_internals,
5000                                        argc, argv);
5001         }
5002
5003         return net_run_function(c, argc, argv, "net rpc share", func);
5004 }
5005
5006 static NTSTATUS rpc_sh_share_list(struct net_context *c,
5007                                   TALLOC_CTX *mem_ctx,
5008                                   struct rpc_sh_ctx *ctx,
5009                                   struct rpc_pipe_client *pipe_hnd,
5010                                   int argc, const char **argv)
5011 {
5012         return rpc_share_list_internals(c, ctx->domain_sid, ctx->domain_name,
5013                                         ctx->cli, pipe_hnd, mem_ctx,
5014                                         argc, argv);
5015 }
5016
5017 static NTSTATUS rpc_sh_share_add(struct net_context *c,
5018                                  TALLOC_CTX *mem_ctx,
5019                                  struct rpc_sh_ctx *ctx,
5020                                  struct rpc_pipe_client *pipe_hnd,
5021                                  int argc, const char **argv)
5022 {
5023         WERROR result;
5024         NTSTATUS status;
5025         uint32_t parm_err = 0;
5026         union srvsvc_NetShareInfo info;
5027         struct srvsvc_NetShareInfo2 info2;
5028
5029         if ((argc < 2) || (argc > 3)) {
5030                 d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
5031                           ctx->whoami);
5032                 return NT_STATUS_INVALID_PARAMETER;
5033         }
5034
5035         info2.name              = argv[0];
5036         info2.type              = STYPE_DISKTREE;
5037         info2.comment           = (argc == 3) ? argv[2] : "";
5038         info2.permissions       = 0;
5039         info2.max_users         = 0;
5040         info2.current_users     = 0;
5041         info2.path              = argv[1];
5042         info2.password          = NULL;
5043
5044         info.info2 = &info2;
5045
5046         status = rpccli_srvsvc_NetShareAdd(pipe_hnd, mem_ctx,
5047                                            pipe_hnd->desthost,
5048                                            2,
5049                                            &info,
5050                                            &parm_err,
5051                                            &result);
5052
5053         return status;
5054 }
5055
5056 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
5057                                     TALLOC_CTX *mem_ctx,
5058                                     struct rpc_sh_ctx *ctx,
5059                                     struct rpc_pipe_client *pipe_hnd,
5060                                     int argc, const char **argv)
5061 {
5062         WERROR result;
5063         NTSTATUS status;
5064
5065         if (argc != 1) {
5066                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
5067                 return NT_STATUS_INVALID_PARAMETER;
5068         }
5069
5070         status = rpccli_srvsvc_NetShareDel(pipe_hnd, mem_ctx,
5071                                            pipe_hnd->desthost,
5072                                            argv[0],
5073                                            0,
5074                                            &result);
5075
5076         return status;
5077 }
5078
5079 static NTSTATUS rpc_sh_share_info(struct net_context *c,
5080                                   TALLOC_CTX *mem_ctx,
5081                                   struct rpc_sh_ctx *ctx,
5082                                   struct rpc_pipe_client *pipe_hnd,
5083                                   int argc, const char **argv)
5084 {
5085         union srvsvc_NetShareInfo info;
5086         WERROR result;
5087         NTSTATUS status;
5088
5089         if (argc != 1) {
5090                 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
5091                 return NT_STATUS_INVALID_PARAMETER;
5092         }
5093
5094         status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
5095                                                pipe_hnd->desthost,
5096                                                argv[0],
5097                                                2,
5098                                                &info,
5099                                                &result);
5100         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
5101                 goto done;
5102         }
5103
5104         d_printf("Name:     %s\n", info.info2->name);
5105         d_printf("Comment:  %s\n", info.info2->comment);
5106         d_printf("Path:     %s\n", info.info2->path);
5107         d_printf("Password: %s\n", info.info2->password);
5108
5109  done:
5110         return werror_to_ntstatus(result);
5111 }
5112
5113 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
5114                                       struct rpc_sh_ctx *ctx)
5115 {
5116         static struct rpc_sh_cmd cmds[] = {
5117
5118         { "list", NULL, PI_SRVSVC, rpc_sh_share_list,
5119           "List available shares" },
5120
5121         { "add", NULL, PI_SRVSVC, rpc_sh_share_add,
5122           "Add a share" },
5123
5124         { "delete", NULL, PI_SRVSVC, rpc_sh_share_delete,
5125           "Delete a share" },
5126
5127         { "info", NULL, PI_SRVSVC, rpc_sh_share_info,
5128           "Get information about a share" },
5129
5130         { NULL, NULL, 0, NULL, NULL }
5131         };
5132
5133         return cmds;
5134 }
5135
5136 /****************************************************************************/
5137
5138 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
5139 {
5140         return net_file_usage(c, argc, argv);
5141 }
5142
5143 /**
5144  * Close a file on a remote RPC server.
5145  *
5146  * All parameters are provided by the run_rpc_command function, except for
5147  * argc, argv which are passed through.
5148  *
5149  * @param c     A net_context structure.
5150  * @param domain_sid The domain sid acquired from the remote server.
5151  * @param cli A cli_state connected to the server.
5152  * @param mem_ctx Talloc context, destroyed on completion of the function.
5153  * @param argc  Standard main() style argc.
5154  * @param argv  Standard main() style argv. Initial components are already
5155  *              stripped.
5156  *
5157  * @return Normal NTSTATUS return.
5158  **/
5159 static NTSTATUS rpc_file_close_internals(struct net_context *c,
5160                                         const DOM_SID *domain_sid,
5161                                         const char *domain_name,
5162                                         struct cli_state *cli,
5163                                         struct rpc_pipe_client *pipe_hnd,
5164                                         TALLOC_CTX *mem_ctx,
5165                                         int argc,
5166                                         const char **argv)
5167 {
5168         return rpccli_srvsvc_NetFileClose(pipe_hnd, mem_ctx,
5169                                             pipe_hnd->desthost,
5170                                             atoi(argv[0]), NULL);
5171 }
5172
5173 /**
5174  * Close a file on a remote RPC server.
5175  *
5176  * @param argc  Standard main() style argc.
5177  * @param argv  Standard main() style argv. Initial components are already
5178  *              stripped.
5179  *
5180  * @return A shell status integer (0 for success).
5181  **/
5182 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5183 {
5184         if (argc < 1 || c->display_usage) {
5185                 return rpc_file_usage(c, argc, argv);
5186         }
5187
5188         return run_rpc_command(c, NULL, PI_SRVSVC, 0,
5189                                rpc_file_close_internals,
5190                                argc, argv);
5191 }
5192
5193 /**
5194  * Formatted print of open file info
5195  *
5196  * @param r  struct srvsvc_NetFileInfo3 contents
5197  **/
5198
5199 static void display_file_info_3(struct srvsvc_NetFileInfo3 *r)
5200 {
5201         d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5202                  r->fid, r->user, r->permissions, r->num_locks, r->path);
5203 }
5204
5205 /**
5206  * List open files on a remote RPC server.
5207  *
5208  * All parameters are provided by the run_rpc_command function, except for
5209  * argc, argv which are passed through.
5210  *
5211  * @param c     A net_context structure.
5212  * @param domain_sid The domain sid acquired from the remote server.
5213  * @param cli A cli_state connected to the server.
5214  * @param mem_ctx Talloc context, destroyed on completion of the function.
5215  * @param argc  Standard main() style argc.
5216  * @param argv  Standard main() style argv. Initial components are already
5217  *              stripped.
5218  *
5219  * @return Normal NTSTATUS return.
5220  **/
5221
5222 static NTSTATUS rpc_file_list_internals(struct net_context *c,
5223                                         const DOM_SID *domain_sid,
5224                                         const char *domain_name,
5225                                         struct cli_state *cli,
5226                                         struct rpc_pipe_client *pipe_hnd,
5227                                         TALLOC_CTX *mem_ctx,
5228                                         int argc,
5229                                         const char **argv)
5230 {
5231         struct srvsvc_NetFileInfoCtr info_ctr;
5232         struct srvsvc_NetFileCtr3 ctr3;
5233         WERROR result;
5234         NTSTATUS status;
5235         uint32 preferred_len = 0xffffffff, i;
5236         const char *username=NULL;
5237         uint32_t total_entries = 0;
5238         uint32_t resume_handle = 0;
5239
5240         /* if argc > 0, must be user command */
5241         if (argc > 0)
5242                 username = smb_xstrdup(argv[0]);
5243
5244         ZERO_STRUCT(info_ctr);
5245         ZERO_STRUCT(ctr3);
5246
5247         info_ctr.level = 3;
5248         info_ctr.ctr.ctr3 = &ctr3;
5249
5250         status = rpccli_srvsvc_NetFileEnum(pipe_hnd, mem_ctx,
5251                                            pipe_hnd->desthost,
5252                                            NULL,
5253                                            username,
5254                                            &info_ctr,
5255                                            preferred_len,
5256                                            &total_entries,
5257                                            &resume_handle,
5258                                            &result);
5259
5260         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
5261                 goto done;
5262
5263         /* Display results */
5264
5265         d_printf(
5266                  "\nEnumerating open files on remote server:\n\n"
5267                  "\nFileId  Opened by            Perms  Locks  Path"
5268                  "\n------  ---------            -----  -----  ---- \n");
5269         for (i = 0; i < total_entries; i++)
5270                 display_file_info_3(&info_ctr.ctr.ctr3->array[i]);
5271  done:
5272         return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
5273 }
5274
5275 /**
5276  * List files for a user on a remote RPC server.
5277  *
5278  * @param argc  Standard main() style argc.
5279  * @param argv  Standard main() style argv. Initial components are already
5280  *              stripped.
5281  *
5282  * @return A shell status integer (0 for success)..
5283  **/
5284
5285 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5286 {
5287         if (argc < 1 || c->display_usage) {
5288                 return rpc_file_usage(c, argc, argv);
5289         }
5290
5291         return run_rpc_command(c, NULL, PI_SRVSVC, 0,
5292                                rpc_file_list_internals,
5293                                argc, argv);
5294 }
5295
5296 /**
5297  * 'net rpc file' entrypoint.
5298  * @param argc  Standard main() style argc.
5299  * @param argv  Standard main() style argv. Initial components are already
5300  *              stripped.
5301  **/
5302
5303 int net_rpc_file(struct net_context *c, int argc, const char **argv)
5304 {
5305         struct functable func[] = {
5306                 {
5307                         "close",
5308                         rpc_file_close,
5309                         NET_TRANSPORT_RPC,
5310                         "Close opened file",
5311                         "net rpc file close\n"
5312                         "    Close opened file"
5313                 },
5314                 {
5315                         "user",
5316                         rpc_file_user,
5317                         NET_TRANSPORT_RPC,
5318                         "List files opened by user",
5319                         "net rpc file user\n"
5320                         "    List files opened by user"
5321                 },
5322 #if 0
5323                 {
5324                         "info",
5325                         rpc_file_info,
5326                         NET_TRANSPORT_RPC,
5327                         "Display information about opened file",
5328                         "net rpc file info\n"
5329                         "    Display information about opened file"
5330                 },
5331 #endif
5332                 {NULL, NULL, 0, NULL, NULL}
5333         };
5334
5335         if (argc == 0) {
5336                 if (c->display_usage) {
5337                         d_printf("Usage:\n");
5338                         d_printf("net rpc file\n"
5339                                  "    List opened files\n");
5340                         net_display_usage_from_functable(func);
5341                         return 0;
5342                 }
5343
5344                 return run_rpc_command(c, NULL, PI_SRVSVC, 0,
5345                                        rpc_file_list_internals,
5346                                        argc, argv);
5347         }
5348
5349         return net_run_function(c, argc, argv, "net rpc file", func);
5350 }
5351
5352 /**
5353  * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5354  *
5355  * All parameters are provided by the run_rpc_command function, except for
5356  * argc, argv which are passed through.
5357  *
5358  * @param c     A net_context structure.
5359  * @param domain_sid The domain sid acquired from the remote server.
5360  * @param cli A cli_state connected to the server.
5361  * @param mem_ctx Talloc context, destroyed on completion of the function.
5362  * @param argc  Standard main() style argc.
5363  * @param argv  Standard main() style argv. Initial components are already
5364  *              stripped.
5365  *
5366  * @return Normal NTSTATUS return.
5367  **/
5368
5369 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5370                                         const DOM_SID *domain_sid,
5371                                         const char *domain_name,
5372                                         struct cli_state *cli,
5373                                         struct rpc_pipe_client *pipe_hnd,
5374                                         TALLOC_CTX *mem_ctx,
5375                                         int argc,
5376                                         const char **argv)
5377 {
5378         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5379
5380         result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
5381
5382         if (NT_STATUS_IS_OK(result)) {
5383                 d_printf("\nShutdown successfully aborted\n");
5384                 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5385         } else
5386                 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5387
5388         return result;
5389 }
5390
5391 /**
5392  * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5393  *
5394  * All parameters are provided by the run_rpc_command function, except for
5395  * argc, argv which are passed through.
5396  *
5397  * @param c     A net_context structure.
5398  * @param domain_sid The domain sid acquired from the remote server.
5399  * @param cli A cli_state connected to the server.
5400  * @param mem_ctx Talloc context, destroyed on completion of the function.
5401  * @param argc  Standard main() style argc.
5402  * @param argv  Standard main() style argv. Initial components are already
5403  *              stripped.
5404  *
5405  * @return Normal NTSTATUS return.
5406  **/
5407
5408 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5409                                                 const DOM_SID *domain_sid,
5410                                                 const char *domain_name,
5411                                                 struct cli_state *cli,
5412                                                 struct rpc_pipe_client *pipe_hnd,
5413                                                 TALLOC_CTX *mem_ctx,
5414                                                 int argc,
5415                                                 const char **argv)
5416 {
5417         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5418
5419         result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
5420
5421         if (NT_STATUS_IS_OK(result)) {
5422                 d_printf("\nShutdown successfully aborted\n");
5423                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5424         } else
5425                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5426
5427         return result;
5428 }
5429
5430 /**
5431  * ABORT the shutdown of a remote RPC server.
5432  *
5433  * @param argc  Standard main() style argc.
5434  * @param argv  Standard main() style argv. Initial components are already
5435  *              stripped.
5436  *
5437  * @return A shell status integer (0 for success).
5438  **/
5439
5440 static int rpc_shutdown_abort(struct net_context *c, int argc,
5441                               const char **argv)
5442 {
5443         int rc = -1;
5444
5445         if (c->display_usage) {
5446                 d_printf("Usage:\n"
5447                          "net rpc abortshutdown\n"
5448                          "    Abort a scheduled shutdown\n");
5449                 return 0;
5450         }
5451
5452         rc = run_rpc_command(c, NULL, PI_INITSHUTDOWN, 0,
5453                              rpc_shutdown_abort_internals, argc, argv);
5454
5455         if (rc == 0)
5456                 return rc;
5457
5458         DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5459
5460         return run_rpc_command(c, NULL, PI_WINREG, 0,
5461                                rpc_reg_shutdown_abort_internals,
5462                                argc, argv);
5463 }
5464
5465 /**
5466  * Shut down a remote RPC Server via initshutdown pipe.
5467  *
5468  * All parameters are provided by the run_rpc_command function, except for
5469  * argc, argv which are passed through.
5470  *
5471  * @param c     A net_context structure.
5472  * @param domain_sid The domain sid acquired from the remote server.
5473  * @param cli A cli_state connected to the server.
5474  * @param mem_ctx Talloc context, destroyed on completion of the function.
5475  * @param argc  Standard main() style argc.
5476  * @param argv  Standard main() style argv. Initial components are already
5477  *              stripped.
5478  *
5479  * @return Normal NTSTATUS return.
5480  **/
5481
5482 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5483                                      const DOM_SID *domain_sid,
5484                                      const char *domain_name,
5485                                      struct cli_state *cli,
5486                                      struct rpc_pipe_client *pipe_hnd,
5487                                      TALLOC_CTX *mem_ctx,
5488                                      int argc,
5489                                      const char **argv)
5490 {
5491         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5492         const char *msg = "This machine will be shutdown shortly";
5493         uint32 timeout = 20;
5494         struct initshutdown_String msg_string;
5495         struct initshutdown_String_sub s;
5496
5497         if (c->opt_comment) {
5498                 msg = c->opt_comment;
5499         }
5500         if (c->opt_timeout) {
5501                 timeout = c->opt_timeout;
5502         }
5503
5504         s.name = msg;
5505         msg_string.name = &s;
5506
5507         /* create an entry */
5508         result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5509                         &msg_string, timeout, c->opt_force, c->opt_reboot,
5510                         NULL);
5511
5512         if (NT_STATUS_IS_OK(result)) {
5513                 d_printf("\nShutdown of remote machine succeeded\n");
5514                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5515         } else {
5516                 DEBUG(1,("Shutdown of remote machine failed!\n"));
5517         }
5518         return result;
5519 }
5520
5521 /**
5522  * Shut down a remote RPC Server via winreg pipe.
5523  *
5524  * All parameters are provided by the run_rpc_command function, except for
5525  * argc, argv which are passed through.
5526  *
5527  * @param c     A net_context structure.
5528  * @param domain_sid The domain sid acquired from the remote server.
5529  * @param cli A cli_state connected to the server.
5530  * @param mem_ctx Talloc context, destroyed on completion of the function.
5531  * @param argc  Standard main() style argc.
5532  * @param argv  Standard main() style argv. Initial components are already
5533  *              stripped.
5534  *
5535  * @return Normal NTSTATUS return.
5536  **/
5537
5538 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5539                                     const DOM_SID *domain_sid,
5540                                     const char *domain_name,
5541                                     struct cli_state *cli,
5542                                     struct rpc_pipe_client *pipe_hnd,
5543                                     TALLOC_CTX *mem_ctx,
5544                                     int argc,
5545                                     const char **argv)
5546 {
5547         const char *msg = "This machine will be shutdown shortly";
5548         uint32 timeout = 20;
5549         struct initshutdown_String msg_string;
5550         struct initshutdown_String_sub s;
5551         NTSTATUS result;
5552         WERROR werr;
5553
5554         if (c->opt_comment) {
5555                 msg = c->opt_comment;
5556         }
5557         s.name = msg;
5558         msg_string.name = &s;
5559
5560         if (c->opt_timeout) {
5561                 timeout = c->opt_timeout;
5562         }
5563
5564         /* create an entry */
5565         result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5566                         &msg_string, timeout, c->opt_force, c->opt_reboot,
5567                         &werr);
5568
5569         if (NT_STATUS_IS_OK(result)) {
5570                 d_printf("\nShutdown of remote machine succeeded\n");
5571         } else {
5572                 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5573                 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5574                         d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5575                 else
5576                         d_fprintf(stderr, "\nresult was: %s\n", dos_errstr(werr));
5577         }
5578
5579         return result;
5580 }
5581
5582 /**
5583  * Shut down a remote RPC server.
5584  *
5585  * @param argc  Standard main() style argc.
5586  * @param argv  Standard main() style argv. Initial components are already
5587  *              stripped.
5588  *
5589  * @return A shell status integer (0 for success).
5590  **/
5591
5592 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5593 {
5594         int rc =  -1;
5595
5596         if (c->display_usage) {
5597                 d_printf("Usage:\n"
5598                          "net rpc shutdown\n"
5599                          "    Shut down a remote RPC server\n");
5600                 return 0;
5601         }
5602
5603         rc = run_rpc_command(c, NULL, PI_INITSHUTDOWN, 0,
5604                              rpc_init_shutdown_internals, argc, argv);
5605
5606         if (rc) {
5607                 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5608                 rc = run_rpc_command(c, NULL, PI_WINREG, 0,
5609                                      rpc_reg_shutdown_internals, argc, argv);
5610         }
5611
5612         return rc;
5613 }
5614
5615 /***************************************************************************
5616   NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5617  ***************************************************************************/
5618
5619 /**
5620  * Add interdomain trust account to the RPC server.
5621  * All parameters (except for argc and argv) are passed by run_rpc_command
5622  * function.
5623  *
5624  * @param c     A net_context structure.
5625  * @param domain_sid The domain sid acquired from the server.
5626  * @param cli A cli_state connected to the server.
5627  * @param mem_ctx Talloc context, destroyed on completion of the function.
5628  * @param argc  Standard main() style argc.
5629  * @param argv  Standard main() style argv. Initial components are already
5630  *              stripped.
5631  *
5632  * @return normal NTSTATUS return code.
5633  */
5634
5635 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
5636                                                 const DOM_SID *domain_sid,
5637                                                 const char *domain_name,
5638                                                 struct cli_state *cli,
5639                                                 struct rpc_pipe_client *pipe_hnd,
5640                                                 TALLOC_CTX *mem_ctx,
5641                                                 int argc,
5642                                                 const char **argv)
5643 {
5644         POLICY_HND connect_pol, domain_pol, user_pol;
5645         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5646         char *acct_name;
5647         struct lsa_String lsa_acct_name;
5648         uint32 acb_info;
5649         uint32 acct_flags=0;
5650         uint32 user_rid;
5651         uint32_t access_granted = 0;
5652         union samr_UserInfo info;
5653         unsigned int orig_timeout;
5654
5655         if (argc != 2) {
5656                 d_printf("Usage: net rpc trustdom add <domain_name> "
5657                          "<trust password>\n");
5658                 return NT_STATUS_INVALID_PARAMETER;
5659         }
5660
5661         /* 
5662          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5663          */
5664
5665         if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5666                 return NT_STATUS_NO_MEMORY;
5667         }
5668
5669         strupper_m(acct_name);
5670
5671         init_lsa_String(&lsa_acct_name, acct_name);
5672
5673         /* Get samr policy handle */
5674         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5675                                       pipe_hnd->desthost,
5676                                       MAXIMUM_ALLOWED_ACCESS,
5677                                       &connect_pol);
5678         if (!NT_STATUS_IS_OK(result)) {
5679                 goto done;
5680         }
5681
5682         /* Get domain policy handle */
5683         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5684                                         &connect_pol,
5685                                         MAXIMUM_ALLOWED_ACCESS,
5686                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5687                                         &domain_pol);
5688         if (!NT_STATUS_IS_OK(result)) {
5689                 goto done;
5690         }
5691
5692         /* This call can take a long time - allow the server to time out.
5693          * 35 seconds should do it. */
5694
5695         orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5696
5697         /* Create trusting domain's account */
5698         acb_info = ACB_NORMAL;
5699         acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5700                      SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5701                      SAMR_USER_ACCESS_SET_PASSWORD |
5702                      SAMR_USER_ACCESS_GET_ATTRIBUTES |
5703                      SAMR_USER_ACCESS_SET_ATTRIBUTES;
5704
5705         result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5706                                          &domain_pol,
5707                                          &lsa_acct_name,
5708                                          acb_info,
5709                                          acct_flags,
5710                                          &user_pol,
5711                                          &access_granted,
5712                                          &user_rid);
5713
5714         /* And restore our original timeout. */
5715         rpccli_set_timeout(pipe_hnd, orig_timeout);
5716
5717         if (!NT_STATUS_IS_OK(result)) {
5718                 d_printf("net rpc trustdom add: create user %s failed %s\n",
5719                         acct_name, nt_errstr(result));
5720                 goto done;
5721         }
5722
5723         {
5724                 NTTIME notime;
5725                 struct samr_LogonHours hours;
5726                 struct lsa_BinaryString parameters;
5727                 const int units_per_week = 168;
5728                 uchar pwbuf[516];
5729
5730                 encode_pw_buffer(pwbuf, argv[1], STR_UNICODE);
5731
5732                 ZERO_STRUCT(notime);
5733                 ZERO_STRUCT(hours);
5734                 ZERO_STRUCT(parameters);
5735
5736                 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
5737                 if (!hours.bits) {
5738                         result = NT_STATUS_NO_MEMORY;
5739                         goto done;
5740                 }
5741                 hours.units_per_week = units_per_week;
5742                 memset(hours.bits, 0xFF, units_per_week);
5743
5744                 init_samr_user_info23(&info.info23,
5745                                       notime, notime, notime,
5746                                       notime, notime, notime,
5747                                       NULL, NULL, NULL, NULL, NULL,
5748                                       NULL, NULL, NULL, NULL, &parameters,
5749                                       0, 0, ACB_DOMTRUST, SAMR_FIELD_ACCT_FLAGS,
5750                                       hours,
5751                                       0, 0, 0, 0, 0, 0, 0,
5752                                       pwbuf, 24);
5753
5754                 SamOEMhashBlob(info.info23.password.data, 516,
5755                                &cli->user_session_key);
5756
5757                 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5758                                                   &user_pol,
5759                                                   23,
5760                                                   &info);
5761
5762                 if (!NT_STATUS_IS_OK(result)) {
5763                         DEBUG(0,("Could not set trust account password: %s\n",
5764                                  nt_errstr(result)));
5765                         goto done;
5766                 }
5767         }
5768
5769  done:
5770         SAFE_FREE(acct_name);
5771         return result;
5772 }
5773
5774 /**
5775  * Create interdomain trust account for a remote domain.
5776  *
5777  * @param argc Standard argc.
5778  * @param argv Standard argv without initial components.
5779  *
5780  * @return Integer status (0 means success).
5781  **/
5782
5783 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5784 {
5785         if (argc > 0 && !c->display_usage) {
5786                 return run_rpc_command(c, NULL, PI_SAMR, 0,
5787                                        rpc_trustdom_add_internals, argc, argv);
5788         } else {
5789                 d_printf("Usage:\n"
5790                         "net rpc trustdom add <domain_name> <trust password>\n");
5791                 return -1;
5792         }
5793 }
5794
5795
5796 /**
5797  * Remove interdomain trust account from the RPC server.
5798  * All parameters (except for argc and argv) are passed by run_rpc_command
5799  * function.
5800  *
5801  * @param c     A net_context structure.
5802  * @param domain_sid The domain sid acquired from the server.
5803  * @param cli A cli_state connected to the server.
5804  * @param mem_ctx Talloc context, destroyed on completion of the function.
5805  * @param argc  Standard main() style argc.
5806  * @param argv  Standard main() style argv. Initial components are already
5807  *              stripped.
5808  *
5809  * @return normal NTSTATUS return code.
5810  */
5811
5812 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
5813                                         const DOM_SID *domain_sid,
5814                                         const char *domain_name,
5815                                         struct cli_state *cli,
5816                                         struct rpc_pipe_client *pipe_hnd,
5817                                         TALLOC_CTX *mem_ctx,
5818                                         int argc,
5819                                         const char **argv)
5820 {
5821         POLICY_HND connect_pol, domain_pol, user_pol;
5822         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5823         char *acct_name;
5824         DOM_SID trust_acct_sid;
5825         struct samr_Ids user_rids, name_types;
5826         struct lsa_String lsa_acct_name;
5827
5828         if (argc != 1) {
5829                 d_printf("Usage: net rpc trustdom del <domain_name>\n");
5830                 return NT_STATUS_INVALID_PARAMETER;
5831         }
5832
5833         /*
5834          * Make valid trusting domain account (ie. uppercased and with '$' appended)
5835          */
5836         acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5837
5838         if (acct_name == NULL)
5839                 return NT_STATUS_NO_MEMORY;
5840
5841         strupper_m(acct_name);
5842
5843         /* Get samr policy handle */
5844         result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5845                                       pipe_hnd->desthost,
5846                                       MAXIMUM_ALLOWED_ACCESS,
5847                                       &connect_pol);
5848         if (!NT_STATUS_IS_OK(result)) {
5849                 goto done;
5850         }
5851
5852         /* Get domain policy handle */
5853         result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5854                                         &connect_pol,
5855                                         MAXIMUM_ALLOWED_ACCESS,
5856                                         CONST_DISCARD(struct dom_sid2 *, domain_sid),
5857                                         &domain_pol);
5858         if (!NT_STATUS_IS_OK(result)) {
5859                 goto done;
5860         }
5861
5862         init_lsa_String(&lsa_acct_name, acct_name);
5863
5864         result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5865                                          &domain_pol,
5866                                          1,
5867                                          &lsa_acct_name,
5868                                          &user_rids,
5869                                          &name_types);
5870
5871         if (!NT_STATUS_IS_OK(result)) {
5872                 d_printf("net rpc trustdom del: LookupNames on user %s failed %s\n",
5873                         acct_name, nt_errstr(result) );
5874                 goto done;
5875         }
5876
5877         result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5878                                       &domain_pol,
5879                                       MAXIMUM_ALLOWED_ACCESS,
5880                                       user_rids.ids[0],
5881                                       &user_pol);
5882
5883         if (!NT_STATUS_IS_OK(result)) {
5884                 d_printf("net rpc trustdom del: OpenUser on user %s failed %s\n",
5885                         acct_name, nt_errstr(result) );
5886                 goto done;
5887         }
5888
5889         /* append the rid to the domain sid */
5890         sid_copy(&trust_acct_sid, domain_sid);
5891         if (!sid_append_rid(&trust_acct_sid, user_rids.ids[0])) {
5892                 goto done;
5893         }
5894
5895         /* remove the sid */
5896
5897         result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5898                                                            &user_pol,
5899                                                            &trust_acct_sid);
5900         if (!NT_STATUS_IS_OK(result)) {
5901                 d_printf("net rpc trustdom del: RemoveMemberFromForeignDomain on user %s failed %s\n",
5902                         acct_name, nt_errstr(result) );
5903                 goto done;
5904         }
5905
5906         /* Delete user */
5907
5908         result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5909                                         &user_pol);
5910
5911         if (!NT_STATUS_IS_OK(result)) {
5912                 d_printf("net rpc trustdom del: DeleteUser on user %s failed %s\n",
5913                         acct_name, nt_errstr(result) );
5914                 goto done;
5915         }
5916
5917         if (!NT_STATUS_IS_OK(result)) {
5918                 d_printf("Could not set trust account password: %s\n",
5919                    nt_errstr(result));
5920                 goto done;
5921         }
5922
5923  done:
5924         return result;
5925 }
5926
5927 /**
5928  * Delete interdomain trust account for a remote domain.
5929  *
5930  * @param argc Standard argc.
5931  * @param argv Standard argv without initial components.
5932  *
5933  * @return Integer status (0 means success).
5934  **/
5935
5936 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
5937 {
5938         if (argc > 0 && !c->display_usage) {
5939                 return run_rpc_command(c, NULL, PI_SAMR, 0,
5940                                        rpc_trustdom_del_internals, argc, argv);
5941         } else {
5942                 d_printf("Usage:\n"
5943                          "net rpc trustdom del <domain>\n");
5944                 return -1;
5945         }
5946 }
5947
5948 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
5949                                      struct cli_state *cli,
5950                                      TALLOC_CTX *mem_ctx,
5951                                      const char *domain_name)
5952 {
5953         char *dc_name = NULL;
5954         const char *buffer = NULL;
5955         struct rpc_pipe_client *netr;
5956         NTSTATUS status;
5957
5958         /* Use NetServerEnum2 */
5959
5960         if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
5961                 SAFE_FREE(dc_name);
5962                 return NT_STATUS_OK;
5963         }
5964
5965         DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
5966                  for domain %s\n", domain_name));
5967
5968         /* Try netr_GetDcName */
5969
5970         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
5971                                           &netr);
5972         if (!NT_STATUS_IS_OK(status)) {
5973                 return status;
5974         }
5975
5976         status = rpccli_netr_GetDcName(netr, mem_ctx,
5977                                        cli->desthost,
5978                                        domain_name,
5979                                        &buffer,
5980                                        NULL);
5981         TALLOC_FREE(netr);
5982
5983         if (NT_STATUS_IS_OK(status)) {
5984                 return status;
5985         }
5986
5987         DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
5988                  for domain %s\n", domain_name));
5989
5990         return status;
5991 }
5992
5993 /**
5994  * Establish trust relationship to a trusting domain.
5995  * Interdomain account must already be created on remote PDC.
5996  *
5997  * @param c    A net_context structure.
5998  * @param argc Standard argc.
5999  * @param argv Standard argv without initial components.
6000  *
6001  * @return Integer status (0 means success).
6002  **/
6003
6004 static int rpc_trustdom_establish(struct net_context *c, int argc,
6005                                   const char **argv)
6006 {
6007         struct cli_state *cli = NULL;
6008         struct sockaddr_storage server_ss;
6009         struct rpc_pipe_client *pipe_hnd = NULL;
6010         POLICY_HND connect_hnd;
6011         TALLOC_CTX *mem_ctx;
6012         NTSTATUS nt_status;
6013         DOM_SID *domain_sid;
6014
6015         char* domain_name;
6016         char* acct_name;
6017         fstring pdc_name;
6018         union lsa_PolicyInformation *info = NULL;
6019
6020         /*
6021          * Connect to \\server\ipc$ as 'our domain' account with password
6022          */
6023
6024         if (argc != 1 || c->display_usage) {
6025                 d_printf("Usage:\n"
6026                          "net rpc trustdom establish <domain_name>\n");
6027                 return -1;
6028         }
6029
6030         domain_name = smb_xstrdup(argv[0]);
6031         strupper_m(domain_name);
6032
6033         /* account name used at first is our domain's name with '$' */
6034         asprintf(&acct_name, "%s$", lp_workgroup());
6035         strupper_m(acct_name);
6036
6037         /*
6038          * opt_workgroup will be used by connection functions further,
6039          * hence it should be set to remote domain name instead of ours
6040          */
6041         if (c->opt_workgroup) {
6042                 c->opt_workgroup = smb_xstrdup(domain_name);
6043         };
6044
6045         c->opt_user_name = acct_name;
6046
6047         /* find the domain controller */
6048         if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
6049                 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
6050                 return -1;
6051         }
6052
6053         /* connect to ipc$ as username/password */
6054         nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
6055         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
6056
6057                 /* Is it trusting domain account for sure ? */
6058                 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
6059                         nt_errstr(nt_status)));
6060                 return -1;
6061         }
6062
6063         /* store who we connected to */
6064
6065         saf_store( domain_name, pdc_name );
6066
6067         /*
6068          * Connect to \\server\ipc$ again (this time anonymously)
6069          */
6070
6071         nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
6072                                              (char*)pdc_name);
6073
6074         if (NT_STATUS_IS_ERR(nt_status)) {
6075                 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
6076                         domain_name, nt_errstr(nt_status)));
6077                 return -1;
6078         }
6079
6080         if (!(mem_ctx = talloc_init("establishing trust relationship to "
6081                                     "domain %s", domain_name))) {
6082                 DEBUG(0, ("talloc_init() failed\n"));
6083                 cli_shutdown(cli);
6084                 return -1;
6085         }
6086
6087         /* Make sure we're talking to a proper server */
6088
6089         nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
6090         if (!NT_STATUS_IS_OK(nt_status)) {
6091                 cli_shutdown(cli);
6092                 talloc_destroy(mem_ctx);
6093                 return -1;
6094         }
6095
6096         /*
6097          * Call LsaOpenPolicy and LsaQueryInfo
6098          */
6099
6100         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6101                                              &pipe_hnd);
6102         if (!NT_STATUS_IS_OK(nt_status)) {
6103                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
6104                 cli_shutdown(cli);
6105                 talloc_destroy(mem_ctx);
6106                 return -1;
6107         }
6108
6109         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, SEC_RIGHTS_QUERY_VALUE,
6110                                          &connect_hnd);
6111         if (NT_STATUS_IS_ERR(nt_status)) {
6112                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6113                         nt_errstr(nt_status)));
6114                 cli_shutdown(cli);
6115                 talloc_destroy(mem_ctx);
6116                 return -1;
6117         }
6118
6119         /* Querying info level 5 */
6120
6121         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6122                                                &connect_hnd,
6123                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6124                                                &info);
6125         if (NT_STATUS_IS_ERR(nt_status)) {
6126                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6127                         nt_errstr(nt_status)));
6128                 cli_shutdown(cli);
6129                 talloc_destroy(mem_ctx);
6130                 return -1;
6131         }
6132
6133         domain_sid = info->account_domain.sid;
6134
6135         /* There should be actually query info level 3 (following nt serv behaviour),
6136            but I still don't know if it's _really_ necessary */
6137
6138         /*
6139          * Store the password in secrets db
6140          */
6141
6142         if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6143                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6144                 cli_shutdown(cli);
6145                 talloc_destroy(mem_ctx);
6146                 return -1;
6147         }
6148
6149         /*
6150          * Close the pipes and clean up
6151          */
6152
6153         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6154         if (NT_STATUS_IS_ERR(nt_status)) {
6155                 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6156                         nt_errstr(nt_status)));
6157                 cli_shutdown(cli);
6158                 talloc_destroy(mem_ctx);
6159                 return -1;
6160         }
6161
6162         cli_shutdown(cli);
6163
6164         talloc_destroy(mem_ctx);
6165
6166         d_printf("Trust to domain %s established\n", domain_name);
6167         return 0;
6168 }
6169
6170 /**
6171  * Revoke trust relationship to the remote domain.
6172  *
6173  * @param c    A net_context structure.
6174  * @param argc Standard argc.
6175  * @param argv Standard argv without initial components.
6176  *
6177  * @return Integer status (0 means success).
6178  **/
6179
6180 static int rpc_trustdom_revoke(struct net_context *c, int argc,
6181                                const char **argv)
6182 {
6183         char* domain_name;
6184         int rc = -1;
6185
6186         if (argc < 1 || c->display_usage) {
6187                 d_printf("Usage:\n"
6188                          "net rpc trustdom revoke <domain_name>\n"
6189                          "  Revoke trust relationship\n"
6190                          "    domain_name\tName of domain to revoke trust\n");
6191                 return -1;
6192         }
6193
6194         /* generate upper cased domain name */
6195         domain_name = smb_xstrdup(argv[0]);
6196         strupper_m(domain_name);
6197
6198         /* delete password of the trust */
6199         if (!pdb_del_trusteddom_pw(domain_name)) {
6200                 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6201                           domain_name));
6202                 goto done;
6203         };
6204
6205         rc = 0;
6206 done:
6207         SAFE_FREE(domain_name);
6208         return rc;
6209 }
6210
6211 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6212                                         const DOM_SID *domain_sid,
6213                                         const char *domain_name,
6214                                         struct cli_state *cli,
6215                                         struct rpc_pipe_client *pipe_hnd,
6216                                         TALLOC_CTX *mem_ctx,
6217                                         int argc,
6218                                         const char **argv)
6219 {
6220         fstring str_sid;
6221         sid_to_fstring(str_sid, domain_sid);
6222         d_printf("%s\n", str_sid);
6223         return NT_STATUS_OK;
6224 }
6225
6226 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
6227 {
6228         fstring ascii_sid, padding;
6229         int pad_len, col_len = 20;
6230
6231         /* convert sid into ascii string */
6232         sid_to_fstring(ascii_sid, dom_sid);
6233
6234         /* calculate padding space for d_printf to look nicer */
6235         pad_len = col_len - strlen(trusted_dom_name);
6236         padding[pad_len] = 0;
6237         do padding[--pad_len] = ' '; while (pad_len);
6238
6239         d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
6240 }
6241
6242 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6243                                       TALLOC_CTX *mem_ctx,
6244                                       POLICY_HND *pol,
6245                                       DOM_SID dom_sid,
6246                                       const char *trusted_dom_name)
6247 {
6248         NTSTATUS nt_status;
6249         union lsa_TrustedDomainInfo *info = NULL;
6250         char *cleartextpwd = NULL;
6251         uint8_t nt_hash[16];
6252         DATA_BLOB data;
6253
6254         nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
6255                                                            pol,
6256                                                            &dom_sid,
6257                                                            LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6258                                                            &info);
6259         if (NT_STATUS_IS_ERR(nt_status)) {
6260                 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6261                 nt_errstr(nt_status)));
6262                 goto done;
6263         }
6264
6265         data = data_blob(info->password.password->data,
6266                          info->password.password->length);
6267
6268         if (!rpccli_get_pwd_hash(pipe_hnd, nt_hash)) {
6269                 DEBUG(0, ("Could not retrieve password hash\n"));
6270                 goto done;
6271         }
6272
6273         cleartextpwd = decrypt_trustdom_secret(nt_hash, &data);
6274
6275         if (cleartextpwd == NULL) {
6276                 DEBUG(0,("retrieved NULL password\n"));
6277                 nt_status = NT_STATUS_UNSUCCESSFUL;
6278                 goto done;
6279         }
6280
6281         if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6282                 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6283                 nt_status = NT_STATUS_UNSUCCESSFUL;
6284                 goto done;
6285         }
6286
6287 #ifdef DEBUG_PASSWORD
6288         DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
6289                    "password: [%s]\n", trusted_dom_name,
6290                    sid_string_dbg(&dom_sid), cleartextpwd));
6291 #endif
6292
6293 done:
6294         SAFE_FREE(cleartextpwd);
6295         data_blob_free(&data);
6296
6297         return nt_status;
6298 }
6299
6300 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6301                                 const char **argv)
6302 {
6303         /* common variables */
6304         TALLOC_CTX* mem_ctx;
6305         struct cli_state *cli = NULL;
6306         struct rpc_pipe_client *pipe_hnd = NULL;
6307         NTSTATUS nt_status;
6308         const char *domain_name = NULL;
6309         DOM_SID *queried_dom_sid;
6310         POLICY_HND connect_hnd;
6311         union lsa_PolicyInformation *info = NULL;
6312
6313         /* trusted domains listing variables */
6314         unsigned int enum_ctx = 0;
6315         int i;
6316         struct lsa_DomainList dom_list;
6317         fstring pdc_name;
6318
6319         if (c->display_usage) {
6320                 d_printf("Usage:\n"
6321                          "net rpc trustdom vampire\n"
6322                          "  Vampire trust relationship from remote server\n");
6323                 return 0;
6324         }
6325
6326         /*
6327          * Listing trusted domains (stored in secrets.tdb, if local)
6328          */
6329
6330         mem_ctx = talloc_init("trust relationships vampire");
6331
6332         /*
6333          * set domain and pdc name to local samba server (default)
6334          * or to remote one given in command line
6335          */
6336
6337         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6338                 domain_name = c->opt_workgroup;
6339                 c->opt_target_workgroup = c->opt_workgroup;
6340         } else {
6341                 fstrcpy(pdc_name, global_myname());
6342                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6343                 c->opt_target_workgroup = domain_name;
6344         };
6345
6346         /* open \PIPE\lsarpc and open policy handle */
6347         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6348         if (!NT_STATUS_IS_OK(nt_status)) {
6349                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6350                           nt_errstr(nt_status)));
6351                 talloc_destroy(mem_ctx);
6352                 return -1;
6353         };
6354
6355         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6356                                              &pipe_hnd);
6357         if (!NT_STATUS_IS_OK(nt_status)) {
6358                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6359                         nt_errstr(nt_status) ));
6360                 cli_shutdown(cli);
6361                 talloc_destroy(mem_ctx);
6362                 return -1;
6363         };
6364
6365         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, SEC_RIGHTS_QUERY_VALUE,
6366                                         &connect_hnd);
6367         if (NT_STATUS_IS_ERR(nt_status)) {
6368                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6369                         nt_errstr(nt_status)));
6370                 cli_shutdown(cli);
6371                 talloc_destroy(mem_ctx);
6372                 return -1;
6373         };
6374
6375         /* query info level 5 to obtain sid of a domain being queried */
6376         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6377                                                &connect_hnd,
6378                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6379                                                &info);
6380
6381         if (NT_STATUS_IS_ERR(nt_status)) {
6382                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6383                         nt_errstr(nt_status)));
6384                 cli_shutdown(cli);
6385                 talloc_destroy(mem_ctx);
6386                 return -1;
6387         }
6388
6389         queried_dom_sid = info->account_domain.sid;
6390
6391         /*
6392          * Keep calling LsaEnumTrustdom over opened pipe until
6393          * the end of enumeration is reached
6394          */
6395
6396         d_printf("Vampire trusted domains:\n\n");
6397
6398         do {
6399                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6400                                                     &connect_hnd,
6401                                                     &enum_ctx,
6402                                                     &dom_list,
6403                                                     (uint32_t)-1);
6404                 if (NT_STATUS_IS_ERR(nt_status)) {
6405                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6406                                 nt_errstr(nt_status)));
6407                         cli_shutdown(cli);
6408                         talloc_destroy(mem_ctx);
6409                         return -1;
6410                 };
6411
6412                 for (i = 0; i < dom_list.count; i++) {
6413
6414                         print_trusted_domain(dom_list.domains[i].sid,
6415                                              dom_list.domains[i].name.string);
6416
6417                         nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
6418                                                            *dom_list.domains[i].sid,
6419                                                            dom_list.domains[i].name.string);
6420                         if (!NT_STATUS_IS_OK(nt_status)) {
6421                                 cli_shutdown(cli);
6422                                 talloc_destroy(mem_ctx);
6423                                 return -1;
6424                         }
6425                 };
6426
6427                 /*
6428                  * in case of no trusted domains say something rather
6429                  * than just display blank line
6430                  */
6431                 if (!dom_list.count) d_printf("none\n");
6432
6433         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6434
6435         /* close this connection before doing next one */
6436         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6437         if (NT_STATUS_IS_ERR(nt_status)) {
6438                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6439                         nt_errstr(nt_status)));
6440                 cli_shutdown(cli);
6441                 talloc_destroy(mem_ctx);
6442                 return -1;
6443         };
6444
6445         /* close lsarpc pipe and connection to IPC$ */
6446         cli_shutdown(cli);
6447
6448         talloc_destroy(mem_ctx);
6449         return 0;
6450 }
6451
6452 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6453 {
6454         /* common variables */
6455         TALLOC_CTX* mem_ctx;
6456         struct cli_state *cli = NULL, *remote_cli = NULL;
6457         struct rpc_pipe_client *pipe_hnd = NULL;
6458         NTSTATUS nt_status;
6459         const char *domain_name = NULL;
6460         DOM_SID *queried_dom_sid;
6461         fstring padding;
6462         int ascii_dom_name_len;
6463         POLICY_HND connect_hnd;
6464         union lsa_PolicyInformation *info = NULL;
6465
6466         /* trusted domains listing variables */
6467         unsigned int num_domains, enum_ctx = 0;
6468         int i, pad_len, col_len = 20;
6469         struct lsa_DomainList dom_list;
6470         fstring pdc_name;
6471
6472         /* trusting domains listing variables */
6473         POLICY_HND domain_hnd;
6474         struct samr_SamArray *trusts = NULL;
6475
6476         if (c->display_usage) {
6477                 d_printf("Usage:\n"
6478                          "net rpc trustdom list\n"
6479                          "    List trust relationships\n");
6480                 return 0;
6481         }
6482
6483         /*
6484          * Listing trusted domains (stored in secrets.tdb, if local)
6485          */
6486
6487         mem_ctx = talloc_init("trust relationships listing");
6488
6489         /*
6490          * set domain and pdc name to local samba server (default)
6491          * or to remote one given in command line
6492          */
6493
6494         if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6495                 domain_name = c->opt_workgroup;
6496                 c->opt_target_workgroup = c->opt_workgroup;
6497         } else {
6498                 fstrcpy(pdc_name, global_myname());
6499                 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6500                 c->opt_target_workgroup = domain_name;
6501         };
6502
6503         /* open \PIPE\lsarpc and open policy handle */
6504         nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6505         if (!NT_STATUS_IS_OK(nt_status)) {
6506                 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6507                           nt_errstr(nt_status)));
6508                 talloc_destroy(mem_ctx);
6509                 return -1;
6510         };
6511
6512         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6513                                              &pipe_hnd);
6514         if (!NT_STATUS_IS_OK(nt_status)) {
6515                 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6516                         nt_errstr(nt_status) ));
6517                 cli_shutdown(cli);
6518                 talloc_destroy(mem_ctx);
6519                 return -1;
6520         };
6521
6522         nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, SEC_RIGHTS_QUERY_VALUE,
6523                                         &connect_hnd);
6524         if (NT_STATUS_IS_ERR(nt_status)) {
6525                 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6526                         nt_errstr(nt_status)));
6527                 cli_shutdown(cli);
6528                 talloc_destroy(mem_ctx);
6529                 return -1;
6530         };
6531         
6532         /* query info level 5 to obtain sid of a domain being queried */
6533         nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6534                                                &connect_hnd,
6535                                                LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6536                                                &info);
6537
6538         if (NT_STATUS_IS_ERR(nt_status)) {
6539                 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6540                         nt_errstr(nt_status)));
6541                 cli_shutdown(cli);
6542                 talloc_destroy(mem_ctx);
6543                 return -1;
6544         }
6545
6546         queried_dom_sid = info->account_domain.sid;
6547
6548         /*
6549          * Keep calling LsaEnumTrustdom over opened pipe until
6550          * the end of enumeration is reached
6551          */
6552          
6553         d_printf("Trusted domains list:\n\n");
6554
6555         do {
6556                 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6557                                                     &connect_hnd,
6558                                                     &enum_ctx,
6559                                                     &dom_list,
6560                                                     (uint32_t)-1);
6561                 if (NT_STATUS_IS_ERR(nt_status)) {
6562                         DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6563                                 nt_errstr(nt_status)));
6564                         cli_shutdown(cli);
6565                         talloc_destroy(mem_ctx);
6566                         return -1;
6567                 };
6568
6569                 for (i = 0; i < dom_list.count; i++) {
6570                         print_trusted_domain(dom_list.domains[i].sid,
6571                                              dom_list.domains[i].name.string);
6572                 };
6573
6574                 /*
6575                  * in case of no trusted domains say something rather
6576                  * than just display blank line
6577                  */
6578                 if (!dom_list.count) d_printf("none\n");
6579
6580         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6581
6582         /* close this connection before doing next one */
6583         nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6584         if (NT_STATUS_IS_ERR(nt_status)) {
6585                 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6586                         nt_errstr(nt_status)));
6587                 cli_shutdown(cli);
6588                 talloc_destroy(mem_ctx);
6589                 return -1;
6590         };
6591         
6592         TALLOC_FREE(pipe_hnd);
6593
6594         /*
6595          * Listing trusting domains (stored in passdb backend, if local)
6596          */
6597         
6598         d_printf("\nTrusting domains list:\n\n");
6599
6600         /*
6601          * Open \PIPE\samr and get needed policy handles
6602          */
6603         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6604                                              &pipe_hnd);
6605         if (!NT_STATUS_IS_OK(nt_status)) {
6606                 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6607                 cli_shutdown(cli);
6608                 talloc_destroy(mem_ctx);
6609                 return -1;
6610         };
6611
6612         /* SamrConnect2 */
6613         nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6614                                          pipe_hnd->desthost,
6615                                          SA_RIGHT_SAM_OPEN_DOMAIN,
6616                                          &connect_hnd);
6617         if (!NT_STATUS_IS_OK(nt_status)) {
6618                 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6619                         nt_errstr(nt_status)));
6620                 cli_shutdown(cli);
6621                 talloc_destroy(mem_ctx);
6622                 return -1;
6623         };
6624
6625         /* SamrOpenDomain - we have to open domain policy handle in order to be
6626            able to enumerate accounts*/
6627         nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6628                                            &connect_hnd,
6629                                            SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
6630                                            queried_dom_sid,
6631                                            &domain_hnd);
6632         if (!NT_STATUS_IS_OK(nt_status)) {
6633                 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6634                         nt_errstr(nt_status)));
6635                 cli_shutdown(cli);
6636                 talloc_destroy(mem_ctx);
6637                 return -1;
6638         };
6639
6640         /*
6641          * perform actual enumeration
6642          */
6643
6644         enum_ctx = 0;   /* reset enumeration context from last enumeration */
6645         do {
6646
6647                 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6648                                                         &domain_hnd,
6649                                                         &enum_ctx,
6650                                                         ACB_DOMTRUST,
6651                                                         &trusts,
6652                                                         0xffff,
6653                                                         &num_domains);
6654                 if (NT_STATUS_IS_ERR(nt_status)) {
6655                         DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6656                                 nt_errstr(nt_status)));
6657                         cli_shutdown(cli);
6658                         talloc_destroy(mem_ctx);
6659                         return -1;
6660                 };
6661
6662                 for (i = 0; i < num_domains; i++) {
6663
6664                         char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6665
6666                         /*
6667                          * get each single domain's sid (do we _really_ need this ?):
6668                          *  1) connect to domain's pdc
6669                          *  2) query the pdc for domain's sid
6670                          */
6671
6672                         /* get rid of '$' tail */
6673                         ascii_dom_name_len = strlen(str);
6674                         if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6675                                 str[ascii_dom_name_len - 1] = '\0';
6676
6677                         /* calculate padding space for d_printf to look nicer */
6678                         pad_len = col_len - strlen(str);
6679                         padding[pad_len] = 0;
6680                         do padding[--pad_len] = ' '; while (pad_len);
6681
6682                         /* set opt_* variables to remote domain */
6683                         strupper_m(str);
6684                         c->opt_workgroup = talloc_strdup(mem_ctx, str);
6685                         c->opt_target_workgroup = c->opt_workgroup;
6686
6687                         d_printf("%s%s", str, padding);
6688
6689                         /* connect to remote domain controller */
6690                         nt_status = net_make_ipc_connection(c,
6691                                         NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6692                                         &remote_cli);
6693                         if (NT_STATUS_IS_OK(nt_status)) {
6694                                 /* query for domain's sid */
6695                                 if (run_rpc_command(c, remote_cli, PI_LSARPC, 0,
6696                                                     rpc_query_domain_sid, argc,
6697                                                     argv))
6698                                         d_fprintf(stderr, "couldn't get domain's sid\n");
6699
6700                                 cli_shutdown(remote_cli);
6701
6702                         } else {
6703                                 d_fprintf(stderr, "domain controller is not "
6704                                           "responding: %s\n",
6705                                           nt_errstr(nt_status));
6706                         };
6707                 };
6708
6709                 if (!num_domains) d_printf("none\n");
6710
6711         } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6712
6713         /* close opened samr and domain policy handles */
6714         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6715         if (!NT_STATUS_IS_OK(nt_status)) {
6716                 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6717         };
6718
6719         nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6720         if (!NT_STATUS_IS_OK(nt_status)) {
6721                 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6722         };
6723
6724         /* close samr pipe and connection to IPC$ */
6725         cli_shutdown(cli);
6726
6727         talloc_destroy(mem_ctx);
6728         return 0;
6729 }
6730
6731 /**
6732  * Entrypoint for 'net rpc trustdom' code.
6733  *
6734  * @param argc Standard argc.
6735  * @param argv Standard argv without initial components.
6736  *
6737  * @return Integer status (0 means success).
6738  */
6739
6740 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
6741 {
6742         struct functable func[] = {
6743                 {
6744                         "add",
6745                         rpc_trustdom_add,
6746                         NET_TRANSPORT_RPC,
6747                         "Add trusted domain's account",
6748                         "net rpc trustdom add\n"
6749                         "    Add trusted domain's account"
6750                 },
6751                 {
6752                         "del",
6753                         rpc_trustdom_del,
6754                         NET_TRANSPORT_RPC,
6755                         "Remove trusted domain's account",
6756                         "net rpc trustdom del\n"
6757                         "    Remove trusted domain's account"
6758                 },
6759                 {
6760                         "establish",
6761                         rpc_trustdom_establish,
6762                         NET_TRANSPORT_RPC,
6763                         "Establish trust relationship",
6764                         "net rpc trustdom establish\n"
6765                         "    Establish trust relationship"
6766                 },
6767                 {
6768                         "revoke",
6769                         rpc_trustdom_revoke,
6770                         NET_TRANSPORT_RPC,
6771                         "Revoke trust relationship",
6772                         "net rpc trustdom revoke\n"
6773                         "    Revoke trust relationship"
6774                 },
6775                 {
6776                         "list",
6777                         rpc_trustdom_list,
6778                         NET_TRANSPORT_RPC,
6779                         "List domain trusts",
6780                         "net rpc trustdom list\n"
6781                         "    List domain trusts"
6782                 },
6783                 {
6784                         "vampire",
6785                         rpc_trustdom_vampire,
6786                         NET_TRANSPORT_RPC,
6787                         "Vampire trusts from remote server",
6788                         "net rpc trustdom vampire\n"
6789                         "    Vampire trusts from remote server"
6790                 },
6791                 {NULL, NULL, 0, NULL, NULL}
6792         };
6793
6794         return net_run_function(c, argc, argv, "net rpc trustdom", func);
6795 }
6796
6797 /**
6798  * Check if a server will take rpc commands
6799  * @param flags Type of server to connect to (PDC, DMB, localhost)
6800  *              if the host is not explicitly specified
6801  * @return  bool (true means rpc supported)
6802  */
6803 bool net_rpc_check(struct net_context *c, unsigned flags)
6804 {
6805         struct cli_state *cli;
6806         bool ret = false;
6807         struct sockaddr_storage server_ss;
6808         char *server_name = NULL;
6809         NTSTATUS status;
6810
6811         /* flags (i.e. server type) may depend on command */
6812         if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
6813                 return false;
6814
6815         if ((cli = cli_initialise()) == NULL) {
6816                 return false;
6817         }
6818
6819         status = cli_connect(cli, server_name, &server_ss);
6820         if (!NT_STATUS_IS_OK(status))
6821                 goto done;
6822         if (!attempt_netbios_session_request(&cli, global_myname(),
6823                                              server_name, &server_ss))
6824                 goto done;
6825         if (!cli_negprot(cli))
6826                 goto done;
6827         if (cli->protocol < PROTOCOL_NT1)
6828                 goto done;
6829
6830         ret = true;
6831  done:
6832         cli_shutdown(cli);
6833         return ret;
6834 }
6835
6836 /* dump sam database via samsync rpc calls */
6837 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
6838         if (c->display_usage) {
6839                 d_printf("Usage:\n"
6840                          "net rpc samdump\n"
6841                          "    Dump remote SAM database\n");
6842                 return 0;
6843         }
6844
6845         return run_rpc_command(c, NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS,
6846                                rpc_samdump_internals, argc, argv);
6847 }
6848
6849 /* syncronise sam database via samsync rpc calls */
6850 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
6851 {
6852         struct functable func[] = {
6853                 {
6854                         "ldif",
6855                         rpc_vampire_ldif,
6856                         NET_TRANSPORT_RPC,
6857                         "Dump remote SAM database to ldif",
6858                         "net rpc vampire ldif\n"
6859                         "    Dump remote SAM database to LDIF file or stdout"
6860                 },
6861                 {
6862                         "keytab",
6863                         rpc_vampire_keytab,
6864                         NET_TRANSPORT_RPC,
6865                         "Dump remote SAM database to Kerberos Keytab",
6866                         "net rpc vampire keytab\n"
6867                         "    Dump remote SAM database to Kerberos keytab file"
6868                 },
6869
6870                 {NULL, NULL, 0, NULL, NULL}
6871         };
6872
6873         if (argc == 0) {
6874                 if (c->display_usage) {
6875                         d_printf("Usage:\n"
6876                                  "net rpc vampire\n"
6877                                  "    Vampire remote SAM database\n");
6878                         return 0;
6879                 }
6880
6881                 return run_rpc_command(c, NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS,
6882                                        rpc_vampire_internals,
6883                                        argc, argv);
6884         }
6885
6886         return net_run_function(c, argc, argv, "net rpc vampire", func);
6887 }
6888
6889 /**
6890  * Migrate everything from a print server.
6891  *
6892  * @param c     A net_context structure.
6893  * @param argc  Standard main() style argc.
6894  * @param argv  Standard main() style argv. Initial components are already
6895  *              stripped.
6896  *
6897  * @return A shell status integer (0 for success).
6898  *
6899  * The order is important !
6900  * To successfully add drivers the print queues have to exist !
6901  * Applying ACLs should be the last step, because you're easily locked out.
6902  *
6903  **/
6904 static int rpc_printer_migrate_all(struct net_context *c, int argc,
6905                                    const char **argv)
6906 {
6907         int ret;
6908
6909         if (c->display_usage) {
6910                 d_printf("Usage:\n"
6911                          "net rpc printer migrate all\n"
6912                          "    Migrate everything from a print server\n");
6913                 return 0;
6914         }
6915
6916         if (!c->opt_host) {
6917                 d_printf("no server to migrate\n");
6918                 return -1;
6919         }
6920
6921         ret = run_rpc_command(c, NULL, PI_SPOOLSS, 0,
6922                               rpc_printer_migrate_printers_internals, argc,
6923                               argv);
6924         if (ret)
6925                 return ret;
6926
6927         ret = run_rpc_command(c, NULL, PI_SPOOLSS, 0,
6928                               rpc_printer_migrate_drivers_internals, argc,
6929                               argv);
6930         if (ret)
6931                 return ret;
6932
6933         ret = run_rpc_command(c, NULL, PI_SPOOLSS, 0,
6934                               rpc_printer_migrate_forms_internals, argc, argv);
6935         if (ret)
6936                 return ret;
6937
6938         ret = run_rpc_command(c, NULL, PI_SPOOLSS, 0,
6939                               rpc_printer_migrate_settings_internals, argc,
6940                               argv);
6941         if (ret)
6942                 return ret;
6943
6944         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
6945                                rpc_printer_migrate_security_internals, argc,
6946                                argv);
6947
6948 }
6949
6950 /**
6951  * Migrate print drivers from a print server.
6952  *
6953  * @param c     A net_context structure.
6954  * @param argc  Standard main() style argc.
6955  * @param argv  Standard main() style argv. Initial components are already
6956  *              stripped.
6957  *
6958  * @return A shell status integer (0 for success).
6959  **/
6960 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
6961                                        const char **argv)
6962 {
6963         if (c->display_usage) {
6964                 d_printf("Usage:\n"
6965                          "net rpc printer migrate drivers\n"
6966                          "     Migrate print-drivers from a print-server\n");
6967                 return 0;
6968         }
6969
6970         if (!c->opt_host) {
6971                 d_printf("no server to migrate\n");
6972                 return -1;
6973         }
6974
6975         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
6976                                rpc_printer_migrate_drivers_internals,
6977                                argc, argv);
6978 }
6979
6980 /**
6981  * Migrate print-forms from a print-server.
6982  *
6983  * @param c     A net_context structure.
6984  * @param argc  Standard main() style argc.
6985  * @param argv  Standard main() style argv. Initial components are already
6986  *              stripped.
6987  *
6988  * @return A shell status integer (0 for success).
6989  **/
6990 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
6991                                      const char **argv)
6992 {
6993         if (c->display_usage) {
6994                 d_printf("Usage:\n"
6995                          "net rpc printer migrate forms\n"
6996                          "    Migrate print-forms from a print-server\n");
6997                 return 0;
6998         }
6999
7000         if (!c->opt_host) {
7001                 d_printf("no server to migrate\n");
7002                 return -1;
7003         }
7004
7005         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7006                                rpc_printer_migrate_forms_internals,
7007                                argc, argv);
7008 }
7009
7010 /**
7011  * Migrate printers from a print-server.
7012  *
7013  * @param c     A net_context structure.
7014  * @param argc  Standard main() style argc.
7015  * @param argv  Standard main() style argv. Initial components are already
7016  *              stripped.
7017  *
7018  * @return A shell status integer (0 for success).
7019  **/
7020 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
7021                                         const char **argv)
7022 {
7023         if (c->display_usage) {
7024                 d_printf("Usage:\n"
7025                          "net rpc printer migrate printers\n"
7026                          "    Migrate printers from a print-server\n");
7027                 return 0;
7028         }
7029
7030         if (!c->opt_host) {
7031                 d_printf("no server to migrate\n");
7032                 return -1;
7033         }
7034
7035         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7036                                rpc_printer_migrate_printers_internals,
7037                                argc, argv);
7038 }
7039
7040 /**
7041  * Migrate printer-ACLs from a print-server
7042  *
7043  * @param c     A net_context structure.
7044  * @param argc  Standard main() style argc.
7045  * @param argv  Standard main() style argv. Initial components are already
7046  *              stripped.
7047  *
7048  * @return A shell status integer (0 for success).
7049  **/
7050 static int rpc_printer_migrate_security(struct net_context *c, int argc,
7051                                         const char **argv)
7052 {
7053         if (c->display_usage) {
7054                 d_printf("Usage:\n"
7055                          "net rpc printer migrate security\n"
7056                          "    Migrate printer-ACLs from a print-server\n");
7057                 return 0;
7058         }
7059
7060         if (!c->opt_host) {
7061                 d_printf("no server to migrate\n");
7062                 return -1;
7063         }
7064
7065         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7066                                rpc_printer_migrate_security_internals,
7067                                argc, argv);
7068 }
7069
7070 /**
7071  * Migrate printer-settings from a print-server.
7072  *
7073  * @param c     A net_context structure.
7074  * @param argc  Standard main() style argc.
7075  * @param argv  Standard main() style argv. Initial components are already
7076  *              stripped.
7077  *
7078  * @return A shell status integer (0 for success).
7079  **/
7080 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
7081                                         const char **argv)
7082 {
7083         if (c->display_usage) {
7084                 d_printf("Usage:\n"
7085                          "net rpc printer migrate settings\n"
7086                          "    Migrate printer-settings from a print-server\n");
7087                 return 0;
7088         }
7089
7090         if (!c->opt_host) {
7091                 d_printf("no server to migrate\n");
7092                 return -1;
7093         }
7094
7095         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7096                                rpc_printer_migrate_settings_internals,
7097                                argc, argv);
7098 }
7099
7100 /**
7101  * 'net rpc printer' entrypoint.
7102  *
7103  * @param c     A net_context structure.
7104  * @param argc  Standard main() style argc.
7105  * @param argv  Standard main() style argv. Initial components are already
7106  *              stripped.
7107  **/
7108
7109 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
7110 {
7111
7112         /* ouch: when addriver and setdriver are called from within
7113            rpc_printer_migrate_drivers_internals, the printer-queue already
7114            *has* to exist */
7115
7116         struct functable func[] = {
7117                 {
7118                         "all",
7119                         rpc_printer_migrate_all,
7120                         NET_TRANSPORT_RPC,
7121                         "Migrate all from remote to local print server",
7122                         "net rpc printer migrate all\n"
7123                         "    Migrate all from remote to local print server"
7124                 },
7125                 {
7126                         "drivers",
7127                         rpc_printer_migrate_drivers,
7128                         NET_TRANSPORT_RPC,
7129                         "Migrate drivers to local server",
7130                         "net rpc printer migrate drivers\n"
7131                         "    Migrate drivers to local server"
7132                 },
7133                 {
7134                         "forms",
7135                         rpc_printer_migrate_forms,
7136                         NET_TRANSPORT_RPC,
7137                         "Migrate froms to local server",
7138                         "net rpc printer migrate forms\n"
7139                         "    Migrate froms to local server"
7140                 },
7141                 {
7142                         "printers",
7143                         rpc_printer_migrate_printers,
7144                         NET_TRANSPORT_RPC,
7145                         "Migrate printers to local server",
7146                         "net rpc printer migrate printers\n"
7147                         "    Migrate printers to local server"
7148                 },
7149                 {
7150                         "security",
7151                         rpc_printer_migrate_security,
7152                         NET_TRANSPORT_RPC,
7153                         "Mirgate printer ACLs to local server",
7154                         "net rpc printer migrate security\n"
7155                         "    Mirgate printer ACLs to local server"
7156                 },
7157                 {
7158                         "settings",
7159                         rpc_printer_migrate_settings,
7160                         NET_TRANSPORT_RPC,
7161                         "Migrate printer settings to local server",
7162                         "net rpc printer migrate settings\n"
7163                         "    Migrate printer settings to local server"
7164                 },
7165                 {NULL, NULL, 0, NULL, NULL}
7166         };
7167
7168         return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7169 }
7170
7171
7172 /**
7173  * List printers on a remote RPC server.
7174  *
7175  * @param c     A net_context structure.
7176  * @param argc  Standard main() style argc.
7177  * @param argv  Standard main() style argv. Initial components are already
7178  *              stripped.
7179  *
7180  * @return A shell status integer (0 for success).
7181  **/
7182 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7183 {
7184         if (c->display_usage) {
7185                 d_printf("Usage:\n"
7186                          "net rpc printer list\n"
7187                          "    List printers on a remote RPC server\n");
7188                 return 0;
7189         }
7190
7191         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7192                                rpc_printer_list_internals,
7193                                argc, argv);
7194 }
7195
7196 /**
7197  * List printer-drivers on a remote RPC server.
7198  *
7199  * @param c     A net_context structure.
7200  * @param argc  Standard main() style argc.
7201  * @param argv  Standard main() style argv. Initial components are already
7202  *              stripped.
7203  *
7204  * @return A shell status integer (0 for success).
7205  **/
7206 static int rpc_printer_driver_list(struct net_context *c, int argc,
7207                                    const char **argv)
7208 {
7209         if (c->display_usage) {
7210                 d_printf("Usage:\n"
7211                          "net rpc printer driver\n"
7212                          "    List printer-drivers on a remote RPC server\n");
7213                 return 0;
7214         }
7215
7216         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7217                                rpc_printer_driver_list_internals,
7218                                argc, argv);
7219 }
7220
7221 /**
7222  * Publish printer in ADS via MSRPC.
7223  *
7224  * @param c     A net_context structure.
7225  * @param argc  Standard main() style argc.
7226  * @param argv  Standard main() style argv. Initial components are already
7227  *              stripped.
7228  *
7229  * @return A shell status integer (0 for success).
7230  **/
7231 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7232                                        const char **argv)
7233 {
7234         if (c->display_usage) {
7235                 d_printf("Usage:\n"
7236                          "net rpc printer publish publish\n"
7237                          "     Publish printer in ADS via MSRPC\n");
7238                 return 0;
7239         }
7240
7241         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7242                                rpc_printer_publish_publish_internals,
7243                                argc, argv);
7244 }
7245
7246 /**
7247  * Update printer in ADS via MSRPC.
7248  *
7249  * @param c     A net_context structure.
7250  * @param argc  Standard main() style argc.
7251  * @param argv  Standard main() style argv. Initial components are already
7252  *              stripped.
7253  *
7254  * @return A shell status integer (0 for success).
7255  **/
7256 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7257 {
7258         if (c->display_usage) {
7259                 d_printf("Usage:\n"
7260                          "net rpc printer publish update\n"
7261                          "    Update printer in ADS via MSRPC\n");
7262                 return 0;
7263         }
7264
7265         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7266                                rpc_printer_publish_update_internals,
7267                                argc, argv);
7268 }
7269
7270 /**
7271  * UnPublish printer in ADS via MSRPC.
7272  *
7273  * @param c     A net_context structure.
7274  * @param argc  Standard main() style argc.
7275  * @param argv  Standard main() style argv. Initial components are already
7276  *              stripped.
7277  *
7278  * @return A shell status integer (0 for success).
7279  **/
7280 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7281                                          const char **argv)
7282 {
7283         if (c->display_usage) {
7284                 d_printf("Usage:\n"
7285                          "net rpc printer publish unpublish\n"
7286                          "    UnPublish printer in ADS via MSRPC\n");
7287                 return 0;
7288         }
7289
7290         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7291                                rpc_printer_publish_unpublish_internals,
7292                                argc, argv);
7293 }
7294
7295 /**
7296  * List published printers via MSRPC.
7297  *
7298  * @param c     A net_context structure.
7299  * @param argc  Standard main() style argc.
7300  * @param argv  Standard main() style argv. Initial components are already
7301  *              stripped.
7302  *
7303  * @return A shell status integer (0 for success).
7304  **/
7305 static int rpc_printer_publish_list(struct net_context *c, int argc,
7306                                     const char **argv)
7307 {
7308         if (c->display_usage) {
7309                 d_printf("Usage:\n"
7310                          "net rpc printer publish list\n"
7311                          "    List published printers via MSRPC\n");
7312                 return 0;
7313         }
7314
7315         return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7316                                rpc_printer_publish_list_internals,
7317                                argc, argv);
7318 }
7319
7320
7321 /**
7322  * Publish printer in ADS.
7323  *
7324  * @param c     A net_context structure.
7325  * @param argc  Standard main() style argc.
7326  * @param argv  Standard main() style argv. Initial components are already
7327  *              stripped.
7328  *
7329  * @return A shell status integer (0 for success).
7330  **/
7331 static int rpc_printer_publish(struct net_context *c, int argc,
7332                                const char **argv)
7333 {
7334
7335         struct functable func[] = {
7336                 {
7337                         "publish",
7338                         rpc_printer_publish_publish,
7339                         NET_TRANSPORT_RPC,
7340                         "Publish printer in AD",
7341                         "net rpc printer publish publish\n"
7342                         "    Publish printer in AD"
7343                 },
7344                 {
7345                         "update",
7346                         rpc_printer_publish_update,
7347                         NET_TRANSPORT_RPC,
7348                         "Update printer in AD",
7349                         "net rpc printer publish update\n"
7350                         "    Update printer in AD"
7351                 },
7352                 {
7353                         "unpublish",
7354                         rpc_printer_publish_unpublish,
7355                         NET_TRANSPORT_RPC,
7356                         "Unpublish printer",
7357                         "net rpc printer publish unpublish\n"
7358                         "    Unpublish printer"
7359                 },
7360                 {
7361                         "list",
7362                         rpc_printer_publish_list,
7363                         NET_TRANSPORT_RPC,
7364                         "List published printers",
7365                         "net rpc printer publish list\n"
7366                         "    List published printers"
7367                 },
7368                 {NULL, NULL, 0, NULL, NULL}
7369         };
7370
7371         if (argc == 0) {
7372                 if (c->display_usage) {
7373                         d_printf("Usage:\n");
7374                         d_printf("net rpc printer publish\n"
7375                                  "    List published printers\n"
7376                                  "    Alias of net rpc printer publish list\n");
7377                         net_display_usage_from_functable(func);
7378                         return 0;
7379                 }
7380                 return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7381                                rpc_printer_publish_list_internals,
7382                                argc, argv);
7383         }
7384
7385         return net_run_function(c, argc, argv, "net rpc printer publish",func);
7386
7387 }
7388
7389
7390 /**
7391  * Display rpc printer help page.
7392  *
7393  * @param c     A net_context structure.
7394  * @param argc  Standard main() style argc.
7395  * @param argv  Standard main() style argv. Initial components are already
7396  *              stripped.
7397  **/
7398 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
7399 {
7400         d_printf("net rpc printer LIST [printer] [misc. options] [targets]\n"
7401                  "\tlists all printers on print-server\n\n");
7402         d_printf("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
7403                  "\tlists all printer-drivers on print-server\n\n");
7404         d_printf("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
7405                  "\tpublishes printer settings in Active Directory\n"
7406                  "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n");
7407         d_printf("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
7408                  "\n\tmigrates printers from remote to local server\n\n");
7409         d_printf("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
7410                  "\n\tmigrates printer-settings from remote to local server\n\n");
7411         d_printf("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
7412                  "\n\tmigrates printer-drivers from remote to local server\n\n");
7413         d_printf("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
7414                  "\n\tmigrates printer-forms from remote to local server\n\n");
7415         d_printf("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
7416                  "\n\tmigrates printer-ACLs from remote to local server\n\n");
7417         d_printf("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
7418                  "\n\tmigrates drivers, forms, queues, settings and acls from\n"
7419                  "\tremote to local print-server\n\n");
7420         net_common_methods_usage(c, argc, argv);
7421         net_common_flags_usage(c, argc, argv);
7422         d_printf(
7423          "\t-v or --verbose\t\t\tgive verbose output\n"
7424          "\t      --destination\t\tmigration target server (default: localhost)\n");
7425
7426         return -1;
7427 }
7428
7429 /**
7430  * 'net rpc printer' entrypoint.
7431  *
7432  * @param c     A net_context structure.
7433  * @param argc  Standard main() style argc.
7434  * @param argv  Standard main() style argv. Initial components are already
7435  *              stripped.
7436  **/
7437 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7438 {
7439         struct functable func[] = {
7440                 {
7441                         "list",
7442                         rpc_printer_list,
7443                         NET_TRANSPORT_RPC,
7444                         "List all printers on print server",
7445                         "net rpc printer list\n"
7446                         "    List all printers on print server"
7447                 },
7448                 {
7449                         "migrate",
7450                         rpc_printer_migrate,
7451                         NET_TRANSPORT_RPC,
7452                         "Migrate printer to local server",
7453                         "net rpc printer migrate\n"
7454                         "    Migrate printer to local server"
7455                 },
7456                 {
7457                         "driver",
7458                         rpc_printer_driver_list,
7459                         NET_TRANSPORT_RPC,
7460                         "List printer drivers",
7461                         "net rpc printer driver\n"
7462                         "    List printer drivers"
7463                 },
7464                 {
7465                         "publish",
7466                         rpc_printer_publish,
7467                         NET_TRANSPORT_RPC,
7468                         "Publish printer in AD",
7469                         "net rpc printer publish\n"
7470                         "    Publish printer in AD"
7471                 },
7472                 {NULL, NULL, 0, NULL, NULL}
7473         };
7474
7475         if (argc == 0) {
7476                 if (c->display_usage) {
7477                         d_printf("Usage:\n");
7478                         d_printf("net rpc printer\n"
7479                                  "    List printers\n");
7480                         net_display_usage_from_functable(func);
7481                         return 0;
7482                 }
7483                 return run_rpc_command(c, NULL, PI_SPOOLSS, 0,
7484                                rpc_printer_list_internals,
7485                                argc, argv);
7486         }
7487
7488         return net_run_function(c, argc, argv, "net rpc printer", func);
7489 }
7490
7491 /**
7492  * 'net rpc' entrypoint.
7493  *
7494  * @param c     A net_context structure.
7495  * @param argc  Standard main() style argc.
7496  * @param argv  Standard main() style argv. Initial components are already
7497  *              stripped.
7498  **/
7499
7500 int net_rpc(struct net_context *c, int argc, const char **argv)
7501 {
7502         struct functable func[] = {
7503                 {
7504                         "audit",
7505                         net_rpc_audit,
7506                         NET_TRANSPORT_RPC,
7507                         "Modify global audit settings",
7508                         "net rpc audit\n"
7509                         "    Modify global audit settings"
7510                 },
7511                 {
7512                         "info",
7513                         net_rpc_info,
7514                         NET_TRANSPORT_RPC,
7515                         "Show basic info about a domain",
7516                         "net rpc info\n"
7517                         "    Show basic info about a domain"
7518                 },
7519                 {
7520                         "join",
7521                         net_rpc_join,
7522                         NET_TRANSPORT_RPC,
7523                         "Join a domain",
7524                         "net rpc join\n"
7525                         "    Join a domain"
7526                 },
7527                 {
7528                         "oldjoin",
7529                         net_rpc_oldjoin,
7530                         NET_TRANSPORT_RPC,
7531                         "Join a domain created in server manager",
7532                         "net rpc oldjoin\n"
7533                         "    Join a domain created in server manager"
7534                 },
7535                 {
7536                         "testjoin",
7537                         net_rpc_testjoin,
7538                         NET_TRANSPORT_RPC,
7539                         "Test that a join is valid",
7540                         "net rpc testjoin\n"
7541                         "    Test that a join is valid"
7542                 },
7543                 {
7544                         "user",
7545                         net_rpc_user,
7546                         NET_TRANSPORT_RPC,
7547                         "List/modify users",
7548                         "net rpc user\n"
7549                         "    List/modify users"
7550                 },
7551                 {
7552                         "password",
7553                         rpc_user_password,
7554                         NET_TRANSPORT_RPC,
7555                         "Change a user password",
7556                         "net rpc password\n"
7557                         "    Change a user password\n"
7558                         "    Alias for net rpc user password"
7559                 },
7560                 {
7561                         "group",
7562                         net_rpc_group,
7563                         NET_TRANSPORT_RPC,
7564                         "List/modify groups",
7565                         "net rpc group\n"
7566                         "    List/modify groups"
7567                 },
7568                 {
7569                         "share",
7570                         net_rpc_share,
7571                         NET_TRANSPORT_RPC,
7572                         "List/modify shares",
7573                         "net rpc share\n"
7574                         "    List/modify shares"
7575                 },
7576                 {
7577                         "file",
7578                         net_rpc_file,
7579                         NET_TRANSPORT_RPC,
7580                         "List open files",
7581                         "net rpc file\n"
7582                         "    List open files"
7583                 },
7584                 {
7585                         "printer",
7586                         net_rpc_printer,
7587                         NET_TRANSPORT_RPC,
7588                         "List/modify printers",
7589                         "net rpc printer\n"
7590                         "    List/modify printers"
7591                 },
7592                 {
7593                         "changetrustpw",
7594                         net_rpc_changetrustpw,
7595                         NET_TRANSPORT_RPC,
7596                         "Change trust account password",
7597                         "net rpc changetrustpw\n"
7598                         "    Change trust account password"
7599                 },
7600                 {
7601                         "trustdom",
7602                         rpc_trustdom,
7603                         NET_TRANSPORT_RPC,
7604                         "Modify domain trusts",
7605                         "net rpc trustdom\n"
7606                         "    Modify domain trusts"
7607                 },
7608                 {
7609                         "abortshutdown",
7610                         rpc_shutdown_abort,
7611                         NET_TRANSPORT_RPC,
7612                         "Abort a remote shutdown",
7613                         "net rpc abortshutdown\n"
7614                         "    Abort a remote shutdown"
7615                 },
7616                 {
7617                         "shutdown",
7618                         rpc_shutdown,
7619                         NET_TRANSPORT_RPC,
7620                         "Shutdown a remote server",
7621                         "net rpc shutdown\n"
7622                         "    Shutdown a remote server"
7623                 },
7624                 {
7625                         "samdump",
7626                         rpc_samdump,
7627                         NET_TRANSPORT_RPC,
7628                         "Dump SAM data of remote NT PDC",
7629                         "net rpc samdump\n"
7630                         "    Dump SAM data of remote NT PDC"
7631                 },
7632                 {
7633                         "vampire",
7634                         rpc_vampire,
7635                         NET_TRANSPORT_RPC,
7636                         "Sync a remote NT PDC's data into local passdb",
7637                         "net rpc vampire\n"
7638                         "    Sync a remote NT PDC's data into local passdb"
7639                 },
7640                 {
7641                         "getsid",
7642                         net_rpc_getsid,
7643                         NET_TRANSPORT_RPC,
7644                         "Fetch the domain sid into local secrets.tdb",
7645                         "net rpc getsid\n"
7646                         "    Fetch the domain sid into local secrets.tdb"
7647                 },
7648                 {
7649                         "rights",
7650                         net_rpc_rights,
7651                         NET_TRANSPORT_RPC,
7652                         "Manage privileges assigned to SID",
7653                         "net rpc rights\n"
7654                         "    Manage privileges assigned to SID"
7655                 },
7656                 {
7657                         "service",
7658                         net_rpc_service,
7659                         NET_TRANSPORT_RPC,
7660                         "Start/stop/query remote services",
7661                         "net rpc service\n"
7662                         "    Start/stop/query remote services"
7663                 },
7664                 {
7665                         "registry",
7666                         net_rpc_registry,
7667                         NET_TRANSPORT_RPC,
7668                         "Manage registry hives",
7669                         "net rpc registry\n"
7670                         "    Manage registry hives"
7671                 },
7672                 {
7673                         "shell",
7674                         net_rpc_shell,
7675                         NET_TRANSPORT_RPC,
7676                         "Open interactive shell on remote server",
7677                         "net rpc shell\n"
7678                         "    Open interactive shell on remote server"
7679                 },
7680                 {NULL, NULL, 0, NULL, NULL}
7681         };
7682         return net_run_function(c, argc, argv, "net rpc", func);
7683 }