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