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