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