merge from SAMBA_2_2
[Samba.git] / source / utils / net_rpc.c
blob471e41468348d6345909b00e86c17527af3cf70d
1 /*
2 Samba Unix/Linux SMB client library
3 Distributed SMB/CIFS Server Management Utility
4 Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20 #include "includes.h"
21 #include "../utils/net.h"
23 extern pstring global_myname;
25 /**
26 * @file net_rpc.c
28 * @brief RPC based subcommands for the 'net' utility.
30 * This file should contain much of the functionality that used to
31 * be found in rpcclient, execpt that the commands should change
32 * less often, and the fucntionality should be sane (the user is not
33 * expected to know a rid/sid before they conduct an operation etc.)
35 * @todo Perhaps eventually these should be split out into a number
36 * of files, as this could get quite big.
37 **/
40 /* A function of this type is passed to the 'run_rpc_command' wrapper */
41 typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, struct cli_state *, TALLOC_CTX *, int, const char **);
43 /**
44 * Many of the RPC functions need the domain sid. This function gets
45 * it at the start of every run
47 * @param cli A cli_state already connected to the remote machine
49 * @return The Domain SID of the remote machine.
50 **/
52 static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
54 DOM_SID *domain_sid;
55 POLICY_HND pol;
56 NTSTATUS result = NT_STATUS_OK;
57 uint32 info_class = 5;
58 fstring domain_name;
59 TALLOC_CTX *mem_ctx;
61 if (!(domain_sid = malloc(sizeof(DOM_SID)))){
62 DEBUG(0,("net_get_remote_domain_sid: malloc returned NULL!\n"));
63 goto error;
66 if (!(mem_ctx=talloc_init()))
68 DEBUG(0,("net_get_remote_domain_sid: talloc_init returned NULL!\n"));
69 goto error;
73 if (!cli_nt_session_open (cli, PIPE_LSARPC)) {
74 fprintf(stderr, "could not initialise lsa pipe\n");
75 goto error;
78 result = cli_lsa_open_policy(cli, mem_ctx, True,
79 SEC_RIGHTS_MAXIMUM_ALLOWED,
80 &pol);
81 if (!NT_STATUS_IS_OK(result)) {
82 goto error;
85 result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class,
86 domain_name, domain_sid);
87 if (!NT_STATUS_IS_OK(result)) {
88 goto error;
91 cli_lsa_close(cli, mem_ctx, &pol);
92 cli_nt_session_close(cli);
93 talloc_destroy(mem_ctx);
95 return domain_sid;
97 error:
98 fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
100 if (!NT_STATUS_IS_OK(result)) {
101 fprintf(stderr, "error: %s\n", nt_errstr(result));
104 exit(1);
108 * Run a single RPC command, from start to finish.
110 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
111 * @param conn_flag a NET_FLAG_ combination. Passed to
112 * net_make_ipc_connection.
113 * @param argc Standard main() style argc
114 * @param argc Standard main() style argv. Initial components are already
115 * stripped
116 * @return A shell status integer (0 for success)
119 static int run_rpc_command(const char *pipe_name, int conn_flags,
120 rpc_command_fn fn,
121 int argc, const char **argv)
123 struct cli_state *cli = net_make_ipc_connection(conn_flags);
124 TALLOC_CTX *mem_ctx;
125 NTSTATUS nt_status;
126 DOM_SID *domain_sid;
128 if (!cli) {
129 return -1;
132 domain_sid = net_get_remote_domain_sid(cli);
134 /* Create mem_ctx */
136 if (!(mem_ctx = talloc_init())) {
137 DEBUG(0, ("talloc_init() failed\n"));
138 cli_shutdown(cli);
139 return -1;
142 if (!cli_nt_session_open(cli, pipe_name)) {
143 DEBUG(0, ("Could not initialise samr pipe\n"));
146 nt_status = fn(domain_sid, cli, mem_ctx, argc, argv);
148 if (!NT_STATUS_IS_OK(nt_status)) {
149 DEBUG(0, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
150 } else {
151 DEBUG(5, ("rpc command function succedded\n"));
155 if (cli->nt_pipe_fnum)
156 cli_nt_session_close(cli);
158 talloc_destroy(mem_ctx);
160 return (!NT_STATUS_IS_OK(nt_status));
164 /****************************************************************************/
167 /**
168 * Force a change of the trust acccount password.
170 * All paramaters are provided by the run_rpc_command funcion, except for
171 * argc, argv which are passes through.
173 * @param domain_sid The domain sid aquired from the remote server
174 * @param cli A cli_state connected to the server.
175 * @param mem_ctx Talloc context, destoyed on compleation of the function.
176 * @param argc Standard main() style argc
177 * @param argc Standard main() style argv. Initial components are already
178 * stripped
180 * @return Normal NTSTATUS return.
183 static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
184 int argc, const char **argv) {
186 return trust_pw_find_change_and_store_it(cli, mem_ctx, opt_target_workgroup);
189 /**
190 * Force a change of the trust acccount password.
192 * @param argc Standard main() style argc
193 * @param argc Standard main() style argv. Initial components are already
194 * stripped
196 * @return A shell status integer (0 for success)
199 static int rpc_changetrustpw(int argc, const char **argv)
201 return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_changetrustpw_internals,
202 argc, argv);
206 /****************************************************************************/
209 /**
210 * Join a domain, the old way.
212 * This uses 'machinename' as the inital password, and changes it.
214 * The password should be created with 'server manager' or eqiv first.
216 * All paramaters are provided by the run_rpc_command funcion, except for
217 * argc, argv which are passes through.
219 * @param domain_sid The domain sid aquired from the remote server
220 * @param cli A cli_state connected to the server.
221 * @param mem_ctx Talloc context, destoyed on compleation of the function.
222 * @param argc Standard main() style argc
223 * @param argc Standard main() style argv. Initial components are already
224 * stripped
226 * @return Normal NTSTATUS return.
229 static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
230 int argc, const char **argv) {
232 extern pstring global_myname;
233 fstring trust_passwd;
234 unsigned char orig_trust_passwd_hash[16];
236 fstrcpy(trust_passwd, global_myname);
237 strlower(trust_passwd);
240 * Machine names can be 15 characters, but the max length on
241 * a password is 14. --jerry
244 trust_passwd[14] = '\0';
246 E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash);
248 return trust_pw_change_and_store_it(cli, mem_ctx, orig_trust_passwd_hash);
251 /**
252 * Join a domain, the old way.
254 * @param argc Standard main() style argc
255 * @param argc Standard main() style argv. Initial components are already
256 * stripped
258 * @return A shell status integer (0 for success)
261 static int net_rpc_join_oldstyle(int argc, const char **argv)
263 return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_join_oldstyle_internals,
264 argc, argv);
267 /**
268 * Basic usage function for 'net rpc join'
269 * @param argc Standard main() style argc
270 * @param argc Standard main() style argv. Initial components are already
271 * stripped
274 static int rpc_join_usage(int argc, const char **argv)
276 d_printf("net rpc join -U <username>[%%password] [options]\n"\
277 "\t to join a domain with admin username & password\n"\
278 "\t\t password will be prompted if none is specified\n");
279 d_printf("net rpc join [options except -U]\n"\
280 "\t to join a domain created in server manager\n\n\n");
282 net_common_flags_usage(argc, argv);
283 return -1;
286 /**
287 * 'net rpc join' entrypoint.
288 * @param argc Standard main() style argc
289 * @param argc Standard main() style argv. Initial components are already
290 * stripped
292 * Main 'net_rpc_join()' (where the admain username/password is used) is
293 * in net_rpc_join.c
294 * Assume if a -U is specified, it's the new style, otherwise it's the
295 * old style
298 int net_rpc_join(int argc, const char **argv)
300 if ((net_rpc_join_oldstyle(argc, argv) == 0))
301 return 0;
303 return net_rpc_join_newstyle(argc, argv);
307 /****************************************************************************/
310 * Basic usage function for 'net rpc user'
311 * @param argc Standard main() style argc.
312 * @param argv Standard main() style argv. Initial components are already
313 * stripped.
316 static int rpc_user_usage(int argc, const char **argv)
318 return net_help_user(argc, argv);
321 /**
322 * Add a new user to a remote RPC server
324 * All paramaters are provided by the run_rpc_command funcion, except for
325 * argc, argv which are passes through.
327 * @param domain_sid The domain sid acquired from the remote server
328 * @param cli A cli_state connected to the server.
329 * @param mem_ctx Talloc context, destoyed on completion of the function.
330 * @param argc Standard main() style argc
331 * @param argv Standard main() style argv. Initial components are already
332 * stripped
334 * @return Normal NTSTATUS return.
337 static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
338 int argc, const char **argv) {
340 POLICY_HND connect_pol, domain_pol, user_pol;
341 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
342 const char *acct_name;
343 uint16 acb_info;
344 uint32 unknown, user_rid;
346 if (argc != 1) {
347 d_printf("User must be specified\n");
348 rpc_user_usage(argc, argv);
349 return NT_STATUS_OK;
352 acct_name = argv[0];
354 /* Get sam policy handle */
356 result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
357 &connect_pol);
358 if (!NT_STATUS_IS_OK(result)) {
359 goto done;
362 /* Get domain policy handle */
364 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
365 MAXIMUM_ALLOWED_ACCESS,
366 domain_sid, &domain_pol);
367 if (!NT_STATUS_IS_OK(result)) {
368 goto done;
371 /* Create domain user */
373 acb_info = ACB_NORMAL;
374 unknown = 0xe005000b; /* No idea what this is - a permission mask? */
376 result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
377 acct_name, acb_info, unknown,
378 &user_pol, &user_rid);
379 if (!NT_STATUS_IS_OK(result)) {
380 goto done;
383 done:
384 if (!NT_STATUS_IS_OK(result)) {
385 d_printf("Failed to add user %s - %s\n", acct_name,
386 nt_errstr(result));
387 } else {
388 d_printf("Added user %s\n", acct_name);
390 return result;
393 /**
394 * Add a new user to a remote RPC server
396 * @param argc Standard main() style argc
397 * @param argv Standard main() style argv. Initial components are already
398 * stripped
400 * @return A shell status integer (0 for success)
403 static int rpc_user_add(int argc, const char **argv)
405 return run_rpc_command(PIPE_SAMR, 0, rpc_user_add_internals,
406 argc, argv);
409 /**
410 * Delete a user from a remote RPC server
412 * All paramaters are provided by the run_rpc_command funcion, except for
413 * argc, argv which are passes through.
415 * @param domain_sid The domain sid acquired from the remote server
416 * @param cli A cli_state connected to the server.
417 * @param mem_ctx Talloc context, destoyed on completion of the function.
418 * @param argc Standard main() style argc
419 * @param argv Standard main() style argv. Initial components are already
420 * stripped
422 * @return Normal NTSTATUS return.
425 static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
426 struct cli_state *cli,
427 TALLOC_CTX *mem_ctx,
428 int argc, const char **argv)
430 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
431 POLICY_HND connect_pol, domain_pol, user_pol;
433 if (argc < 1) {
434 d_printf("User must be specified\n");
435 rpc_user_usage(argc, argv);
436 return NT_STATUS_OK;
438 /* Get sam policy and domain handles */
440 result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
441 &connect_pol);
443 if (!NT_STATUS_IS_OK(result)) {
444 goto done;
447 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
448 MAXIMUM_ALLOWED_ACCESS,
449 domain_sid, &domain_pol);
451 if (!NT_STATUS_IS_OK(result)) {
452 goto done;
455 /* Get handle on user */
458 uint32 *user_rids, num_rids, *name_types;
459 uint32 flags = 0x000003e8; /* Unknown */
461 result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
462 flags, 1, &argv[0],
463 &num_rids, &user_rids,
464 &name_types);
466 if (!NT_STATUS_IS_OK(result)) {
467 goto done;
470 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
471 MAXIMUM_ALLOWED_ACCESS,
472 user_rids[0], &user_pol);
474 if (!NT_STATUS_IS_OK(result)) {
475 goto done;
479 /* Delete user */
481 result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
483 if (!NT_STATUS_IS_OK(result)) {
484 goto done;
487 /* Display results */
489 done:
490 return result;
494 /**
495 * Delete a user from a remote RPC server
497 * @param argc Standard main() style argc
498 * @param argv Standard main() style argv. Initial components are already
499 * stripped
501 * @return A shell status integer (0 for success)
504 static int rpc_user_delete(int argc, const char **argv)
506 return run_rpc_command(PIPE_SAMR, 0, rpc_user_del_internals,
507 argc, argv);
510 /**
511 * List user's groups on a remote RPC server
513 * All paramaters are provided by the run_rpc_command funcion, except for
514 * argc, argv which are passes through.
516 * @param domain_sid The domain sid acquired from the remote server
517 * @param cli A cli_state connected to the server.
518 * @param mem_ctx Talloc context, destoyed on completion of the function.
519 * @param argc Standard main() style argc
520 * @param argv Standard main() style argv. Initial components are already
521 * stripped
523 * @return Normal NTSTATUS return.
526 static NTSTATUS
527 rpc_user_info_internals(const DOM_SID *domain_sid, struct cli_state *cli,
528 TALLOC_CTX *mem_ctx, int argc, const char **argv)
530 POLICY_HND connect_pol, domain_pol, user_pol;
531 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
532 uint32 *rids, num_rids, *name_types, num_names;
533 uint32 flags = 0x000003e8; /* Unknown */
534 int i;
535 char **names;
536 DOM_GID *user_gids;
538 if (argc < 1) {
539 d_printf("User must be specified\n");
540 rpc_user_usage(argc, argv);
541 return NT_STATUS_OK;
543 /* Get sam policy handle */
545 result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
546 &connect_pol);
547 if (!NT_STATUS_IS_OK(result)) goto done;
549 /* Get domain policy handle */
551 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
552 MAXIMUM_ALLOWED_ACCESS,
553 domain_sid, &domain_pol);
554 if (!NT_STATUS_IS_OK(result)) goto done;
556 /* Get handle on user */
558 result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
559 flags, 1, &argv[0],
560 &num_rids, &rids, &name_types);
562 if (!NT_STATUS_IS_OK(result)) goto done;
564 result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
565 MAXIMUM_ALLOWED_ACCESS,
566 rids[0], &user_pol);
567 if (!NT_STATUS_IS_OK(result)) goto done;
569 result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
570 &num_rids, &user_gids);
572 /* Look up rids */
574 rids = (uint32 *)talloc(mem_ctx, sizeof(uint32) * num_rids);
576 for (i = 0; i < num_rids; i++)
577 rids[i] = user_gids[i].g_rid;
579 result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
580 flags, num_rids, rids,
581 &num_names, &names, &name_types);
583 if (!NT_STATUS_IS_OK(result)) {
584 goto done;
587 /* Display results */
589 for (i = 0; i < num_names; i++)
590 printf("%s\n", names[i]);
592 done:
593 return result;
596 /**
597 * List a user's groups from a remote RPC server
599 * @param argc Standard main() style argc
600 * @param argv Standard main() style argv. Initial components are already
601 * stripped
603 * @return A shell status integer (0 for success)
606 static int rpc_user_info(int argc, const char **argv)
608 return run_rpc_command(PIPE_SAMR, 0, rpc_user_info_internals,
609 argc, argv);
612 /**
613 * List users on a remote RPC server
615 * All paramaters are provided by the run_rpc_command funcion, except for
616 * argc, argv which are passes through.
618 * @param domain_sid The domain sid acquired from the remote server
619 * @param cli A cli_state connected to the server.
620 * @param mem_ctx Talloc context, destoyed on completion of the function.
621 * @param argc Standard main() style argc
622 * @param argv Standard main() style argv. Initial components are already
623 * stripped
625 * @return Normal NTSTATUS return.
628 static NTSTATUS
629 rpc_user_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
630 TALLOC_CTX *mem_ctx, int argc, const char **argv)
632 POLICY_HND connect_pol, domain_pol;
633 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
634 uint32 start_idx=0, max_entries=250, num_entries, i;
635 SAM_DISPINFO_CTR ctr;
636 SAM_DISPINFO_1 info1;
638 /* Get sam policy handle */
640 result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
641 &connect_pol);
642 if (!NT_STATUS_IS_OK(result)) {
643 goto done;
646 /* Get domain policy handle */
648 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
649 MAXIMUM_ALLOWED_ACCESS,
650 domain_sid, &domain_pol);
651 if (!NT_STATUS_IS_OK(result)) {
652 goto done;
655 /* Query domain users */
656 ZERO_STRUCT(ctr);
657 ZERO_STRUCT(info1);
658 ctr.sam.info1 = &info1;
659 if (opt_long_list_entries)
660 d_printf("\nUser name Comment"\
661 "\n-----------------------------\n");
662 do {
663 fstring user, desc;
664 result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
665 &start_idx, 1, &num_entries,
666 max_entries, &ctr);
667 for (i = 0; i < num_entries; i++) {
668 unistr2_to_ascii(user, &(&ctr.sam.info1->str[i])->uni_acct_name, sizeof(user)-1);
669 if (opt_long_list_entries)
670 unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1);
672 if (opt_long_list_entries)
673 printf("%-21.21s %-50.50s\n", user, desc);
674 else
675 printf("%s\n", user);
677 } while (!NT_STATUS_IS_OK(result));
679 done:
680 return result;
683 /**
684 * 'net rpc user' entrypoint.
685 * @param argc Standard main() style argc
686 * @param argc Standard main() style argv. Initial components are already
687 * stripped
690 int net_rpc_user(int argc, const char **argv)
692 struct functable func[] = {
693 {"add", rpc_user_add},
694 {"info", rpc_user_info},
695 {"delete", rpc_user_delete},
696 {NULL, NULL}
699 if (argc == 0) {
700 if (opt_long_list_entries) {
701 } else {
703 return run_rpc_command(PIPE_SAMR, 0,
704 rpc_user_list_internals,
705 argc, argv);
708 return net_run_function(argc, argv, func, rpc_user_usage);
712 /****************************************************************************/
715 * Basic usage function for 'net rpc group'
716 * @param argc Standard main() style argc.
717 * @param argv Standard main() style argv. Initial components are already
718 * stripped.
721 static int rpc_group_usage(int argc, const char **argv)
723 return net_help_group(argc, argv);
726 /**
727 * List groups on a remote RPC server
729 * All paramaters are provided by the run_rpc_command funcion, except for
730 * argc, argv which are passes through.
732 * @param domain_sid The domain sid acquired from the remote server
733 * @param cli A cli_state connected to the server.
734 * @param mem_ctx Talloc context, destoyed on completion of the function.
735 * @param argc Standard main() style argc
736 * @param argv Standard main() style argv. Initial components are already
737 * stripped
739 * @return Normal NTSTATUS return.
742 static NTSTATUS
743 rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli,
744 TALLOC_CTX *mem_ctx, int argc, const char **argv)
746 POLICY_HND connect_pol, domain_pol;
747 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
748 uint32 start_idx=0, max_entries=250, num_entries, i;
749 struct acct_info *groups;
750 DOM_SID global_sid_Builtin;
752 string_to_sid(&global_sid_Builtin, "S-1-5-32");
754 /* Get sam policy handle */
756 result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
757 &connect_pol);
758 if (!NT_STATUS_IS_OK(result)) {
759 goto done;
762 /* Get domain policy handle */
764 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
765 MAXIMUM_ALLOWED_ACCESS,
766 domain_sid, &domain_pol);
767 if (!NT_STATUS_IS_OK(result)) {
768 goto done;
771 /* Query domain groups */
772 if (opt_long_list_entries)
773 d_printf("\nGroup name Comment"\
774 "\n-----------------------------\n");
775 do {
776 result = cli_samr_enum_dom_groups(cli, mem_ctx, &domain_pol,
777 &start_idx, max_entries,
778 &groups, &num_entries);
780 for (i = 0; i < num_entries; i++) {
781 if (opt_long_list_entries)
782 printf("%-21.21s %-50.50s\n",
783 groups[i].acct_name,
784 groups[i].acct_desc);
785 else
786 printf("%-21.21s\n", groups[i].acct_name);
788 } while (!NT_STATUS_IS_OK(result));
789 /* query domain aliases */
790 do {
791 result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
792 &start_idx, max_entries,
793 &groups, &num_entries);
795 for (i = 0; i < num_entries; i++) {
796 if (opt_long_list_entries)
797 printf("%-21.21s %-50.50s\n",
798 groups[i].acct_name,
799 groups[i].acct_desc);
800 else
801 printf("%-21.21s\n", groups[i].acct_name);
803 } while (!NT_STATUS_IS_OK(result));
804 cli_samr_close(cli, mem_ctx, &domain_pol);
805 /* Get builtin policy handle */
807 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
808 MAXIMUM_ALLOWED_ACCESS,
809 &global_sid_Builtin, &domain_pol);
810 if (!NT_STATUS_IS_OK(result)) {
811 goto done;
813 /* query builtin aliases */
814 do {
815 result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
816 &start_idx, max_entries,
817 &groups, &num_entries);
819 for (i = 0; i < num_entries; i++) {
820 if (opt_long_list_entries)
821 printf("%-21.21s %-50.50s\n",
822 groups[i].acct_name,
823 groups[i].acct_desc);
824 else
825 printf("%s\n", groups[i].acct_name);
827 } while (!NT_STATUS_IS_OK(result));
829 done:
830 return result;
833 /**
834 * 'net rpc group' entrypoint.
835 * @param argc Standard main() style argc
836 * @param argc Standard main() style argv. Initial components are already
837 * stripped
840 int net_rpc_group(int argc, const char **argv)
842 struct functable func[] = {
843 #if 0
844 {"add", rpc_group_add},
845 {"delete", rpc_group_delete},
846 #endif
847 {NULL, NULL}
850 if (argc == 0) {
851 if (opt_long_list_entries) {
852 } else {
854 return run_rpc_command(PIPE_SAMR, 0,
855 rpc_group_list_internals,
856 argc, argv);
859 return net_run_function(argc, argv, func, rpc_group_usage);
863 /****************************************************************************/
867 /**
868 * ABORT the shutdown of a remote RPC Server
870 * All paramaters are provided by the run_rpc_command funcion, except for
871 * argc, argv which are passed through.
873 * @param domain_sid The domain sid aquired from the remote server
874 * @param cli A cli_state connected to the server.
875 * @param mem_ctx Talloc context, destoyed on compleation of the function.
876 * @param argc Standard main() style argc
877 * @param argc Standard main() style argv. Initial components are already
878 * stripped
880 * @return Normal NTSTATUS return.
883 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
884 int argc, const char **argv)
886 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
888 result = cli_reg_abort_shutdown(cli, mem_ctx);
890 if (NT_STATUS_IS_OK(result))
891 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
892 else
893 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
895 return result;
899 /**
900 * ABORT the Shut down of a remote RPC server
902 * @param argc Standard main() style argc
903 * @param argc Standard main() style argv. Initial components are already
904 * stripped
906 * @return A shell status integer (0 for success)
909 static int rpc_shutdown_abort(int argc, const char **argv)
911 return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_abort_internals,
912 argc, argv);
915 /**
916 * Shut down a remote RPC Server
918 * All paramaters are provided by the run_rpc_command funcion, except for
919 * argc, argv which are passes through.
921 * @param domain_sid The domain sid aquired from the remote server
922 * @param cli A cli_state connected to the server.
923 * @param mem_ctx Talloc context, destoyed on compleation of the function.
924 * @param argc Standard main() style argc
925 * @param argc Standard main() style argv. Initial components are already
926 * stripped
928 * @return Normal NTSTATUS return.
931 static NTSTATUS rpc_shutdown_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
932 int argc, const char **argv)
934 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
935 char *msg = "This machine will be shutdown shortly";
936 uint32 timeout = 20;
937 uint16 flgs = 0;
938 BOOL reboot = opt_reboot;
939 BOOL force = opt_force;
940 #if 0
941 poptContext pc;
942 int rc;
944 struct poptOption long_options[] = {
945 {"message", 'm', POPT_ARG_STRING, &msg},
946 {"timeout", 't', POPT_ARG_INT, &timeout},
947 {"reboot", 'r', POPT_ARG_NONE, &reboot},
948 {"force", 'f', POPT_ARG_NONE, &force},
949 { 0, 0, 0, 0}
952 pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
953 POPT_CONTEXT_KEEP_FIRST);
955 rc = poptGetNextOpt(pc);
957 if (rc < -1) {
958 /* an error occurred during option processing */
959 DEBUG(0, ("%s: %s\n",
960 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
961 poptStrerror(rc)));
962 return NT_STATUS_INVALID_PARAMETER;
964 #endif
965 if (reboot) {
966 flgs |= REG_REBOOT_ON_SHUTDOWN;
968 if (force) {
969 flgs |= REG_FORCE_SHUTDOWN;
971 if (opt_comment) {
972 msg = opt_comment;
974 if (opt_timeout) {
975 timeout = opt_timeout;
978 /* create an entry */
979 result = cli_reg_shutdown(cli, mem_ctx, msg, timeout, flgs);
981 if (NT_STATUS_IS_OK(result))
982 DEBUG(5,("Shutdown of remote machine succeeded\n"));
983 else
984 DEBUG(0,("Shutdown of remote machine failed!\n"));
986 return result;
989 /**
990 * Shut down a remote RPC server
992 * @param argc Standard main() style argc
993 * @param argc Standard main() style argv. Initial components are already
994 * stripped
996 * @return A shell status integer (0 for success)
999 static int rpc_shutdown(int argc, const char **argv)
1001 return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_internals,
1002 argc, argv);
1005 /***************************************************************************
1006 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
1008 ***************************************************************************/
1011 * Add interdomain trust account to the RPC server.
1012 * All parameters (except for argc and argv) are passed by run_rpc_command
1013 * function.
1015 * @param domain_sid The domain sid acquired from the server
1016 * @param cli A cli_state connected to the server.
1017 * @param mem_ctx Talloc context, destoyed on completion of the function.
1018 * @param argc Standard main() style argc
1019 * @param argc Standard main() style argv. Initial components are already
1020 * stripped
1022 * @return normal NTSTATUS return code
1025 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx,
1026 int argc, const char **argv) {
1028 POLICY_HND connect_pol, domain_pol, user_pol;
1029 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1030 char *acct_name;
1031 uint16 acb_info;
1032 uint32 unknown, user_rid;
1034 if (argc != 1) {
1035 d_printf("Usage: net rpc trustdom add <domain_name>\n");
1036 return NT_STATUS_INVALID_PARAMETER;
1040 * Make valid trusting domain account (ie. uppercased and with '$' appended)
1043 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
1044 return NT_STATUS_NO_MEMORY;
1047 strupper(acct_name);
1049 /* Get sam policy handle */
1051 result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
1052 &connect_pol);
1053 if (!NT_STATUS_IS_OK(result)) {
1054 goto done;
1057 /* Get domain policy handle */
1059 result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
1060 MAXIMUM_ALLOWED_ACCESS,
1061 domain_sid, &domain_pol);
1062 if (!NT_STATUS_IS_OK(result)) {
1063 goto done;
1066 /* Create trusting domain's account */
1068 acb_info = ACB_DOMTRUST;
1069 unknown = 0xe005000b; /* No idea what this is - a permission mask?
1070 Is it needed for interdomain account also ? */
1072 result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
1073 acct_name, acb_info, unknown,
1074 &user_pol, &user_rid);
1075 if (!NT_STATUS_IS_OK(result)) {
1076 goto done;
1079 done:
1080 SAFE_FREE(acct_name);
1081 return result;
1085 * Create interdomain trust account for a remote domain.
1087 * @param argc standard argc
1088 * @param argv standard argv without initial components
1090 * @return Integer status (0 means success)
1093 static int rpc_trustdom_add(int argc, const char **argv)
1095 return run_rpc_command(PIPE_SAMR, 0, rpc_trustdom_add_internals,
1096 argc, argv);
1101 * Delete interdomain trust account for a remote domain.
1103 * @param argc standard argc
1104 * @param argv standard argv without initial components
1106 * @return Integer status (0 means success)
1109 static int rpc_trustdom_del(int argc, const char **argv)
1111 d_printf("Sorry, not yet implemented.\n");
1112 return -1;
1117 * Establish trust relationship to a trusting domain.
1118 * Interdomain account must already be created on remote PDC.
1120 * @param argc standard argc
1121 * @param argv standard argv without initial components
1123 * @return Integer status (0 means success)
1126 extern char *opt_user_name;
1127 extern char *opt_password;
1129 static int rpc_trustdom_establish(int argc, const char **argv) {
1131 struct cli_state *cli;
1132 struct in_addr server_ip;
1133 POLICY_HND connect_hnd;
1134 TALLOC_CTX *mem_ctx;
1135 NTSTATUS nt_status;
1136 DOM_SID domain_sid;
1137 WKS_INFO_100 wks_info;
1139 char* domain_name;
1140 char* acct_name;
1141 fstring pdc_name;
1144 * Connect to \\server\ipc$ as 'our domain' account with password
1147 if (argc != 1) {
1148 d_printf("Usage: net rpc trustdom add <domain_name>\n");
1149 return -1;
1153 domain_name = smb_xstrdup(argv[0]);
1154 strupper(domain_name);
1156 asprintf(&acct_name, "%s$", lp_workgroup());
1157 strupper(acct_name);
1159 opt_user_name = (char*)malloc(strlen(acct_name) + 1);
1160 safe_strcpy(opt_user_name, acct_name, strlen(acct_name) + 1);
1162 /* find the domain controller */
1163 if (!net_find_dc(&server_ip, pdc_name, domain_name)) {
1164 DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name));
1165 return -1;
1168 /* connect to ipc$ as username/password */
1169 nt_status = connect_to_ipc(&cli, &server_ip, pdc_name);
1170 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
1172 /* Is it trusting domain account for sure ? */
1173 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
1174 nt_errstr(nt_status)));
1175 return -1;
1179 * Connect to \\server\ipc$ again (this time anonymously)
1182 nt_status = connect_to_ipc_anonymous(&cli, &server_ip, (char*)pdc_name);
1184 if (NT_STATUS_IS_ERR(nt_status)) {
1185 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
1186 domain_name, nt_errstr(nt_status)));
1190 * Use NetServerEnum2 to make sure we're talking to a proper server
1193 if (!cli_get_pdc_name(cli, domain_name, (char*)pdc_name)) {
1194 DEBUG(0, ("NetServerEnum2 error: Couldn't find primary domain controller\
1195 for domain %s\n", domain_name));
1199 * Call WksQueryInfo to check remote server's capabilities
1200 * FIXME:Is really necessary ? nt serv does this, but from samba's
1201 * point of view it doesn't seem to make the difference
1202 * IDEA: It may be used to get info about type of pdc we're talking to
1203 * (e.g. WinNT or Win2k)
1206 if (!cli_nt_session_open(cli, PIPE_WKSSVC)) {
1207 DEBUG(0, ("Couldn't not initialise wkssvc pipe\n"));
1208 return -1;
1211 /* TODO: convert this call from rpc_client/cli_wkssvc.c
1212 to cli_wks_query_info() in libsmb/cli_wkssvc.c
1213 UPDATE: already done :)
1216 if (!(mem_ctx = talloc_init())) {
1217 DEBUG(0, ("talloc_init() failed\n"));
1218 cli_shutdown(cli);
1219 return -1;
1222 nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info);
1224 if (NT_STATUS_IS_ERR(nt_status)) {
1225 DEBUG(0, ("WksQueryInfo call failed.\n"));
1226 return -1;
1229 if (cli->nt_pipe_fnum)
1230 cli_nt_session_close(cli);
1234 * Call LsaOpenPolicy and LsaQueryInfo
1237 if (!(mem_ctx = talloc_init())) {
1238 DEBUG(0, ("talloc_init() failed\n"));
1239 cli_shutdown(cli);
1240 return -1;
1243 if (!cli_nt_session_open(cli, PIPE_LSARPC)) {
1244 DEBUG(0, ("Could not initialise lsa pipe\n"));
1247 nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
1248 &connect_hnd);
1249 if (NT_STATUS_IS_ERR(nt_status)) {
1250 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
1251 nt_errstr(nt_status)));
1252 return -1;
1255 /* Querying info level 5 */
1257 nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
1258 5 /* info level */, domain_name, &domain_sid);
1259 if (NT_STATUS_IS_ERR(nt_status)) {
1260 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
1261 nt_errstr(nt_status)));
1262 return -1;
1266 /* There should be actually query info level 3 (following nt serv behaviour),
1267 but I still don't know if it's _really_ necessary */
1270 * Store the password in secrets db
1273 if (!secrets_store_trusted_domain_password(domain_name, wks_info.uni_lan_grp.buffer,
1274 wks_info.uni_lan_grp.uni_str_len, opt_password,
1275 domain_sid)) {
1276 DEBUG(0, ("Storing password for trusted domain failed.\n"));
1277 return -1;
1281 * Close the pipes and clean up
1284 nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
1285 if (NT_STATUS_IS_ERR(nt_status)) {
1286 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
1287 nt_errstr(nt_status)));
1288 return -1;
1291 if (cli->nt_pipe_fnum)
1292 cli_nt_session_close(cli);
1294 talloc_destroy(mem_ctx);
1296 DEBUG(0, ("Success!\n"));
1297 return 0;
1301 * Revoke trust relationship to the remote domain
1303 * @param argc standard argc
1304 * @param argv standard argv without initial components
1306 * @return Integer status (0 means success)
1309 static int rpc_trustdom_revoke(int argc, const char **argv) {
1311 char* domain_name;
1313 if (argc < 1) return -1;
1315 /* generate upper cased domain name */
1316 domain_name = smb_xstrdup(argv[0]);
1317 strupper(domain_name);
1319 /* delete password of the trust */
1320 if (!trusted_domain_password_delete(domain_name)) {
1321 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
1322 domain_name));
1323 return -1;
1326 return 0;
1330 * Usage for 'net rpc trustdom' command
1332 * @param argc standard argc
1333 * @param argv standard argv without inital components
1335 * @return Integer status returned to shell
1338 static int rpc_trustdom_usage(int argc, const char **argv) {
1339 d_printf(" net rpc trustdom add \t\t add trusting domain's account\n");
1340 d_printf(" net rpc trustdom del \t\t delete trusting domain's account\n");
1341 d_printf(" net rpc trustdom establish \t establish relationship to trusted domain\n");
1342 d_printf(" net rpc trustdom revoke \t abandon relationship to trusted domain\n");
1343 d_printf(" net rpc trustdom list \t show current interdomain trust relationships\n");
1344 return -1;
1349 * Entrypoint for 'net rpc trustdom' code
1351 * @param argc standard argc
1352 * @param argv standard argv without initial components
1354 * @return Integer status (0 means success)
1357 static int rpc_trustdom(int argc, const char **argv)
1359 struct functable func[] = {
1360 {"add", rpc_trustdom_add},
1361 {"del", rpc_trustdom_del},
1362 {"establish", rpc_trustdom_establish},
1363 {"revoke", rpc_trustdom_revoke},
1364 {"help", rpc_trustdom_usage},
1365 {NULL, NULL}
1368 if (argc == 0) {
1369 rpc_trustdom_usage(argc, argv);
1370 return -1;
1373 return (net_run_function(argc, argv, func, rpc_user_usage));
1377 * Check if a server will take rpc commands
1378 * @param flags Type of server to connect to (PDC, DMB, localhost)
1379 * if the host is not explicitly specified
1380 * @return BOOL (true means rpc supported)
1382 BOOL net_rpc_check(unsigned flags)
1384 struct cli_state cli;
1385 BOOL ret = False;
1386 struct in_addr server_ip;
1387 char *server_name = NULL;
1389 /* flags (i.e. server type) may depend on command */
1390 if (!net_find_server(flags, &server_ip, &server_name))
1391 goto done;
1393 ZERO_STRUCT(cli);
1394 if (cli_initialise(&cli) == False)
1395 return False;
1397 if (!cli_connect(&cli, server_name, &server_ip))
1398 goto done;
1399 if (!attempt_netbios_session_request(&cli, global_myname,
1400 server_name, &server_ip))
1401 goto done;
1402 if (!cli_negprot(&cli))
1403 goto done;
1404 if (cli.protocol < PROTOCOL_NT1)
1405 goto done;
1407 ret = True;
1408 done:
1409 cli_shutdown(&cli);
1410 return ret;
1414 /****************************************************************************/
1417 /**
1418 * Basic usage function for 'net rpc'
1419 * @param argc Standard main() style argc
1420 * @param argv Standard main() style argv. Initial components are already
1421 * stripped
1424 int net_rpc_usage(int argc, const char **argv)
1426 d_printf(" net rpc join \t\t\tto join a domain \n");
1427 d_printf(" net rpc user \t\t\tto add, delete and list users\n");
1428 d_printf(" net rpc changetrustpw \tto change the trust account password\n");
1429 d_printf(" net rpc trustdom \t\tto create trusting domain's account or establish trust\n");
1430 d_printf(" net rpc abortshutdown \tto to abort the shutdown of a remote server\n");
1431 d_printf(" net rpc shutdown \t\tto to shutdown a remote server\n");
1432 d_printf("\n");
1433 d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
1434 d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
1435 d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
1436 d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
1437 d_printf("\t-c or --comment=<message>\ttext message to display on impending shutdown\n");
1438 return -1;
1443 * Help function for 'net rpc'. Calls command specific help if requested
1444 * or displays usage of net rpc
1445 * @param argc Standard main() style argc
1446 * @param argv Standard main() style argv. Initial components are already
1447 * stripped
1450 int net_rpc_help(int argc, const char **argv)
1452 struct functable func[] = {
1453 {"join", rpc_join_usage},
1454 {"user", net_help_user},
1455 /*{"changetrustpw", rpc_changetrustpw_usage}, */
1456 {"trustdom", rpc_trustdom_usage},
1457 /*{"abortshutdown", rpc_shutdown_abort_usage},*/
1458 /*{"shutdown", rpc_shutdown_usage}, */
1459 {NULL, NULL}
1462 if (argc == 0) {
1463 net_rpc_usage(argc, argv);
1464 return -1;
1467 return (net_run_function(argc, argv, func, rpc_user_usage));
1471 /**
1472 * 'net rpc' entrypoint.
1473 * @param argc Standard main() style argc
1474 * @param argv Standard main() style argv. Initial components are already
1475 * stripped
1478 int net_rpc(int argc, const char **argv)
1480 struct functable func[] = {
1481 {"join", net_rpc_join},
1482 {"user", net_rpc_user},
1483 {"group", net_rpc_group},
1484 {"changetrustpw", rpc_changetrustpw},
1485 {"trustdom", rpc_trustdom},
1486 {"abortshutdown", rpc_shutdown_abort},
1487 {"shutdown", rpc_shutdown},
1488 {"help", net_rpc_help},
1489 {NULL, NULL}
1491 return net_run_function(argc, argv, func, net_rpc_usage);