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)
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.
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.
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/>. */
24 #include "utils/net.h"
26 static int net_mode_share;
27 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask);
32 * @brief RPC based subcommands for the 'net' utility.
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.)
39 * @todo Perhaps eventually these should be split out into a number
40 * of files, as this could get quite big.
45 * Many of the RPC functions need the domain sid. This function gets
46 * it at the start of every run
48 * @param cli A cli_state already connected to the remote machine
50 * @return The Domain SID of the remote machine.
53 NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
55 const char **domain_name)
57 struct rpc_pipe_client *lsa_pipe;
59 NTSTATUS result = NT_STATUS_OK;
60 union lsa_PolicyInformation *info = NULL;
62 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
64 if (!NT_STATUS_IS_OK(result)) {
65 d_fprintf(stderr, "Could not initialise lsa pipe\n");
69 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, false,
70 SEC_RIGHTS_MAXIMUM_ALLOWED,
72 if (!NT_STATUS_IS_OK(result)) {
73 d_fprintf(stderr, "open_policy failed: %s\n",
78 result = rpccli_lsa_QueryInfoPolicy(lsa_pipe, mem_ctx,
80 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
82 if (!NT_STATUS_IS_OK(result)) {
83 d_fprintf(stderr, "lsaquery failed: %s\n",
88 *domain_name = info->account_domain.name.string;
89 *domain_sid = info->account_domain.sid;
91 rpccli_lsa_Close(lsa_pipe, mem_ctx, &pol);
92 TALLOC_FREE(lsa_pipe);
98 * Run a single RPC command, from start to finish.
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
106 * @return A shell status integer (0 for success).
109 int run_rpc_command(struct net_context *c,
110 struct cli_state *cli_arg,
111 const struct ndr_syntax_id *interface,
117 struct cli_state *cli = NULL;
118 struct rpc_pipe_client *pipe_hnd = NULL;
122 const char *domain_name;
124 /* make use of cli_state handed over as an argument, if possible */
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)));
142 if (!(mem_ctx = talloc_init("run_rpc_command"))) {
143 DEBUG(0, ("talloc_init() failed\n"));
148 nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
150 if (!NT_STATUS_IS_OK(nt_status)) {
155 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
156 if (lp_client_schannel()
157 && (ndr_syntax_id_equal(interface,
158 &ndr_table_netlogon.syntax_id))) {
159 /* Always try and create an schannel netlogon pipe. */
160 nt_status = cli_rpc_pipe_open_schannel(
162 PIPE_AUTH_LEVEL_PRIVACY, domain_name,
164 if (!NT_STATUS_IS_OK(nt_status)) {
165 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
166 nt_errstr(nt_status) ));
171 if (conn_flags & NET_FLAGS_SEAL) {
172 nt_status = cli_rpc_pipe_open_ntlmssp(
174 PIPE_AUTH_LEVEL_PRIVACY,
175 lp_workgroup(), c->opt_user_name,
176 c->opt_password, &pipe_hnd);
178 nt_status = cli_rpc_pipe_open_noauth(
182 if (!NT_STATUS_IS_OK(nt_status)) {
183 DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
184 cli_get_pipe_name_from_iface(
185 debug_ctx(), cli, interface),
186 nt_errstr(nt_status) ));
193 nt_status = fn(c, domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
195 if (!NT_STATUS_IS_OK(nt_status)) {
196 DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
198 DEBUG(5, ("rpc command function succedded\n"));
201 if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
203 TALLOC_FREE(pipe_hnd);
207 /* close the connection only if it was opened here */
212 talloc_destroy(mem_ctx);
213 return (!NT_STATUS_IS_OK(nt_status));
217 * Force a change of the trust acccount password.
219 * All parameters are provided by the run_rpc_command function, except for
220 * argc, argv which are passed through.
222 * @param domain_sid The domain sid acquired from the remote server.
223 * @param cli A cli_state connected to the server.
224 * @param mem_ctx Talloc context, destroyed on completion of the function.
225 * @param argc Standard main() style argc.
226 * @param argv Standard main() style argv. Initial components are already
229 * @return Normal NTSTATUS return.
232 static NTSTATUS rpc_changetrustpw_internals(struct net_context *c,
233 const DOM_SID *domain_sid,
234 const char *domain_name,
235 struct cli_state *cli,
236 struct rpc_pipe_client *pipe_hnd,
242 return trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup);
246 * Force a change of the trust acccount password.
248 * @param argc Standard main() style argc.
249 * @param argv Standard main() style argv. Initial components are already
252 * @return A shell status integer (0 for success).
255 int net_rpc_changetrustpw(struct net_context *c, int argc, const char **argv)
257 if (c->display_usage) {
259 "net rpc changetrustpw\n"
260 " Change the machine trust password\n");
264 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
265 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
266 rpc_changetrustpw_internals,
271 * Join a domain, the old way.
273 * This uses 'machinename' as the inital password, and changes it.
275 * The password should be created with 'server manager' or equiv first.
277 * All parameters are provided by the run_rpc_command function, except for
278 * argc, argv which are passed through.
280 * @param domain_sid The domain sid acquired from the remote server.
281 * @param cli A cli_state connected to the server.
282 * @param mem_ctx Talloc context, destroyed on completion of the function.
283 * @param argc Standard main() style argc.
284 * @param argv Standard main() style argv. Initial components are already
287 * @return Normal NTSTATUS return.
290 static NTSTATUS rpc_oldjoin_internals(struct net_context *c,
291 const DOM_SID *domain_sid,
292 const char *domain_name,
293 struct cli_state *cli,
294 struct rpc_pipe_client *pipe_hnd,
300 fstring trust_passwd;
301 unsigned char orig_trust_passwd_hash[16];
303 uint32 sec_channel_type;
305 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
307 if (!NT_STATUS_IS_OK(result)) {
308 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
311 nt_errstr(result) ));
316 check what type of join - if the user want's to join as
317 a BDC, the server must agree that we are a BDC.
320 sec_channel_type = get_sec_channel_type(argv[0]);
322 sec_channel_type = get_sec_channel_type(NULL);
325 fstrcpy(trust_passwd, global_myname());
326 strlower_m(trust_passwd);
329 * Machine names can be 15 characters, but the max length on
330 * a password is 14. --jerry
333 trust_passwd[14] = '\0';
335 E_md4hash(trust_passwd, orig_trust_passwd_hash);
337 result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, c->opt_target_workgroup,
338 orig_trust_passwd_hash,
341 if (NT_STATUS_IS_OK(result))
342 printf("Joined domain %s.\n", c->opt_target_workgroup);
345 if (!secrets_store_domain_sid(c->opt_target_workgroup, domain_sid)) {
346 DEBUG(0, ("error storing domain sid for %s\n", c->opt_target_workgroup));
347 result = NT_STATUS_UNSUCCESSFUL;
354 * Join a domain, the old way.
356 * @param argc Standard main() style argc.
357 * @param argv Standard main() style argv. Initial components are already
360 * @return A shell status integer (0 for success).
363 static int net_rpc_perform_oldjoin(struct net_context *c, int argc, const char **argv)
365 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
366 NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
367 rpc_oldjoin_internals,
372 * Join a domain, the old way. This function exists to allow
373 * the message to be displayed when oldjoin was explicitly
374 * requested, but not when it was implied by "net rpc join".
376 * @param argc Standard main() style argc.
377 * @param argv Standard main() style argv. Initial components are already
380 * @return A shell status integer (0 for success).
383 static int net_rpc_oldjoin(struct net_context *c, int argc, const char **argv)
387 if (c->display_usage) {
390 " Join a domain the old way\n");
394 rc = net_rpc_perform_oldjoin(c, argc, argv);
397 d_fprintf(stderr, "Failed to join domain\n");
404 * 'net rpc join' entrypoint.
405 * @param argc Standard main() style argc.
406 * @param argv Standard main() style argv. Initial components are already
409 * Main 'net_rpc_join()' (where the admin username/password is used) is
411 * Try to just change the password, but if that doesn't work, use/prompt
412 * for a username/password.
415 int net_rpc_join(struct net_context *c, int argc, const char **argv)
417 if (c->display_usage) {
419 "net rpc join -U <username>[%%password] <type>\n"
421 " username\tName of the admin user"
422 " password\tPassword of the admin user, will "
423 "prompt if not specified\n"
424 " type\tCan be one of the following:\n"
425 "\t\tMEMBER\tJoin as member server (default)\n"
426 "\t\tBDC\tJoin as BDC\n"
427 "\t\tPDC\tJoin as PDC\n");
431 if (lp_server_role() == ROLE_STANDALONE) {
432 d_printf("cannot join as standalone machine\n");
436 if (strlen(global_myname()) > 15) {
437 d_printf("Our netbios name can be at most 15 chars long, "
438 "\"%s\" is %u chars long\n",
439 global_myname(), (unsigned int)strlen(global_myname()));
443 if ((net_rpc_perform_oldjoin(c, argc, argv) == 0))
446 return net_rpc_join_newstyle(c, argc, argv);
450 * display info about a rpc domain
452 * All parameters are provided by the run_rpc_command function, except for
453 * argc, argv which are passed through.
455 * @param domain_sid The domain sid acquired from the remote server
456 * @param cli A cli_state connected to the server.
457 * @param mem_ctx Talloc context, destroyed on completion of the function.
458 * @param argc Standard main() style argc.
459 * @param argv Standard main() style argv. Initial components are already
462 * @return Normal NTSTATUS return.
465 NTSTATUS rpc_info_internals(struct net_context *c,
466 const DOM_SID *domain_sid,
467 const char *domain_name,
468 struct cli_state *cli,
469 struct rpc_pipe_client *pipe_hnd,
474 POLICY_HND connect_pol, domain_pol;
475 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
476 union samr_DomainInfo *info = NULL;
479 sid_to_fstring(sid_str, domain_sid);
481 /* Get sam policy handle */
482 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
484 MAXIMUM_ALLOWED_ACCESS,
486 if (!NT_STATUS_IS_OK(result)) {
487 d_fprintf(stderr, "Could not connect to SAM: %s\n", nt_errstr(result));
491 /* Get domain policy handle */
492 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
494 MAXIMUM_ALLOWED_ACCESS,
495 CONST_DISCARD(struct dom_sid2 *, domain_sid),
497 if (!NT_STATUS_IS_OK(result)) {
498 d_fprintf(stderr, "Could not open domain: %s\n", nt_errstr(result));
502 result = rpccli_samr_QueryDomainInfo(pipe_hnd, mem_ctx,
506 if (NT_STATUS_IS_OK(result)) {
507 d_printf("Domain Name: %s\n", info->info2.domain_name.string);
508 d_printf("Domain SID: %s\n", sid_str);
509 d_printf("Sequence number: %llu\n",
510 (unsigned long long)info->info2.sequence_num);
511 d_printf("Num users: %u\n", info->info2.num_users);
512 d_printf("Num domain groups: %u\n", info->info2.num_groups);
513 d_printf("Num local groups: %u\n", info->info2.num_aliases);
521 * 'net rpc info' entrypoint.
522 * @param argc Standard main() style argc.
523 * @param argv Standard main() style argv. Initial components are already
527 int net_rpc_info(struct net_context *c, int argc, const char **argv)
529 if (c->display_usage) {
532 " Display information about the domain\n");
536 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
537 NET_FLAGS_PDC, rpc_info_internals,
542 * Fetch domain SID into the local secrets.tdb.
544 * All parameters are provided by the run_rpc_command function, except for
545 * argc, argv which are passed through.
547 * @param domain_sid The domain sid acquired from the remote server.
548 * @param cli A cli_state connected to the server.
549 * @param mem_ctx Talloc context, destroyed on completion of the function.
550 * @param argc Standard main() style argc.
551 * @param argv Standard main() style argv. Initial components are already
554 * @return Normal NTSTATUS return.
557 static NTSTATUS rpc_getsid_internals(struct net_context *c,
558 const DOM_SID *domain_sid,
559 const char *domain_name,
560 struct cli_state *cli,
561 struct rpc_pipe_client *pipe_hnd,
568 sid_to_fstring(sid_str, domain_sid);
569 d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
570 sid_str, domain_name);
572 if (!secrets_store_domain_sid(domain_name, domain_sid)) {
573 DEBUG(0,("Can't store domain SID\n"));
574 return NT_STATUS_UNSUCCESSFUL;
581 * 'net rpc getsid' entrypoint.
582 * @param argc Standard main() style argc.
583 * @param argv Standard main() style argv. Initial components are already
587 int net_rpc_getsid(struct net_context *c, int argc, const char **argv)
589 if (c->display_usage) {
592 " Fetch domain SID into local secrets.tdb\n");
596 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id,
597 NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC,
598 rpc_getsid_internals,
602 /****************************************************************************/
605 * Basic usage function for 'net rpc user'.
606 * @param argc Standard main() style argc.
607 * @param argv Standard main() style argv. Initial components are already
611 static int rpc_user_usage(struct net_context *c, int argc, const char **argv)
613 return net_user_usage(c, argc, argv);
617 * Add a new user to a remote RPC server.
619 * @param argc Standard main() style argc.
620 * @param argv Standard main() style argv. Initial components are already
623 * @return A shell status integer (0 for success).
626 static int rpc_user_add(struct net_context *c, int argc, const char **argv)
628 NET_API_STATUS status;
629 struct USER_INFO_1 info1;
630 uint32_t parm_error = 0;
632 if (argc < 1 || c->display_usage) {
633 rpc_user_usage(c, argc, argv);
639 info1.usri1_name = argv[0];
641 info1.usri1_password = argv[1];
644 status = NetUserAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
647 d_fprintf(stderr, "Failed to add user '%s' with: %s.\n",
648 argv[0], libnetapi_get_error_string(c->netapi_ctx,
652 d_printf("Added user '%s'.\n", argv[0]);
659 * Rename a user on a remote RPC server.
661 * @param argc Standard main() style argc.
662 * @param argv Standard main() style argv. Initial components are already
665 * @return A shell status integer (0 for success).
668 static int rpc_user_rename(struct net_context *c, int argc, const char **argv)
670 NET_API_STATUS status;
671 struct USER_INFO_0 u0;
672 uint32_t parm_err = 0;
674 if (argc != 2 || c->display_usage) {
675 rpc_user_usage(c, argc, argv);
679 u0.usri0_name = argv[1];
681 status = NetUserSetInfo(c->opt_host, argv[0],
682 0, (uint8_t *)&u0, &parm_err);
684 d_fprintf(stderr, "Failed to rename user from %s to %s - %s\n",
686 libnetapi_get_error_string(c->netapi_ctx, status));
688 d_printf("Renamed user from %s to %s\n", argv[0], argv[1]);
695 * Delete a user from a remote RPC server.
697 * @param argc Standard main() style argc.
698 * @param argv Standard main() style argv. Initial components are already
701 * @return A shell status integer (0 for success).
704 static int rpc_user_delete(struct net_context *c, int argc, const char **argv)
706 NET_API_STATUS status;
708 if (argc < 1 || c->display_usage) {
709 rpc_user_usage(c, argc, argv);
713 status = NetUserDel(c->opt_host, argv[0]);
716 d_fprintf(stderr, "Failed to delete user '%s' with: %s.\n",
718 libnetapi_get_error_string(c->netapi_ctx, status));
721 d_printf("Deleted user '%s'.\n", argv[0]);
728 * Set a password for a user on a remote RPC server.
730 * All parameters are provided by the run_rpc_command function, except for
731 * argc, argv which are passed through.
733 * @param domain_sid The domain sid acquired from the remote server.
734 * @param cli A cli_state connected to the server.
735 * @param mem_ctx Talloc context, destroyed on completion of the function.
736 * @param argc Standard main() style argc.
737 * @param argv Standard main() style argv. Initial components are already
740 * @return Normal NTSTATUS return.
743 static NTSTATUS rpc_user_password_internals(struct net_context *c,
744 const DOM_SID *domain_sid,
745 const char *domain_name,
746 struct cli_state *cli,
747 struct rpc_pipe_client *pipe_hnd,
752 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
753 POLICY_HND connect_pol, domain_pol, user_pol;
755 const char *new_password;
757 union samr_UserInfo info;
758 struct samr_CryptPassword crypt_pwd;
760 if (argc < 1 || c->display_usage) {
761 rpc_user_usage(c, argc, argv);
768 new_password = argv[1];
770 asprintf(&prompt, "Enter new password for %s:", user);
771 new_password = getpass(prompt);
775 /* Get sam policy and domain handles */
777 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
779 MAXIMUM_ALLOWED_ACCESS,
782 if (!NT_STATUS_IS_OK(result)) {
786 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
788 MAXIMUM_ALLOWED_ACCESS,
789 CONST_DISCARD(struct dom_sid2 *, domain_sid),
792 if (!NT_STATUS_IS_OK(result)) {
796 /* Get handle on user */
799 struct samr_Ids user_rids, name_types;
800 struct lsa_String lsa_acct_name;
802 init_lsa_String(&lsa_acct_name, user);
804 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
810 if (!NT_STATUS_IS_OK(result)) {
814 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
816 MAXIMUM_ALLOWED_ACCESS,
820 if (!NT_STATUS_IS_OK(result)) {
825 /* Set password on account */
827 init_samr_CryptPassword(new_password,
828 &cli->user_session_key,
831 init_samr_user_info24(&info.info24, crypt_pwd.data, 24);
833 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
838 if (!NT_STATUS_IS_OK(result)) {
842 /* Display results */
850 * Set a user's password on a remote RPC server.
852 * @param argc Standard main() style argc.
853 * @param argv Standard main() style argv. Initial components are already
856 * @return A shell status integer (0 for success).
859 static int rpc_user_password(struct net_context *c, int argc, const char **argv)
861 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
862 rpc_user_password_internals, argc, argv);
866 * List user's groups on a remote RPC server.
868 * All parameters are provided by the run_rpc_command function, except for
869 * argc, argv which are passed through.
871 * @param domain_sid The domain sid acquired from the remote server.
872 * @param cli A cli_state connected to the server.
873 * @param mem_ctx Talloc context, destroyed on completion of the function.
874 * @param argc Standard main() style argc.
875 * @param argv Standard main() style argv. Initial components are already
878 * @return Normal NTSTATUS return.
881 static NTSTATUS rpc_user_info_internals(struct net_context *c,
882 const DOM_SID *domain_sid,
883 const char *domain_name,
884 struct cli_state *cli,
885 struct rpc_pipe_client *pipe_hnd,
890 POLICY_HND connect_pol, domain_pol, user_pol;
891 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
893 struct samr_RidWithAttributeArray *rid_array = NULL;
894 struct lsa_Strings names;
895 struct samr_Ids types;
896 uint32_t *lrids = NULL;
897 struct samr_Ids rids, name_types;
898 struct lsa_String lsa_acct_name;
901 if (argc < 1 || c->display_usage) {
902 rpc_user_usage(c, argc, argv);
905 /* Get sam policy handle */
907 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
909 MAXIMUM_ALLOWED_ACCESS,
911 if (!NT_STATUS_IS_OK(result)) goto done;
913 /* Get domain policy handle */
915 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
917 MAXIMUM_ALLOWED_ACCESS,
918 CONST_DISCARD(struct dom_sid2 *, domain_sid),
920 if (!NT_STATUS_IS_OK(result)) goto done;
922 /* Get handle on user */
924 init_lsa_String(&lsa_acct_name, argv[0]);
926 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
933 if (!NT_STATUS_IS_OK(result)) goto done;
935 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
937 MAXIMUM_ALLOWED_ACCESS,
940 if (!NT_STATUS_IS_OK(result)) goto done;
942 result = rpccli_samr_GetGroupsForUser(pipe_hnd, mem_ctx,
946 if (!NT_STATUS_IS_OK(result)) goto done;
950 if (rid_array->count) {
951 if ((lrids = TALLOC_ARRAY(mem_ctx, uint32, rid_array->count)) == NULL) {
952 result = NT_STATUS_NO_MEMORY;
956 for (i = 0; i < rid_array->count; i++)
957 lrids[i] = rid_array->rids[i].rid;
959 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
966 if (!NT_STATUS_IS_OK(result)) {
970 /* Display results */
972 for (i = 0; i < names.count; i++)
973 printf("%s\n", names.names[i].string);
980 * List a user's groups from a remote RPC server.
982 * @param argc Standard main() style argc.
983 * @param argv Standard main() style argv. Initial components are already
986 * @return A shell status integer (0 for success)
989 static int rpc_user_info(struct net_context *c, int argc, const char **argv)
991 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
992 rpc_user_info_internals, argc, argv);
996 * List users on a remote RPC server.
998 * All parameters are provided by the run_rpc_command function, except for
999 * argc, argv which are passed through.
1001 * @param domain_sid The domain sid acquired from the remote server.
1002 * @param cli A cli_state connected to the server.
1003 * @param mem_ctx Talloc context, destroyed on completion of the function.
1004 * @param argc Standard main() style argc.
1005 * @param argv Standard main() style argv. Initial components are already
1008 * @return Normal NTSTATUS return.
1011 static NTSTATUS rpc_user_list_internals(struct net_context *c,
1012 const DOM_SID *domain_sid,
1013 const char *domain_name,
1014 struct cli_state *cli,
1015 struct rpc_pipe_client *pipe_hnd,
1016 TALLOC_CTX *mem_ctx,
1020 POLICY_HND connect_pol, domain_pol;
1021 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1022 uint32 start_idx=0, num_entries, i, loop_count = 0;
1024 /* Get sam policy handle */
1026 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1028 MAXIMUM_ALLOWED_ACCESS,
1030 if (!NT_STATUS_IS_OK(result)) {
1034 /* Get domain policy handle */
1036 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1038 MAXIMUM_ALLOWED_ACCESS,
1039 CONST_DISCARD(struct dom_sid2 *, domain_sid),
1041 if (!NT_STATUS_IS_OK(result)) {
1045 /* Query domain users */
1046 if (c->opt_long_list_entries)
1047 d_printf("\nUser name Comment"
1048 "\n-----------------------------\n");
1050 const char *user = NULL;
1051 const char *desc = NULL;
1052 uint32 max_entries, max_size;
1053 uint32_t total_size, returned_size;
1054 union samr_DispInfo info;
1056 get_query_dispinfo_params(
1057 loop_count, &max_entries, &max_size);
1059 result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
1069 start_idx += info.info1.count;
1070 num_entries = info.info1.count;
1072 for (i = 0; i < num_entries; i++) {
1073 user = info.info1.entries[i].account_name.string;
1074 if (c->opt_long_list_entries)
1075 desc = info.info1.entries[i].description.string;
1076 if (c->opt_long_list_entries)
1077 printf("%-21.21s %s\n", user, desc);
1079 printf("%s\n", user);
1081 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1088 * 'net rpc user' entrypoint.
1089 * @param argc Standard main() style argc.
1090 * @param argv Standard main() style argv. Initial components are already
1094 int net_rpc_user(struct net_context *c, int argc, const char **argv)
1096 NET_API_STATUS status;
1098 struct functable func[] = {
1103 "Add specified user",
1104 "net rpc user add\n"
1105 " Add specified user"
1111 "List domain groups of user",
1112 "net rpc user info\n"
1113 " Lis domain groups of user"
1119 "Remove specified user",
1120 "net rpc user delete\n"
1121 " Remove specified user"
1127 "Change user password",
1128 "net rpc user password\n"
1129 " Change user password"
1135 "Rename specified user",
1136 "net rpc user rename\n"
1137 " Rename specified user"
1139 {NULL, NULL, 0, NULL, NULL}
1142 status = libnetapi_init(&c->netapi_ctx);
1146 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
1147 libnetapi_set_password(c->netapi_ctx, c->opt_password);
1148 if (c->opt_kerberos) {
1149 libnetapi_set_use_kerberos(c->netapi_ctx);
1153 if (c->display_usage) {
1154 d_printf("Usage:\n");
1155 d_printf("net rpc user\n"
1156 " List all users\n");
1157 net_display_usage_from_functable(func);
1161 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1162 rpc_user_list_internals,
1166 return net_run_function(c, argc, argv, "net rpc user", func);
1169 static NTSTATUS rpc_sh_user_list(struct net_context *c,
1170 TALLOC_CTX *mem_ctx,
1171 struct rpc_sh_ctx *ctx,
1172 struct rpc_pipe_client *pipe_hnd,
1173 int argc, const char **argv)
1175 return rpc_user_list_internals(c, ctx->domain_sid, ctx->domain_name,
1176 ctx->cli, pipe_hnd, mem_ctx,
1180 static NTSTATUS rpc_sh_user_info(struct net_context *c,
1181 TALLOC_CTX *mem_ctx,
1182 struct rpc_sh_ctx *ctx,
1183 struct rpc_pipe_client *pipe_hnd,
1184 int argc, const char **argv)
1186 return rpc_user_info_internals(c, ctx->domain_sid, ctx->domain_name,
1187 ctx->cli, pipe_hnd, mem_ctx,
1191 static NTSTATUS rpc_sh_handle_user(struct net_context *c,
1192 TALLOC_CTX *mem_ctx,
1193 struct rpc_sh_ctx *ctx,
1194 struct rpc_pipe_client *pipe_hnd,
1195 int argc, const char **argv,
1197 struct net_context *c,
1198 TALLOC_CTX *mem_ctx,
1199 struct rpc_sh_ctx *ctx,
1200 struct rpc_pipe_client *pipe_hnd,
1201 POLICY_HND *user_hnd,
1202 int argc, const char **argv))
1204 POLICY_HND connect_pol, domain_pol, user_pol;
1205 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1208 enum lsa_SidType type;
1211 d_fprintf(stderr, "usage: %s <username>\n", ctx->whoami);
1212 return NT_STATUS_INVALID_PARAMETER;
1215 ZERO_STRUCT(connect_pol);
1216 ZERO_STRUCT(domain_pol);
1217 ZERO_STRUCT(user_pol);
1219 result = net_rpc_lookup_name(c, mem_ctx, rpc_pipe_np_smb_conn(pipe_hnd),
1220 argv[0], NULL, NULL, &sid, &type);
1221 if (!NT_STATUS_IS_OK(result)) {
1222 d_fprintf(stderr, "Could not lookup %s: %s\n", argv[0],
1227 if (type != SID_NAME_USER) {
1228 d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
1229 sid_type_lookup(type));
1230 result = NT_STATUS_NO_SUCH_USER;
1234 if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
1235 d_fprintf(stderr, "%s is not in our domain\n", argv[0]);
1236 result = NT_STATUS_NO_SUCH_USER;
1240 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1242 MAXIMUM_ALLOWED_ACCESS,
1244 if (!NT_STATUS_IS_OK(result)) {
1248 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1250 MAXIMUM_ALLOWED_ACCESS,
1253 if (!NT_STATUS_IS_OK(result)) {
1257 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1259 MAXIMUM_ALLOWED_ACCESS,
1262 if (!NT_STATUS_IS_OK(result)) {
1266 result = fn(c, mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
1269 if (is_valid_policy_hnd(&user_pol)) {
1270 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1272 if (is_valid_policy_hnd(&domain_pol)) {
1273 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
1275 if (is_valid_policy_hnd(&connect_pol)) {
1276 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1281 static NTSTATUS rpc_sh_user_show_internals(struct net_context *c,
1282 TALLOC_CTX *mem_ctx,
1283 struct rpc_sh_ctx *ctx,
1284 struct rpc_pipe_client *pipe_hnd,
1285 POLICY_HND *user_hnd,
1286 int argc, const char **argv)
1289 union samr_UserInfo *info = NULL;
1292 d_fprintf(stderr, "usage: %s show <username>\n", ctx->whoami);
1293 return NT_STATUS_INVALID_PARAMETER;
1296 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1300 if (!NT_STATUS_IS_OK(result)) {
1304 d_printf("user rid: %d, group rid: %d\n",
1306 info->info21.primary_gid);
1311 static NTSTATUS rpc_sh_user_show(struct net_context *c,
1312 TALLOC_CTX *mem_ctx,
1313 struct rpc_sh_ctx *ctx,
1314 struct rpc_pipe_client *pipe_hnd,
1315 int argc, const char **argv)
1317 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1318 rpc_sh_user_show_internals);
1321 #define FETCHSTR(name, rec) \
1322 do { if (strequal(ctx->thiscmd, name)) { \
1323 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1326 #define SETSTR(name, rec, flag) \
1327 do { if (strequal(ctx->thiscmd, name)) { \
1328 init_lsa_String(&(info->info21.rec), argv[0]); \
1329 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1332 static NTSTATUS rpc_sh_user_str_edit_internals(struct net_context *c,
1333 TALLOC_CTX *mem_ctx,
1334 struct rpc_sh_ctx *ctx,
1335 struct rpc_pipe_client *pipe_hnd,
1336 POLICY_HND *user_hnd,
1337 int argc, const char **argv)
1340 const char *username;
1341 const char *oldval = "";
1342 union samr_UserInfo *info = NULL;
1345 d_fprintf(stderr, "usage: %s <username> [new value|NULL]\n",
1347 return NT_STATUS_INVALID_PARAMETER;
1350 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1354 if (!NT_STATUS_IS_OK(result)) {
1358 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1360 FETCHSTR("fullname", full_name);
1361 FETCHSTR("homedir", home_directory);
1362 FETCHSTR("homedrive", home_drive);
1363 FETCHSTR("logonscript", logon_script);
1364 FETCHSTR("profilepath", profile_path);
1365 FETCHSTR("description", description);
1368 d_printf("%s's %s: [%s]\n", username, ctx->thiscmd, oldval);
1372 if (strcmp(argv[0], "NULL") == 0) {
1376 ZERO_STRUCT(info->info21);
1378 SETSTR("fullname", full_name, FULL_NAME);
1379 SETSTR("homedir", home_directory, HOME_DIRECTORY);
1380 SETSTR("homedrive", home_drive, HOME_DRIVE);
1381 SETSTR("logonscript", logon_script, LOGON_SCRIPT);
1382 SETSTR("profilepath", profile_path, PROFILE_PATH);
1383 SETSTR("description", description, DESCRIPTION);
1385 result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1390 d_printf("Set %s's %s from [%s] to [%s]\n", username,
1391 ctx->thiscmd, oldval, argv[0]);
1398 #define HANDLEFLG(name, rec) \
1399 do { if (strequal(ctx->thiscmd, name)) { \
1400 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1402 newflags = oldflags | ACB_##rec; \
1404 newflags = oldflags & ~ACB_##rec; \
1407 static NTSTATUS rpc_sh_user_str_edit(struct net_context *c,
1408 TALLOC_CTX *mem_ctx,
1409 struct rpc_sh_ctx *ctx,
1410 struct rpc_pipe_client *pipe_hnd,
1411 int argc, const char **argv)
1413 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1414 rpc_sh_user_str_edit_internals);
1417 static NTSTATUS rpc_sh_user_flag_edit_internals(struct net_context *c,
1418 TALLOC_CTX *mem_ctx,
1419 struct rpc_sh_ctx *ctx,
1420 struct rpc_pipe_client *pipe_hnd,
1421 POLICY_HND *user_hnd,
1422 int argc, const char **argv)
1425 const char *username;
1426 const char *oldval = "unknown";
1427 uint32 oldflags, newflags;
1429 union samr_UserInfo *info = NULL;
1432 ((argc == 1) && !strequal(argv[0], "yes") &&
1433 !strequal(argv[0], "no"))) {
1434 d_fprintf(stderr, "usage: %s <username> [yes|no]\n",
1436 return NT_STATUS_INVALID_PARAMETER;
1439 newval = strequal(argv[0], "yes");
1441 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1445 if (!NT_STATUS_IS_OK(result)) {
1449 username = talloc_strdup(mem_ctx, info->info21.account_name.string);
1450 oldflags = info->info21.acct_flags;
1451 newflags = info->info21.acct_flags;
1453 HANDLEFLG("disabled", DISABLED);
1454 HANDLEFLG("pwnotreq", PWNOTREQ);
1455 HANDLEFLG("autolock", AUTOLOCK);
1456 HANDLEFLG("pwnoexp", PWNOEXP);
1459 d_printf("%s's %s flag: %s\n", username, ctx->thiscmd, oldval);
1463 ZERO_STRUCT(info->info21);
1465 info->info21.acct_flags = newflags;
1466 info->info21.fields_present = SAMR_FIELD_ACCT_FLAGS;
1468 result = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
1473 if (NT_STATUS_IS_OK(result)) {
1474 d_printf("Set %s's %s flag from [%s] to [%s]\n", username,
1475 ctx->thiscmd, oldval, argv[0]);
1483 static NTSTATUS rpc_sh_user_flag_edit(struct net_context *c,
1484 TALLOC_CTX *mem_ctx,
1485 struct rpc_sh_ctx *ctx,
1486 struct rpc_pipe_client *pipe_hnd,
1487 int argc, const char **argv)
1489 return rpc_sh_handle_user(c, mem_ctx, ctx, pipe_hnd, argc, argv,
1490 rpc_sh_user_flag_edit_internals);
1493 struct rpc_sh_cmd *net_rpc_user_edit_cmds(struct net_context *c,
1494 TALLOC_CTX *mem_ctx,
1495 struct rpc_sh_ctx *ctx)
1497 static struct rpc_sh_cmd cmds[] = {
1499 { "fullname", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1500 "Show/Set a user's full name" },
1502 { "homedir", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1503 "Show/Set a user's home directory" },
1505 { "homedrive", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1506 "Show/Set a user's home drive" },
1508 { "logonscript", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1509 "Show/Set a user's logon script" },
1511 { "profilepath", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1512 "Show/Set a user's profile path" },
1514 { "description", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_str_edit,
1515 "Show/Set a user's description" },
1517 { "disabled", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1518 "Show/Set whether a user is disabled" },
1520 { "autolock", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1521 "Show/Set whether a user locked out" },
1523 { "pwnotreq", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1524 "Show/Set whether a user does not need a password" },
1526 { "pwnoexp", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_flag_edit,
1527 "Show/Set whether a user's password does not expire" },
1529 { NULL, NULL, 0, NULL, NULL }
1535 struct rpc_sh_cmd *net_rpc_user_cmds(struct net_context *c,
1536 TALLOC_CTX *mem_ctx,
1537 struct rpc_sh_ctx *ctx)
1539 static struct rpc_sh_cmd cmds[] = {
1541 { "list", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_list,
1542 "List available users" },
1544 { "info", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_info,
1545 "List the domain groups a user is member of" },
1547 { "show", NULL, &ndr_table_samr.syntax_id, rpc_sh_user_show,
1548 "Show info about a user" },
1550 { "edit", net_rpc_user_edit_cmds, 0, NULL,
1551 "Show/Modify a user's fields" },
1553 { NULL, NULL, 0, NULL, NULL }
1559 /****************************************************************************/
1562 * Basic usage function for 'net rpc group'.
1563 * @param argc Standard main() style argc.
1564 * @param argv Standard main() style argv. Initial components are already
1568 static int rpc_group_usage(struct net_context *c, int argc, const char **argv)
1570 return net_group_usage(c, argc, argv);
1574 * Delete group on a remote RPC server.
1576 * All parameters are provided by the run_rpc_command function, except for
1577 * argc, argv which are passed through.
1579 * @param domain_sid The domain sid acquired from the remote server.
1580 * @param cli A cli_state connected to the server.
1581 * @param mem_ctx Talloc context, destroyed on completion of the function.
1582 * @param argc Standard main() style argc.
1583 * @param argv Standard main() style argv. Initial components are already
1586 * @return Normal NTSTATUS return.
1589 static NTSTATUS rpc_group_delete_internals(struct net_context *c,
1590 const DOM_SID *domain_sid,
1591 const char *domain_name,
1592 struct cli_state *cli,
1593 struct rpc_pipe_client *pipe_hnd,
1594 TALLOC_CTX *mem_ctx,
1598 POLICY_HND connect_pol, domain_pol, group_pol, user_pol;
1599 bool group_is_primary = false;
1600 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1602 struct samr_RidTypeArray *rids = NULL;
1605 /* DOM_GID *user_gids; */
1607 struct samr_Ids group_rids, name_types;
1608 struct lsa_String lsa_acct_name;
1609 union samr_UserInfo *info = NULL;
1611 if (argc < 1 || c->display_usage) {
1612 rpc_group_usage(c, argc,argv);
1613 return NT_STATUS_OK; /* ok? */
1616 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1618 MAXIMUM_ALLOWED_ACCESS,
1621 if (!NT_STATUS_IS_OK(result)) {
1622 d_fprintf(stderr, "Request samr_Connect2 failed\n");
1626 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1628 MAXIMUM_ALLOWED_ACCESS,
1629 CONST_DISCARD(struct dom_sid2 *, domain_sid),
1632 if (!NT_STATUS_IS_OK(result)) {
1633 d_fprintf(stderr, "Request open_domain failed\n");
1637 init_lsa_String(&lsa_acct_name, argv[0]);
1639 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1645 if (!NT_STATUS_IS_OK(result)) {
1646 d_fprintf(stderr, "Lookup of '%s' failed\n",argv[0]);
1650 switch (name_types.ids[0])
1652 case SID_NAME_DOM_GRP:
1653 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1655 MAXIMUM_ALLOWED_ACCESS,
1658 if (!NT_STATUS_IS_OK(result)) {
1659 d_fprintf(stderr, "Request open_group failed");
1663 group_rid = group_rids.ids[0];
1665 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
1669 if (!NT_STATUS_IS_OK(result)) {
1670 d_fprintf(stderr, "Unable to query group members of %s",argv[0]);
1674 if (c->opt_verbose) {
1675 d_printf("Domain Group %s (rid: %d) has %d members\n",
1676 argv[0],group_rid, rids->count);
1679 /* Check if group is anyone's primary group */
1680 for (i = 0; i < rids->count; i++)
1682 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
1684 MAXIMUM_ALLOWED_ACCESS,
1688 if (!NT_STATUS_IS_OK(result)) {
1689 d_fprintf(stderr, "Unable to open group member %d\n",
1694 result = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
1699 if (!NT_STATUS_IS_OK(result)) {
1700 d_fprintf(stderr, "Unable to lookup userinfo for group member %d\n",
1705 if (info->info21.primary_gid == group_rid) {
1706 if (c->opt_verbose) {
1707 d_printf("Group is primary group of %s\n",
1708 info->info21.account_name.string);
1710 group_is_primary = true;
1713 rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
1716 if (group_is_primary) {
1717 d_fprintf(stderr, "Unable to delete group because some "
1718 "of it's members have it as primary group\n");
1719 result = NT_STATUS_MEMBERS_PRIMARY_GROUP;
1723 /* remove all group members */
1724 for (i = 0; i < rids->count; i++)
1727 d_printf("Remove group member %d...",
1729 result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
1733 if (NT_STATUS_IS_OK(result)) {
1738 d_printf("failed\n");
1743 result = rpccli_samr_DeleteDomainGroup(pipe_hnd, mem_ctx,
1747 /* removing a local group is easier... */
1748 case SID_NAME_ALIAS:
1749 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
1751 MAXIMUM_ALLOWED_ACCESS,
1755 if (!NT_STATUS_IS_OK(result)) {
1756 d_fprintf(stderr, "Request open_alias failed\n");
1760 result = rpccli_samr_DeleteDomAlias(pipe_hnd, mem_ctx,
1764 d_fprintf(stderr, "%s is of type %s. This command is only for deleting local or global groups\n",
1765 argv[0],sid_type_lookup(name_types.ids[0]));
1766 result = NT_STATUS_UNSUCCESSFUL;
1770 if (NT_STATUS_IS_OK(result)) {
1772 d_printf("Deleted %s '%s'\n",sid_type_lookup(name_types.ids[0]),argv[0]);
1774 d_fprintf(stderr, "Deleting of %s failed: %s\n",argv[0],
1775 get_friendly_nt_error_msg(result));
1783 static int rpc_group_delete(struct net_context *c, int argc, const char **argv)
1785 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
1786 rpc_group_delete_internals, argc,argv);
1789 static int rpc_group_add_internals(struct net_context *c, int argc, const char **argv)
1791 NET_API_STATUS status;
1792 struct GROUP_INFO_1 info1;
1793 uint32_t parm_error = 0;
1795 if (argc != 1 || c->display_usage) {
1796 rpc_group_usage(c, argc, argv);
1802 info1.grpi1_name = argv[0];
1803 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1804 info1.grpi1_comment = c->opt_comment;
1807 status = NetGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1810 d_fprintf(stderr, "Failed to add group '%s' with: %s.\n",
1811 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1815 d_printf("Added group '%s'.\n", argv[0]);
1821 static int rpc_alias_add_internals(struct net_context *c, int argc, const char **argv)
1823 NET_API_STATUS status;
1824 struct LOCALGROUP_INFO_1 info1;
1825 uint32_t parm_error = 0;
1827 if (argc != 1 || c->display_usage) {
1828 rpc_group_usage(c, argc, argv);
1834 info1.lgrpi1_name = argv[0];
1835 if (c->opt_comment && strlen(c->opt_comment) > 0) {
1836 info1.lgrpi1_comment = c->opt_comment;
1839 status = NetLocalGroupAdd(c->opt_host, 1, (uint8_t *)&info1, &parm_error);
1842 d_fprintf(stderr, "Failed to add alias '%s' with: %s.\n",
1843 argv[0], libnetapi_get_error_string(c->netapi_ctx,
1847 d_printf("Added alias '%s'.\n", argv[0]);
1853 static int rpc_group_add(struct net_context *c, int argc, const char **argv)
1855 if (c->opt_localgroup)
1856 return rpc_alias_add_internals(c, argc, argv);
1858 return rpc_group_add_internals(c, argc, argv);
1861 static NTSTATUS get_sid_from_name(struct cli_state *cli,
1862 TALLOC_CTX *mem_ctx,
1865 enum lsa_SidType *type)
1867 DOM_SID *sids = NULL;
1868 enum lsa_SidType *types = NULL;
1869 struct rpc_pipe_client *pipe_hnd;
1871 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
1873 result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
1875 if (!NT_STATUS_IS_OK(result)) {
1879 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, false,
1880 SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
1882 if (!NT_STATUS_IS_OK(result)) {
1886 result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
1887 &name, NULL, 1, &sids, &types);
1889 if (NT_STATUS_IS_OK(result)) {
1890 sid_copy(sid, &sids[0]);
1894 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
1898 TALLOC_FREE(pipe_hnd);
1901 if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
1903 /* Try as S-1-5-whatever */
1907 if (string_to_sid(&tmp_sid, name)) {
1908 sid_copy(sid, &tmp_sid);
1909 *type = SID_NAME_UNKNOWN;
1910 result = NT_STATUS_OK;
1917 static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
1918 TALLOC_CTX *mem_ctx,
1919 const DOM_SID *group_sid,
1922 POLICY_HND connect_pol, domain_pol;
1925 POLICY_HND group_pol;
1927 struct samr_Ids rids, rid_types;
1928 struct lsa_String lsa_acct_name;
1932 sid_copy(&sid, group_sid);
1934 if (!sid_split_rid(&sid, &group_rid)) {
1935 return NT_STATUS_UNSUCCESSFUL;
1938 /* Get sam policy handle */
1939 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
1941 MAXIMUM_ALLOWED_ACCESS,
1943 if (!NT_STATUS_IS_OK(result)) {
1947 /* Get domain policy handle */
1948 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
1950 MAXIMUM_ALLOWED_ACCESS,
1953 if (!NT_STATUS_IS_OK(result)) {
1957 init_lsa_String(&lsa_acct_name, member);
1959 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
1966 if (!NT_STATUS_IS_OK(result)) {
1967 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
1971 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
1973 MAXIMUM_ALLOWED_ACCESS,
1977 if (!NT_STATUS_IS_OK(result)) {
1981 result = rpccli_samr_AddGroupMember(pipe_hnd, mem_ctx,
1984 0x0005); /* unknown flags */
1987 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
1991 static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
1992 TALLOC_CTX *mem_ctx,
1993 const DOM_SID *alias_sid,
1996 POLICY_HND connect_pol, domain_pol;
1999 POLICY_HND alias_pol;
2002 enum lsa_SidType member_type;
2006 sid_copy(&sid, alias_sid);
2008 if (!sid_split_rid(&sid, &alias_rid)) {
2009 return NT_STATUS_UNSUCCESSFUL;
2012 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2013 member, &member_sid, &member_type);
2015 if (!NT_STATUS_IS_OK(result)) {
2016 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2020 /* Get sam policy handle */
2021 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2023 MAXIMUM_ALLOWED_ACCESS,
2025 if (!NT_STATUS_IS_OK(result)) {
2029 /* Get domain policy handle */
2030 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2032 MAXIMUM_ALLOWED_ACCESS,
2035 if (!NT_STATUS_IS_OK(result)) {
2039 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2041 MAXIMUM_ALLOWED_ACCESS,
2045 if (!NT_STATUS_IS_OK(result)) {
2049 result = rpccli_samr_AddAliasMember(pipe_hnd, mem_ctx,
2053 if (!NT_STATUS_IS_OK(result)) {
2058 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2062 static NTSTATUS rpc_group_addmem_internals(struct net_context *c,
2063 const DOM_SID *domain_sid,
2064 const char *domain_name,
2065 struct cli_state *cli,
2066 struct rpc_pipe_client *pipe_hnd,
2067 TALLOC_CTX *mem_ctx,
2072 enum lsa_SidType group_type;
2074 if (argc != 2 || c->display_usage) {
2076 "net rpc group addmem <group> <member>\n"
2077 " Add a member to a group\n"
2078 " group\tGroup to add member to\n"
2079 " member\tMember to add to group\n");
2080 return NT_STATUS_UNSUCCESSFUL;
2083 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2084 &group_sid, &group_type))) {
2085 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2086 return NT_STATUS_UNSUCCESSFUL;
2089 if (group_type == SID_NAME_DOM_GRP) {
2090 NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
2091 &group_sid, argv[1]);
2093 if (!NT_STATUS_IS_OK(result)) {
2094 d_fprintf(stderr, "Could not add %s to %s: %s\n",
2095 argv[1], argv[0], nt_errstr(result));
2100 if (group_type == SID_NAME_ALIAS) {
2101 NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
2102 &group_sid, argv[1]);
2104 if (!NT_STATUS_IS_OK(result)) {
2105 d_fprintf(stderr, "Could not add %s to %s: %s\n",
2106 argv[1], argv[0], nt_errstr(result));
2111 d_fprintf(stderr, "Can only add members to global or local groups "
2112 "which %s is not\n", argv[0]);
2114 return NT_STATUS_UNSUCCESSFUL;
2117 static int rpc_group_addmem(struct net_context *c, int argc, const char **argv)
2119 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2120 rpc_group_addmem_internals,
2124 static NTSTATUS rpc_del_groupmem(struct net_context *c,
2125 struct rpc_pipe_client *pipe_hnd,
2126 TALLOC_CTX *mem_ctx,
2127 const DOM_SID *group_sid,
2130 POLICY_HND connect_pol, domain_pol;
2133 POLICY_HND group_pol;
2135 struct samr_Ids rids, rid_types;
2136 struct lsa_String lsa_acct_name;
2140 sid_copy(&sid, group_sid);
2142 if (!sid_split_rid(&sid, &group_rid))
2143 return NT_STATUS_UNSUCCESSFUL;
2145 /* Get sam policy handle */
2146 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2148 MAXIMUM_ALLOWED_ACCESS,
2150 if (!NT_STATUS_IS_OK(result))
2153 /* Get domain policy handle */
2154 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2156 MAXIMUM_ALLOWED_ACCESS,
2159 if (!NT_STATUS_IS_OK(result))
2162 init_lsa_String(&lsa_acct_name, member);
2164 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2170 if (!NT_STATUS_IS_OK(result)) {
2171 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2175 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2177 MAXIMUM_ALLOWED_ACCESS,
2181 if (!NT_STATUS_IS_OK(result))
2184 result = rpccli_samr_DeleteGroupMember(pipe_hnd, mem_ctx,
2189 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2193 static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
2194 TALLOC_CTX *mem_ctx,
2195 const DOM_SID *alias_sid,
2198 POLICY_HND connect_pol, domain_pol;
2201 POLICY_HND alias_pol;
2204 enum lsa_SidType member_type;
2208 sid_copy(&sid, alias_sid);
2210 if (!sid_split_rid(&sid, &alias_rid))
2211 return NT_STATUS_UNSUCCESSFUL;
2213 result = get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd), mem_ctx,
2214 member, &member_sid, &member_type);
2216 if (!NT_STATUS_IS_OK(result)) {
2217 d_fprintf(stderr, "Could not lookup up group member %s\n", member);
2221 /* Get sam policy handle */
2222 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2224 MAXIMUM_ALLOWED_ACCESS,
2226 if (!NT_STATUS_IS_OK(result)) {
2230 /* Get domain policy handle */
2231 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2233 MAXIMUM_ALLOWED_ACCESS,
2236 if (!NT_STATUS_IS_OK(result)) {
2240 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2242 MAXIMUM_ALLOWED_ACCESS,
2246 if (!NT_STATUS_IS_OK(result))
2249 result = rpccli_samr_DeleteAliasMember(pipe_hnd, mem_ctx,
2253 if (!NT_STATUS_IS_OK(result))
2257 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
2261 static NTSTATUS rpc_group_delmem_internals(struct net_context *c,
2262 const DOM_SID *domain_sid,
2263 const char *domain_name,
2264 struct cli_state *cli,
2265 struct rpc_pipe_client *pipe_hnd,
2266 TALLOC_CTX *mem_ctx,
2271 enum lsa_SidType group_type;
2273 if (argc != 2 || c->display_usage) {
2275 "net rpc group delmem <group> <member>\n"
2276 " Delete a member from a group\n"
2277 " group\tGroup to delete member from\n"
2278 " member\tMember to delete from group\n");
2279 return NT_STATUS_UNSUCCESSFUL;
2282 if (!NT_STATUS_IS_OK(get_sid_from_name(cli, mem_ctx, argv[0],
2283 &group_sid, &group_type))) {
2284 d_fprintf(stderr, "Could not lookup group name %s\n", argv[0]);
2285 return NT_STATUS_UNSUCCESSFUL;
2288 if (group_type == SID_NAME_DOM_GRP) {
2289 NTSTATUS result = rpc_del_groupmem(c, pipe_hnd, mem_ctx,
2290 &group_sid, argv[1]);
2292 if (!NT_STATUS_IS_OK(result)) {
2293 d_fprintf(stderr, "Could not del %s from %s: %s\n",
2294 argv[1], argv[0], nt_errstr(result));
2299 if (group_type == SID_NAME_ALIAS) {
2300 NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx,
2301 &group_sid, argv[1]);
2303 if (!NT_STATUS_IS_OK(result)) {
2304 d_fprintf(stderr, "Could not del %s from %s: %s\n",
2305 argv[1], argv[0], nt_errstr(result));
2310 d_fprintf(stderr, "Can only delete members from global or local groups "
2311 "which %s is not\n", argv[0]);
2313 return NT_STATUS_UNSUCCESSFUL;
2316 static int rpc_group_delmem(struct net_context *c, int argc, const char **argv)
2318 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2319 rpc_group_delmem_internals,
2324 * List groups on a remote RPC server.
2326 * All parameters are provided by the run_rpc_command function, except for
2327 * argc, argv which are passes through.
2329 * @param domain_sid The domain sid acquired from the remote server.
2330 * @param cli A cli_state connected to the server.
2331 * @param mem_ctx Talloc context, destroyed on completion of the function.
2332 * @param argc Standard main() style argc.
2333 * @param argv Standard main() style argv. Initial components are already
2336 * @return Normal NTSTATUS return.
2339 static NTSTATUS rpc_group_list_internals(struct net_context *c,
2340 const DOM_SID *domain_sid,
2341 const char *domain_name,
2342 struct cli_state *cli,
2343 struct rpc_pipe_client *pipe_hnd,
2344 TALLOC_CTX *mem_ctx,
2348 POLICY_HND connect_pol, domain_pol;
2349 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
2350 uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0;
2351 struct samr_SamArray *groups = NULL;
2352 bool global = false;
2354 bool builtin = false;
2356 if (c->display_usage) {
2358 "net rpc group list [global] [local] [builtin]\n"
2359 " List groups on RPC server\n"
2360 " global\tList global groups\n"
2361 " local\tList local groups\n"
2362 " builtin\tList builtin groups\n"
2363 " If none of global, local or builtin is "
2364 "specified, all three options are considered set\n");
2365 return NT_STATUS_OK;
2374 for (i=0; i<argc; i++) {
2375 if (strequal(argv[i], "global"))
2378 if (strequal(argv[i], "local"))
2381 if (strequal(argv[i], "builtin"))
2385 /* Get sam policy handle */
2387 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2389 MAXIMUM_ALLOWED_ACCESS,
2391 if (!NT_STATUS_IS_OK(result)) {
2395 /* Get domain policy handle */
2397 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2399 MAXIMUM_ALLOWED_ACCESS,
2400 CONST_DISCARD(struct dom_sid2 *, domain_sid),
2402 if (!NT_STATUS_IS_OK(result)) {
2406 /* Query domain groups */
2407 if (c->opt_long_list_entries)
2408 d_printf("\nGroup name Comment"
2409 "\n-----------------------------\n");
2411 uint32_t max_size, total_size, returned_size;
2412 union samr_DispInfo info;
2416 get_query_dispinfo_params(
2417 loop_count, &max_entries, &max_size);
2419 result = rpccli_samr_QueryDisplayInfo(pipe_hnd, mem_ctx,
2428 num_entries = info.info3.count;
2429 start_idx += info.info3.count;
2431 if (!NT_STATUS_IS_OK(result) &&
2432 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2435 for (i = 0; i < num_entries; i++) {
2437 const char *group = NULL;
2438 const char *desc = NULL;
2440 group = info.info3.entries[i].account_name.string;
2441 desc = info.info3.entries[i].description.string;
2443 if (c->opt_long_list_entries)
2444 printf("%-21.21s %-50.50s\n",
2447 printf("%s\n", group);
2449 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2450 /* query domain aliases */
2455 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2461 if (!NT_STATUS_IS_OK(result) &&
2462 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2465 for (i = 0; i < num_entries; i++) {
2467 const char *description = NULL;
2469 if (c->opt_long_list_entries) {
2471 POLICY_HND alias_pol;
2472 union samr_AliasInfo *info = NULL;
2474 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2477 groups->entries[i].idx,
2479 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2483 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2485 description = info->description.string;
2489 if (description != NULL) {
2490 printf("%-21.21s %-50.50s\n",
2491 groups->entries[i].name.string,
2494 printf("%s\n", groups->entries[i].name.string);
2497 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2498 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2499 /* Get builtin policy handle */
2501 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2503 MAXIMUM_ALLOWED_ACCESS,
2504 CONST_DISCARD(struct dom_sid2 *, &global_sid_Builtin),
2506 if (!NT_STATUS_IS_OK(result)) {
2509 /* query builtin aliases */
2512 if (!builtin) break;
2514 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
2520 if (!NT_STATUS_IS_OK(result) &&
2521 !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES))
2524 for (i = 0; i < num_entries; i++) {
2526 const char *description = NULL;
2528 if (c->opt_long_list_entries) {
2530 POLICY_HND alias_pol;
2531 union samr_AliasInfo *info = NULL;
2533 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2536 groups->entries[i].idx,
2538 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd, mem_ctx,
2542 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd, mem_ctx,
2544 description = info->description.string;
2548 if (description != NULL) {
2549 printf("%-21.21s %-50.50s\n",
2550 groups->entries[i].name.string,
2553 printf("%s\n", groups->entries[i].name.string);
2556 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
2562 static int rpc_group_list(struct net_context *c, int argc, const char **argv)
2564 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2565 rpc_group_list_internals,
2569 static NTSTATUS rpc_list_group_members(struct net_context *c,
2570 struct rpc_pipe_client *pipe_hnd,
2571 TALLOC_CTX *mem_ctx,
2572 const char *domain_name,
2573 const DOM_SID *domain_sid,
2574 POLICY_HND *domain_pol,
2578 POLICY_HND group_pol;
2579 uint32 num_members, *group_rids;
2581 struct samr_RidTypeArray *rids = NULL;
2582 struct lsa_Strings names;
2583 struct samr_Ids types;
2586 sid_to_fstring(sid_str, domain_sid);
2588 result = rpccli_samr_OpenGroup(pipe_hnd, mem_ctx,
2590 MAXIMUM_ALLOWED_ACCESS,
2594 if (!NT_STATUS_IS_OK(result))
2597 result = rpccli_samr_QueryGroupMember(pipe_hnd, mem_ctx,
2601 if (!NT_STATUS_IS_OK(result))
2604 num_members = rids->count;
2605 group_rids = rids->rids;
2607 while (num_members > 0) {
2608 int this_time = 512;
2610 if (num_members < this_time)
2611 this_time = num_members;
2613 result = rpccli_samr_LookupRids(pipe_hnd, mem_ctx,
2620 if (!NT_STATUS_IS_OK(result))
2623 /* We only have users as members, but make the output
2624 the same as the output of alias members */
2626 for (i = 0; i < this_time; i++) {
2628 if (c->opt_long_list_entries) {
2629 printf("%s-%d %s\\%s %d\n", sid_str,
2630 group_rids[i], domain_name,
2631 names.names[i].string,
2634 printf("%s\\%s\n", domain_name,
2635 names.names[i].string);
2639 num_members -= this_time;
2643 return NT_STATUS_OK;
2646 static NTSTATUS rpc_list_alias_members(struct net_context *c,
2647 struct rpc_pipe_client *pipe_hnd,
2648 TALLOC_CTX *mem_ctx,
2649 POLICY_HND *domain_pol,
2653 struct rpc_pipe_client *lsa_pipe;
2654 POLICY_HND alias_pol, lsa_pol;
2656 DOM_SID *alias_sids;
2659 enum lsa_SidType *types;
2661 struct lsa_SidArray sid_array;
2663 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
2665 MAXIMUM_ALLOWED_ACCESS,
2669 if (!NT_STATUS_IS_OK(result))
2672 result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
2676 if (!NT_STATUS_IS_OK(result)) {
2677 d_fprintf(stderr, "Couldn't list alias members\n");
2681 num_members = sid_array.num_sids;
2683 if (num_members == 0) {
2684 return NT_STATUS_OK;
2687 result = cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd),
2688 &ndr_table_lsarpc.syntax_id,
2690 if (!NT_STATUS_IS_OK(result)) {
2691 d_fprintf(stderr, "Couldn't open LSA pipe. Error was %s\n",
2692 nt_errstr(result) );
2696 result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, true,
2697 SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
2699 if (!NT_STATUS_IS_OK(result)) {
2700 d_fprintf(stderr, "Couldn't open LSA policy handle\n");
2701 TALLOC_FREE(lsa_pipe);
2705 alias_sids = TALLOC_ZERO_ARRAY(mem_ctx, DOM_SID, num_members);
2707 d_fprintf(stderr, "Out of memory\n");
2708 TALLOC_FREE(lsa_pipe);
2709 return NT_STATUS_NO_MEMORY;
2712 for (i=0; i<num_members; i++) {
2713 sid_copy(&alias_sids[i], sid_array.sids[i].sid);
2716 result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol,
2717 num_members, alias_sids,
2718 &domains, &names, &types);
2720 if (!NT_STATUS_IS_OK(result) &&
2721 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
2722 d_fprintf(stderr, "Couldn't lookup SIDs\n");
2723 TALLOC_FREE(lsa_pipe);
2727 for (i = 0; i < num_members; i++) {
2729 sid_to_fstring(sid_str, &alias_sids[i]);
2731 if (c->opt_long_list_entries) {
2732 printf("%s %s\\%s %d\n", sid_str,
2733 domains[i] ? domains[i] : "*unknown*",
2734 names[i] ? names[i] : "*unknown*", types[i]);
2737 printf("%s\\%s\n", domains[i], names[i]);
2739 printf("%s\n", sid_str);
2743 TALLOC_FREE(lsa_pipe);
2744 return NT_STATUS_OK;
2747 static NTSTATUS rpc_group_members_internals(struct net_context *c,
2748 const DOM_SID *domain_sid,
2749 const char *domain_name,
2750 struct cli_state *cli,
2751 struct rpc_pipe_client *pipe_hnd,
2752 TALLOC_CTX *mem_ctx,
2757 POLICY_HND connect_pol, domain_pol;
2758 struct samr_Ids rids, rid_types;
2759 struct lsa_String lsa_acct_name;
2761 /* Get sam policy handle */
2763 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
2765 MAXIMUM_ALLOWED_ACCESS,
2768 if (!NT_STATUS_IS_OK(result))
2771 /* Get domain policy handle */
2773 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2775 MAXIMUM_ALLOWED_ACCESS,
2776 CONST_DISCARD(struct dom_sid2 *, domain_sid),
2779 if (!NT_STATUS_IS_OK(result))
2782 init_lsa_String(&lsa_acct_name, argv[0]); /* sure? */
2784 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2791 if (!NT_STATUS_IS_OK(result)) {
2793 /* Ok, did not find it in the global sam, try with builtin */
2795 DOM_SID sid_Builtin;
2797 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
2799 sid_copy(&sid_Builtin, &global_sid_Builtin);
2801 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
2803 MAXIMUM_ALLOWED_ACCESS,
2807 if (!NT_STATUS_IS_OK(result)) {
2808 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2812 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
2819 if (!NT_STATUS_IS_OK(result)) {
2820 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2825 if (rids.count != 1) {
2826 d_fprintf(stderr, "Couldn't find group %s\n", argv[0]);
2830 if (rid_types.ids[0] == SID_NAME_DOM_GRP) {
2831 return rpc_list_group_members(c, pipe_hnd, mem_ctx, domain_name,
2832 domain_sid, &domain_pol,
2836 if (rid_types.ids[0] == SID_NAME_ALIAS) {
2837 return rpc_list_alias_members(c, pipe_hnd, mem_ctx, &domain_pol,
2841 return NT_STATUS_NO_SUCH_GROUP;
2844 static int rpc_group_members(struct net_context *c, int argc, const char **argv)
2846 if (argc != 1 || c->display_usage) {
2847 return rpc_group_usage(c, argc, argv);
2850 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2851 rpc_group_members_internals,
2855 static int rpc_group_rename_internals(struct net_context *c, int argc, const char **argv)
2857 NET_API_STATUS status;
2858 struct GROUP_INFO_0 g0;
2862 d_printf("Usage: 'net rpc group rename group newname'\n");
2866 g0.grpi0_name = argv[1];
2868 status = NetGroupSetInfo(c->opt_host,
2875 d_fprintf(stderr, "Renaming group %s failed with: %s\n",
2876 argv[0], libnetapi_get_error_string(c->netapi_ctx,
2884 static int rpc_group_rename(struct net_context *c, int argc, const char **argv)
2886 if (argc != 2 || c->display_usage) {
2887 return rpc_group_usage(c, argc, argv);
2890 return rpc_group_rename_internals(c, argc, argv);
2894 * 'net rpc group' entrypoint.
2895 * @param argc Standard main() style argc.
2896 * @param argv Standard main() style argv. Initial components are already
2900 int net_rpc_group(struct net_context *c, int argc, const char **argv)
2902 NET_API_STATUS status;
2904 struct functable func[] = {
2909 "Create specified group",
2910 "net rpc group add\n"
2911 " Create specified group"
2917 "Delete specified group",
2918 "net rpc group delete\n"
2919 " Delete specified group"
2925 "Add member to group",
2926 "net rpc group addmem\n"
2927 " Add member to group"
2933 "Remove member from group",
2934 "net rpc group delmem\n"
2935 " Remove member from group"
2942 "net rpc group list\n"
2949 "List group members",
2950 "net rpc group members\n"
2951 " List group members"
2958 "net rpc group rename\n"
2961 {NULL, NULL, 0, NULL, NULL}
2964 status = libnetapi_init(&c->netapi_ctx);
2968 libnetapi_set_username(c->netapi_ctx, c->opt_user_name);
2969 libnetapi_set_password(c->netapi_ctx, c->opt_password);
2970 if (c->opt_kerberos) {
2971 libnetapi_set_use_kerberos(c->netapi_ctx);
2975 if (c->display_usage) {
2976 d_printf("Usage:\n");
2977 d_printf("net rpc group\n"
2978 " Alias for net rpc group list global local "
2980 net_display_usage_from_functable(func);
2984 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
2985 rpc_group_list_internals,
2989 return net_run_function(c, argc, argv, "net rpc group", func);
2992 /****************************************************************************/
2994 static int rpc_share_usage(struct net_context *c, int argc, const char **argv)
2996 return net_share_usage(c, argc, argv);
3000 * Add a share on a remote RPC server.
3002 * All parameters are provided by the run_rpc_command function, except for
3003 * argc, argv which are passed through.
3005 * @param domain_sid The domain sid acquired from the remote server.
3006 * @param cli A cli_state connected to the server.
3007 * @param mem_ctx Talloc context, destroyed on completion of the function.
3008 * @param argc Standard main() style argc.
3009 * @param argv Standard main() style argv. Initial components are already
3012 * @return Normal NTSTATUS return.
3014 static NTSTATUS rpc_share_add_internals(struct net_context *c,
3015 const DOM_SID *domain_sid,
3016 const char *domain_name,
3017 struct cli_state *cli,
3018 struct rpc_pipe_client *pipe_hnd,
3019 TALLOC_CTX *mem_ctx,int argc,
3026 uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
3027 uint32 num_users=0, perms=0;
3028 char *password=NULL; /* don't allow a share password */
3030 union srvsvc_NetShareInfo info;
3031 struct srvsvc_NetShareInfo2 info2;
3032 uint32_t parm_error = 0;
3034 if ((sharename = talloc_strdup(mem_ctx, argv[0])) == NULL) {
3035 return NT_STATUS_NO_MEMORY;
3038 path = strchr(sharename, '=');
3040 return NT_STATUS_UNSUCCESSFUL;
3043 info2.name = sharename;
3045 info2.comment = c->opt_comment;
3046 info2.permissions = perms;
3047 info2.max_users = c->opt_maxusers;
3048 info2.current_users = num_users;
3050 info2.password = password;
3052 info.info2 = &info2;
3054 status = rpccli_srvsvc_NetShareAdd(pipe_hnd, mem_ctx,
3063 static int rpc_share_add(struct net_context *c, int argc, const char **argv)
3065 if ((argc < 1) || !strchr(argv[0], '=') || c->display_usage) {
3066 return rpc_share_usage(c, argc, argv);
3068 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3069 rpc_share_add_internals,
3074 * Delete a share on a remote RPC server.
3076 * All parameters are provided by the run_rpc_command function, except for
3077 * argc, argv which are passed through.
3079 * @param domain_sid The domain sid acquired from the remote server.
3080 * @param cli A cli_state connected to the server.
3081 * @param mem_ctx Talloc context, destroyed on completion of the function.
3082 * @param argc Standard main() style argc.
3083 * @param argv Standard main() style argv. Initial components are already
3086 * @return Normal NTSTATUS return.
3088 static NTSTATUS rpc_share_del_internals(struct net_context *c,
3089 const DOM_SID *domain_sid,
3090 const char *domain_name,
3091 struct cli_state *cli,
3092 struct rpc_pipe_client *pipe_hnd,
3093 TALLOC_CTX *mem_ctx,
3099 return rpccli_srvsvc_NetShareDel(pipe_hnd, mem_ctx,
3107 * Delete a share on a remote RPC server.
3109 * @param domain_sid The domain sid acquired from the remote server.
3110 * @param argc Standard main() style argc.
3111 * @param argv Standard main() style argv. Initial components are already
3114 * @return A shell status integer (0 for success).
3116 static int rpc_share_delete(struct net_context *c, int argc, const char **argv)
3118 if (argc < 1 || c->display_usage) {
3119 return rpc_share_usage(c, argc, argv);
3121 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3122 rpc_share_del_internals,
3127 * Formatted print of share info
3129 * @param info1 pointer to SRV_SHARE_INFO_1 to format
3132 static void display_share_info_1(struct net_context *c,
3133 struct srvsvc_NetShareInfo1 *r)
3135 if (c->opt_long_list_entries) {
3136 d_printf("%-12s %-8.8s %-50s\n",
3138 c->share_type[r->type & ~(STYPE_TEMPORARY|STYPE_HIDDEN)],
3141 d_printf("%s\n", r->name);
3145 static WERROR get_share_info(struct net_context *c,
3146 struct rpc_pipe_client *pipe_hnd,
3147 TALLOC_CTX *mem_ctx,
3151 struct srvsvc_NetShareInfoCtr *info_ctr)
3155 union srvsvc_NetShareInfo info;
3157 /* no specific share requested, enumerate all */
3160 uint32_t preferred_len = 0xffffffff;
3161 uint32_t total_entries = 0;
3162 uint32_t resume_handle = 0;
3164 info_ctr->level = level;
3166 status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, mem_ctx,
3176 /* request just one share */
3177 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
3184 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
3189 ZERO_STRUCTP(info_ctr);
3191 info_ctr->level = level;
3196 struct srvsvc_NetShareCtr1 *ctr1;
3198 ctr1 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr1);
3199 W_ERROR_HAVE_NO_MEMORY(ctr1);
3202 ctr1->array = info.info1;
3204 info_ctr->ctr.ctr1 = ctr1;
3208 struct srvsvc_NetShareCtr2 *ctr2;
3210 ctr2 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr2);
3211 W_ERROR_HAVE_NO_MEMORY(ctr2);
3214 ctr2->array = info.info2;
3216 info_ctr->ctr.ctr2 = ctr2;
3220 struct srvsvc_NetShareCtr502 *ctr502;
3222 ctr502 = TALLOC_ZERO_P(mem_ctx, struct srvsvc_NetShareCtr502);
3223 W_ERROR_HAVE_NO_MEMORY(ctr502);
3226 ctr502->array = info.info502;
3228 info_ctr->ctr.ctr502 = ctr502;
3236 * List shares on a remote RPC server.
3238 * All parameters are provided by the run_rpc_command function, except for
3239 * argc, argv which are passed through.
3241 * @param domain_sid The domain sid acquired from the remote server.
3242 * @param cli A cli_state connected to the server.
3243 * @param mem_ctx Talloc context, destroyed on completion of the function.
3244 * @param argc Standard main() style argc.
3245 * @param argv Standard main() style argv. Initial components are already
3248 * @return Normal NTSTATUS return.
3251 static NTSTATUS rpc_share_list_internals(struct net_context *c,
3252 const DOM_SID *domain_sid,
3253 const char *domain_name,
3254 struct cli_state *cli,
3255 struct rpc_pipe_client *pipe_hnd,
3256 TALLOC_CTX *mem_ctx,
3260 struct srvsvc_NetShareInfoCtr info_ctr;
3261 struct srvsvc_NetShareCtr1 ctr1;
3263 uint32 i, level = 1;
3265 ZERO_STRUCT(info_ctr);
3269 info_ctr.ctr.ctr1 = &ctr1;
3271 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3273 if (!W_ERROR_IS_OK(result))
3276 /* Display results */
3278 if (c->opt_long_list_entries) {
3280 "\nEnumerating shared resources (exports) on remote server:\n\n"
3281 "\nShare name Type Description\n"
3282 "---------- ---- -----------\n");
3284 for (i = 0; i < info_ctr.ctr.ctr1->count; i++)
3285 display_share_info_1(c, &info_ctr.ctr.ctr1->array[i]);
3287 return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
3291 * 'net rpc share list' entrypoint.
3292 * @param argc Standard main() style argc.
3293 * @param argv Standard main() style argv. Initial components are already
3296 static int rpc_share_list(struct net_context *c, int argc, const char **argv)
3298 if (c->display_usage) {
3300 "net rpc share list\n"
3301 " List shares on remote server\n");
3305 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3306 rpc_share_list_internals, argc, argv);
3309 static bool check_share_availability(struct cli_state *cli, const char *netname)
3311 if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
3312 d_printf("skipping [%s]: not a file share.\n", netname);
3322 static bool check_share_sanity(struct net_context *c, struct cli_state *cli,
3323 const char *netname, uint32 type)
3325 /* only support disk shares */
3326 if (! ( type == STYPE_DISKTREE || type == (STYPE_DISKTREE | STYPE_HIDDEN)) ) {
3327 printf("share [%s] is not a diskshare (type: %x)\n", netname, type);
3331 /* skip builtin shares */
3332 /* FIXME: should print$ be added too ? */
3333 if (strequal(netname,"IPC$") || strequal(netname,"ADMIN$") ||
3334 strequal(netname,"global"))
3337 if (c->opt_exclude && in_list(netname, c->opt_exclude, false)) {
3338 printf("excluding [%s]\n", netname);
3342 return check_share_availability(cli, netname);
3346 * Migrate shares from a remote RPC server to the local RPC server.
3348 * All parameters are provided by the run_rpc_command function, except for
3349 * argc, argv which are passed through.
3351 * @param domain_sid The domain sid acquired from the remote server.
3352 * @param cli A cli_state connected to the server.
3353 * @param mem_ctx Talloc context, destroyed on completion of the function.
3354 * @param argc Standard main() style argc.
3355 * @param argv Standard main() style argv. Initial components are already
3358 * @return Normal NTSTATUS return.
3361 static NTSTATUS rpc_share_migrate_shares_internals(struct net_context *c,
3362 const DOM_SID *domain_sid,
3363 const char *domain_name,
3364 struct cli_state *cli,
3365 struct rpc_pipe_client *pipe_hnd,
3366 TALLOC_CTX *mem_ctx,
3371 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3372 struct srvsvc_NetShareInfoCtr ctr_src;
3374 struct rpc_pipe_client *srvsvc_pipe = NULL;
3375 struct cli_state *cli_dst = NULL;
3376 uint32 level = 502; /* includes secdesc */
3377 uint32_t parm_error = 0;
3379 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3381 if (!W_ERROR_IS_OK(result))
3384 /* connect destination PI_SRVSVC */
3385 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3386 &ndr_table_srvsvc.syntax_id);
3387 if (!NT_STATUS_IS_OK(nt_status))
3391 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3393 union srvsvc_NetShareInfo info;
3394 struct srvsvc_NetShareInfo502 info502 =
3395 ctr_src.ctr.ctr502->array[i];
3397 /* reset error-code */
3398 nt_status = NT_STATUS_UNSUCCESSFUL;
3400 if (!check_share_sanity(c, cli, info502.name, info502.type))
3403 /* finally add the share on the dst server */
3405 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n",
3406 info502.name, info502.path, info502.comment);
3408 info.info502 = &info502;
3410 nt_status = rpccli_srvsvc_NetShareAdd(srvsvc_pipe, mem_ctx,
3411 srvsvc_pipe->desthost,
3417 if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) {
3418 printf(" [%s] does already exist\n",
3423 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3424 printf("cannot add share: %s\n", dos_errstr(result));
3430 nt_status = NT_STATUS_OK;
3434 cli_shutdown(cli_dst);
3442 * Migrate shares from a RPC server to another.
3444 * @param argc Standard main() style argc.
3445 * @param argv Standard main() style argv. Initial components are already
3448 * @return A shell status integer (0 for success).
3450 static int rpc_share_migrate_shares(struct net_context *c, int argc,
3453 if (c->display_usage) {
3455 "net rpc share migrate shares\n"
3456 " Migrate shares to local server\n");
3461 printf("no server to migrate\n");
3465 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3466 rpc_share_migrate_shares_internals,
3473 * @param f file_info
3474 * @param mask current search mask
3475 * @param state arg-pointer
3478 static void copy_fn(const char *mnt, file_info *f,
3479 const char *mask, void *state)
3481 static NTSTATUS nt_status;
3482 static struct copy_clistate *local_state;
3483 static fstring filename, new_mask;
3486 struct net_context *c;
3488 local_state = (struct copy_clistate *)state;
3489 nt_status = NT_STATUS_UNSUCCESSFUL;
3493 if (strequal(f->name, ".") || strequal(f->name, ".."))
3496 DEBUG(3,("got mask: %s, name: %s\n", mask, f->name));
3499 if (f->mode & aDIR) {
3501 DEBUG(3,("got dir: %s\n", f->name));
3503 fstrcpy(dir, local_state->cwd);
3505 fstrcat(dir, f->name);
3507 switch (net_mode_share)
3509 case NET_MODE_SHARE_MIGRATE:
3510 /* create that directory */
3511 nt_status = net_copy_file(c, local_state->mem_ctx,
3512 local_state->cli_share_src,
3513 local_state->cli_share_dst,
3515 c->opt_acls? true : false,
3516 c->opt_attrs? true : false,
3517 c->opt_timestamps? true:false,
3521 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3525 if (!NT_STATUS_IS_OK(nt_status))
3526 printf("could not handle dir %s: %s\n",
3527 dir, nt_errstr(nt_status));
3529 /* search below that directory */
3530 fstrcpy(new_mask, dir);
3531 fstrcat(new_mask, "\\*");
3533 old_dir = local_state->cwd;
3534 local_state->cwd = dir;
3535 if (!sync_files(local_state, new_mask))
3536 printf("could not handle files\n");
3537 local_state->cwd = old_dir;
3544 fstrcpy(filename, local_state->cwd);
3545 fstrcat(filename, "\\");
3546 fstrcat(filename, f->name);
3548 DEBUG(3,("got file: %s\n", filename));
3550 switch (net_mode_share)
3552 case NET_MODE_SHARE_MIGRATE:
3553 nt_status = net_copy_file(c, local_state->mem_ctx,
3554 local_state->cli_share_src,
3555 local_state->cli_share_dst,
3557 c->opt_acls? true : false,
3558 c->opt_attrs? true : false,
3559 c->opt_timestamps? true: false,
3563 d_fprintf(stderr, "Unsupported file mode %d\n", net_mode_share);
3567 if (!NT_STATUS_IS_OK(nt_status))
3568 printf("could not handle file %s: %s\n",
3569 filename, nt_errstr(nt_status));
3574 * sync files, can be called recursivly to list files
3575 * and then call copy_fn for each file
3577 * @param cp_clistate pointer to the copy_clistate we work with
3578 * @param mask the current search mask
3580 * @return Boolean result
3582 static bool sync_files(struct copy_clistate *cp_clistate, const char *mask)
3584 struct cli_state *targetcli;
3585 char *targetpath = NULL;
3587 DEBUG(3,("calling cli_list with mask: %s\n", mask));
3589 if ( !cli_resolve_path(talloc_tos(), "", cp_clistate->cli_share_src,
3590 mask, &targetcli, &targetpath ) ) {
3591 d_fprintf(stderr, "cli_resolve_path %s failed with error: %s\n",
3592 mask, cli_errstr(cp_clistate->cli_share_src));
3596 if (cli_list(targetcli, targetpath, cp_clistate->attribute, copy_fn, cp_clistate) == -1) {
3597 d_fprintf(stderr, "listing %s failed with error: %s\n",
3598 mask, cli_errstr(targetcli));
3607 * Set the top level directory permissions before we do any further copies.
3608 * Should set up ACL inheritance.
3611 bool copy_top_level_perms(struct net_context *c,
3612 struct copy_clistate *cp_clistate,
3613 const char *sharename)
3615 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3617 switch (net_mode_share) {
3618 case NET_MODE_SHARE_MIGRATE:
3619 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename));
3620 nt_status = net_copy_fileattr(c,
3621 cp_clistate->mem_ctx,
3622 cp_clistate->cli_share_src,
3623 cp_clistate->cli_share_dst,
3625 c->opt_acls? true : false,
3626 c->opt_attrs? true : false,
3627 c->opt_timestamps? true: false,
3631 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3635 if (!NT_STATUS_IS_OK(nt_status)) {
3636 printf("Could handle directory attributes for top level directory of share %s. Error %s\n",
3637 sharename, nt_errstr(nt_status));
3645 * Sync all files inside a remote share to another share (over smb).
3647 * All parameters are provided by the run_rpc_command function, except for
3648 * argc, argv which are passed through.
3650 * @param domain_sid The domain sid acquired from the remote server.
3651 * @param cli A cli_state connected to the server.
3652 * @param mem_ctx Talloc context, destroyed on completion of the function.
3653 * @param argc Standard main() style argc.
3654 * @param argv Standard main() style argv. Initial components are already
3657 * @return Normal NTSTATUS return.
3660 static NTSTATUS rpc_share_migrate_files_internals(struct net_context *c,
3661 const DOM_SID *domain_sid,
3662 const char *domain_name,
3663 struct cli_state *cli,
3664 struct rpc_pipe_client *pipe_hnd,
3665 TALLOC_CTX *mem_ctx,
3670 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3671 struct srvsvc_NetShareInfoCtr ctr_src;
3674 struct copy_clistate cp_clistate;
3675 bool got_src_share = false;
3676 bool got_dst_share = false;
3677 const char *mask = "\\*";
3680 dst = SMB_STRDUP(c->opt_destination?c->opt_destination:"127.0.0.1");
3682 nt_status = NT_STATUS_NO_MEMORY;
3686 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3689 if (!W_ERROR_IS_OK(result))
3692 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3694 struct srvsvc_NetShareInfo502 info502 =
3695 ctr_src.ctr.ctr502->array[i];
3697 if (!check_share_sanity(c, cli, info502.name, info502.type))
3700 /* one might not want to mirror whole discs :) */
3701 if (strequal(info502.name, "print$") || info502.name[1] == '$') {
3702 d_printf("skipping [%s]: builtin/hidden share\n", info502.name);
3706 switch (net_mode_share)
3708 case NET_MODE_SHARE_MIGRATE:
3712 d_fprintf(stderr, "Unsupported mode %d\n", net_mode_share);
3715 printf(" [%s] files and directories %s ACLs, %s DOS Attributes %s\n",
3717 c->opt_acls ? "including" : "without",
3718 c->opt_attrs ? "including" : "without",
3719 c->opt_timestamps ? "(preserving timestamps)" : "");
3721 cp_clistate.mem_ctx = mem_ctx;
3722 cp_clistate.cli_share_src = NULL;
3723 cp_clistate.cli_share_dst = NULL;
3724 cp_clistate.cwd = NULL;
3725 cp_clistate.attribute = aSYSTEM | aHIDDEN | aDIR;
3728 /* open share source */
3729 nt_status = connect_to_service(c, &cp_clistate.cli_share_src,
3730 &cli->dest_ss, cli->desthost,
3731 info502.name, "A:");
3732 if (!NT_STATUS_IS_OK(nt_status))
3735 got_src_share = true;
3737 if (net_mode_share == NET_MODE_SHARE_MIGRATE) {
3738 /* open share destination */
3739 nt_status = connect_to_service(c, &cp_clistate.cli_share_dst,
3740 NULL, dst, info502.name, "A:");
3741 if (!NT_STATUS_IS_OK(nt_status))
3744 got_dst_share = true;
3747 if (!copy_top_level_perms(c, &cp_clistate, info502.name)) {
3748 d_fprintf(stderr, "Could not handle the top level directory permissions for the share: %s\n", info502.name);
3749 nt_status = NT_STATUS_UNSUCCESSFUL;
3753 if (!sync_files(&cp_clistate, mask)) {
3754 d_fprintf(stderr, "could not handle files for share: %s\n", info502.name);
3755 nt_status = NT_STATUS_UNSUCCESSFUL;
3760 nt_status = NT_STATUS_OK;
3765 cli_shutdown(cp_clistate.cli_share_src);
3768 cli_shutdown(cp_clistate.cli_share_dst);
3775 static int rpc_share_migrate_files(struct net_context *c, int argc, const char **argv)
3777 if (c->display_usage) {
3779 "net share migrate files\n"
3780 " Migrate files to local server\n");
3785 d_printf("no server to migrate\n");
3789 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3790 rpc_share_migrate_files_internals,
3795 * Migrate share-ACLs from a remote RPC server to the local RPC server.
3797 * All parameters are provided by the run_rpc_command function, except for
3798 * argc, argv which are passed through.
3800 * @param domain_sid The domain sid acquired from the remote server.
3801 * @param cli A cli_state connected to the server.
3802 * @param mem_ctx Talloc context, destroyed on completion of the function.
3803 * @param argc Standard main() style argc.
3804 * @param argv Standard main() style argv. Initial components are already
3807 * @return Normal NTSTATUS return.
3810 static NTSTATUS rpc_share_migrate_security_internals(struct net_context *c,
3811 const DOM_SID *domain_sid,
3812 const char *domain_name,
3813 struct cli_state *cli,
3814 struct rpc_pipe_client *pipe_hnd,
3815 TALLOC_CTX *mem_ctx,
3820 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
3821 struct srvsvc_NetShareInfoCtr ctr_src;
3822 union srvsvc_NetShareInfo info;
3824 struct rpc_pipe_client *srvsvc_pipe = NULL;
3825 struct cli_state *cli_dst = NULL;
3826 uint32 level = 502; /* includes secdesc */
3827 uint32_t parm_error = 0;
3829 result = get_share_info(c, pipe_hnd, mem_ctx, level, argc, argv,
3832 if (!W_ERROR_IS_OK(result))
3835 /* connect destination PI_SRVSVC */
3836 nt_status = connect_dst_pipe(c, &cli_dst, &srvsvc_pipe,
3837 &ndr_table_srvsvc.syntax_id);
3838 if (!NT_STATUS_IS_OK(nt_status))
3842 for (i = 0; i < ctr_src.ctr.ctr502->count; i++) {
3844 struct srvsvc_NetShareInfo502 info502 =
3845 ctr_src.ctr.ctr502->array[i];
3847 /* reset error-code */
3848 nt_status = NT_STATUS_UNSUCCESSFUL;
3850 if (!check_share_sanity(c, cli, info502.name, info502.type))
3853 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n",
3854 info502.name, info502.path, info502.comment);
3857 display_sec_desc(info502.sd_buf.sd);
3859 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3860 info.info502 = &info502;
3862 /* finally modify the share on the dst server */
3863 nt_status = rpccli_srvsvc_NetShareSetInfo(srvsvc_pipe, mem_ctx,
3864 srvsvc_pipe->desthost,
3870 if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result)) {
3871 printf("cannot set share-acl: %s\n", dos_errstr(result));
3877 nt_status = NT_STATUS_OK;
3881 cli_shutdown(cli_dst);
3889 * Migrate share-acls from a RPC server to another.
3891 * @param argc Standard main() style argc.
3892 * @param argv Standard main() style argv. Initial components are already
3895 * @return A shell status integer (0 for success).
3897 static int rpc_share_migrate_security(struct net_context *c, int argc,
3900 if (c->display_usage) {
3902 "net rpc share migrate security\n"
3903 " Migrate share-acls to local server\n");
3908 d_printf("no server to migrate\n");
3912 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3913 rpc_share_migrate_security_internals,
3918 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3919 * from one server to another.
3921 * @param argc Standard main() style argc.
3922 * @param argv Standard main() style argv. Initial components are already
3925 * @return A shell status integer (0 for success).
3928 static int rpc_share_migrate_all(struct net_context *c, int argc,
3933 if (c->display_usage) {
3935 "net rpc share migrate all\n"
3936 " Migrates shares including all share settings\n");
3941 d_printf("no server to migrate\n");
3945 /* order is important. we don't want to be locked out by the share-acl
3946 * before copying files - gd */
3948 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3949 rpc_share_migrate_shares_internals, argc, argv);
3953 ret = run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3954 rpc_share_migrate_files_internals, argc, argv);
3958 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
3959 rpc_share_migrate_security_internals, argc,
3965 * 'net rpc share migrate' entrypoint.
3966 * @param argc Standard main() style argc.
3967 * @param argv Standard main() style argv. Initial components are already
3970 static int rpc_share_migrate(struct net_context *c, int argc, const char **argv)
3973 struct functable func[] = {
3976 rpc_share_migrate_all,
3978 "Migrate shares from remote to local server",
3979 "net rpc share migrate all\n"
3980 " Migrate shares from remote to local server"
3984 rpc_share_migrate_files,
3986 "Migrate files from remote to local server",
3987 "net rpc share migrate files\n"
3988 " Migrate files from remote to local server"
3992 rpc_share_migrate_security,
3994 "Migrate share-ACLs from remote to local server",
3995 "net rpc share migrate security\n"
3996 " Migrate share-ACLs from remote to local server"
4000 rpc_share_migrate_shares,
4002 "Migrate shares from remote to local server",
4003 "net rpc share migrate shares\n"
4004 " Migrate shares from remote to local server"
4006 {NULL, NULL, 0, NULL, NULL}
4009 net_mode_share = NET_MODE_SHARE_MIGRATE;
4011 return net_run_function(c, argc, argv, "net rpc share migrate", func);
4020 static int num_server_aliases;
4021 static struct full_alias *server_aliases;
4024 * Add an alias to the static list.
4026 static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
4028 if (server_aliases == NULL)
4029 server_aliases = SMB_MALLOC_ARRAY(struct full_alias, 100);
4031 server_aliases[num_server_aliases] = *alias;
4032 num_server_aliases += 1;
4036 * For a specific domain on the server, fetch all the aliases
4037 * and their members. Add all of them to the server_aliases.
4040 static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
4041 TALLOC_CTX *mem_ctx,
4042 POLICY_HND *connect_pol,
4043 const DOM_SID *domain_sid)
4045 uint32 start_idx, max_entries, num_entries, i;
4046 struct samr_SamArray *groups = NULL;
4048 POLICY_HND domain_pol;
4050 /* Get domain policy handle */
4052 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
4054 MAXIMUM_ALLOWED_ACCESS,
4055 CONST_DISCARD(struct dom_sid2 *, domain_sid),
4057 if (!NT_STATUS_IS_OK(result))
4064 result = rpccli_samr_EnumDomainAliases(pipe_hnd, mem_ctx,
4070 for (i = 0; i < num_entries; i++) {
4072 POLICY_HND alias_pol;
4073 struct full_alias alias;
4074 struct lsa_SidArray sid_array;
4077 result = rpccli_samr_OpenAlias(pipe_hnd, mem_ctx,
4079 MAXIMUM_ALLOWED_ACCESS,
4080 groups->entries[i].idx,
4082 if (!NT_STATUS_IS_OK(result))
4085 result = rpccli_samr_GetMembersInAlias(pipe_hnd, mem_ctx,
4088 if (!NT_STATUS_IS_OK(result))
4091 alias.num_members = sid_array.num_sids;
4093 result = rpccli_samr_Close(pipe_hnd, mem_ctx, &alias_pol);
4094 if (!NT_STATUS_IS_OK(result))
4097 alias.members = NULL;
4099 if (alias.num_members > 0) {
4100 alias.members = SMB_MALLOC_ARRAY(DOM_SID, alias.num_members);
4102 for (j = 0; j < alias.num_members; j++)
4103 sid_copy(&alias.members[j],
4104 sid_array.sids[j].sid);
4107 sid_copy(&alias.sid, domain_sid);
4108 sid_append_rid(&alias.sid, groups->entries[i].idx);
4110 push_alias(mem_ctx, &alias);
4112 } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
4114 result = NT_STATUS_OK;
4117 rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
4123 * Dump server_aliases as names for debugging purposes.
4126 static NTSTATUS rpc_aliaslist_dump(struct net_context *c,
4127 const DOM_SID *domain_sid,
4128 const char *domain_name,
4129 struct cli_state *cli,
4130 struct rpc_pipe_client *pipe_hnd,
4131 TALLOC_CTX *mem_ctx,
4139 result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
4140 SEC_RIGHTS_MAXIMUM_ALLOWED,
4142 if (!NT_STATUS_IS_OK(result))
4145 for (i=0; i<num_server_aliases; i++) {
4148 enum lsa_SidType *types;
4151 struct full_alias *alias = &server_aliases[i];
4153 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
4155 &domains, &names, &types);
4156 if (!NT_STATUS_IS_OK(result))
4159 DEBUG(1, ("%s\\%s %d: ", domains[0], names[0], types[0]));
4161 if (alias->num_members == 0) {
4166 result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
4169 &domains, &names, &types);
4171 if (!NT_STATUS_IS_OK(result) &&
4172 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED))
4175 for (j=0; j<alias->num_members; j++)
4176 DEBUG(1, ("%s\\%s (%d); ",
4177 domains[j] ? domains[j] : "*unknown*",
4178 names[j] ? names[j] : "*unknown*",types[j]));
4182 rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
4184 return NT_STATUS_OK;
4188 * Fetch a list of all server aliases and their members into
4192 static NTSTATUS rpc_aliaslist_internals(struct net_context *c,
4193 const DOM_SID *domain_sid,
4194 const char *domain_name,
4195 struct cli_state *cli,
4196 struct rpc_pipe_client *pipe_hnd,
4197 TALLOC_CTX *mem_ctx,
4202 POLICY_HND connect_pol;
4204 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
4206 MAXIMUM_ALLOWED_ACCESS,
4209 if (!NT_STATUS_IS_OK(result))
4212 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4213 &global_sid_Builtin);
4215 if (!NT_STATUS_IS_OK(result))
4218 result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
4221 rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_pol);
4226 static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid)
4228 token->num_sids = 4;
4230 if (!(token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4))) {
4231 d_fprintf(stderr, "malloc failed\n");
4232 token->num_sids = 0;
4236 token->user_sids[0] = *user_sid;
4237 sid_copy(&token->user_sids[1], &global_sid_World);
4238 sid_copy(&token->user_sids[2], &global_sid_Network);
4239 sid_copy(&token->user_sids[3], &global_sid_Authenticated_Users);
4242 static void free_user_token(NT_USER_TOKEN *token)
4244 SAFE_FREE(token->user_sids);
4247 static bool is_sid_in_token(NT_USER_TOKEN *token, DOM_SID *sid)
4251 for (i=0; i<token->num_sids; i++) {
4252 if (sid_compare(sid, &token->user_sids[i]) == 0)
4258 static void add_sid_to_token(NT_USER_TOKEN *token, DOM_SID *sid)
4260 if (is_sid_in_token(token, sid))
4263 token->user_sids = SMB_REALLOC_ARRAY(token->user_sids, DOM_SID, token->num_sids+1);
4264 if (!token->user_sids) {
4268 sid_copy(&token->user_sids[token->num_sids], sid);
4270 token->num_sids += 1;
4275 NT_USER_TOKEN token;
4278 static void dump_user_token(struct user_token *token)
4282 d_printf("%s\n", token->name);
4284 for (i=0; i<token->token.num_sids; i++) {
4285 d_printf(" %s\n", sid_string_tos(&token->token.user_sids[i]));
4289 static bool is_alias_member(DOM_SID *sid, struct full_alias *alias)
4293 for (i=0; i<alias->num_members; i++) {
4294 if (sid_compare(sid, &alias->members[i]) == 0)
4301 static void collect_sid_memberships(NT_USER_TOKEN *token, DOM_SID sid)
4305 for (i=0; i<num_server_aliases; i++) {
4306 if (is_alias_member(&sid, &server_aliases[i]))
4307 add_sid_to_token(token, &server_aliases[i].sid);
4312 * We got a user token with all the SIDs we can know about without asking the
4313 * server directly. These are the user and domain group sids. All of these can
4314 * be members of aliases. So scan the list of aliases for each of the SIDs and
4315 * add them to the token.
4318 static void collect_alias_memberships(NT_USER_TOKEN *token)
4320 int num_global_sids = token->num_sids;
4323 for (i=0; i<num_global_sids; i++) {
4324 collect_sid_memberships(token, token->user_sids[i]);
4328 static bool get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
4330 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4331 enum wbcSidType type;
4333 struct wbcDomainSid wsid;
4334 char *sid_str = NULL;
4336 uint32_t num_groups;
4337 gid_t *groups = NULL;
4340 fstr_sprintf(full_name, "%s%c%s",
4341 domain, *lp_winbind_separator(), user);
4343 /* First let's find out the user sid */
4345 wbc_status = wbcLookupName(domain, user, &wsid, &type);
4347 if (!WBC_ERROR_IS_OK(wbc_status)) {
4348 DEBUG(1, ("winbind could not find %s: %s\n",
4349 full_name, wbcErrorString(wbc_status)));
4353 wbc_status = wbcSidToString(&wsid, &sid_str);
4354 if (!WBC_ERROR_IS_OK(wbc_status)) {
4358 if (type != SID_NAME_USER) {
4359 wbcFreeMemory(sid_str);
4360 DEBUG(1, ("%s is not a user\n", full_name));
4364 string_to_sid(&user_sid, sid_str);
4365 wbcFreeMemory(sid_str);
4368 init_user_token(token, &user_sid);
4370 /* And now the groups winbind knows about */
4372 wbc_status = wbcGetGroups(full_name, &num_groups, &groups);
4373 if (!WBC_ERROR_IS_OK(wbc_status)) {
4374 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4375 full_name, wbcErrorString(wbc_status)));
4379 for (i = 0; i < num_groups; i++) {
4380 gid_t gid = groups[i];
4383 wbc_status = wbcGidToSid(gid, &wsid);
4384 if (!WBC_ERROR_IS_OK(wbc_status)) {
4385 DEBUG(1, ("winbind could not find SID of gid %d: %s\n",
4386 gid, wbcErrorString(wbc_status)));
4387 wbcFreeMemory(groups);
4391 wbc_status = wbcSidToString(&wsid, &sid_str);
4392 if (!WBC_ERROR_IS_OK(wbc_status)) {
4393 wbcFreeMemory(groups);
4397 DEBUG(3, (" %s\n", sid_str));
4399 string_to_sid(&sid, sid_str);
4400 wbcFreeMemory(sid_str);
4403 add_sid_to_token(token, &sid);
4405 wbcFreeMemory(groups);
4411 * Get a list of all user tokens we want to look at
4414 static bool get_user_tokens(struct net_context *c, int *num_tokens,
4415 struct user_token **user_tokens)
4417 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
4418 uint32_t i, num_users;
4420 struct user_token *result;
4421 TALLOC_CTX *frame = NULL;
4423 if (lp_winbind_use_default_domain() &&
4424 (c->opt_target_workgroup == NULL)) {
4425 d_fprintf(stderr, "winbind use default domain = yes set, "
4426 "please specify a workgroup\n");
4430 /* Send request to winbind daemon */
4432 wbc_status = wbcListUsers(NULL, &num_users, &users);
4433 if (!WBC_ERROR_IS_OK(wbc_status)) {
4434 DEBUG(1, ("winbind could not list users: %s\n",
4435 wbcErrorString(wbc_status)));
4439 result = SMB_MALLOC_ARRAY(struct user_token, num_users);
4441 if (result == NULL) {
4442 DEBUG(1, ("Could not malloc sid array\n"));
4443 wbcFreeMemory(users);
4447 frame = talloc_stackframe();
4448 for (i=0; i < num_users; i++) {
4449 fstring domain, user;
4452 fstrcpy(result[i].name, users[i]);
4454 p = strchr(users[i], *lp_winbind_separator());
4456 DEBUG(3, ("%s\n", users[i]));
4459 fstrcpy(domain, c->opt_target_workgroup);
4460 fstrcpy(user, users[i]);
4463 fstrcpy(domain, users[i]);
4468 get_user_sids(domain, user, &(result[i].token));
4472 wbcFreeMemory(users);
4474 *num_tokens = num_users;
4475 *user_tokens = result;
4480 static bool get_user_tokens_from_file(FILE *f,
4482 struct user_token **tokens)
4484 struct user_token *token = NULL;
4489 if (fgets(line, sizeof(line)-1, f) == NULL) {
4493 if (line[strlen(line)-1] == '\n')
4494 line[strlen(line)-1] = '\0';
4496 if (line[0] == ' ') {
4500 string_to_sid(&sid, &line[1]);
4502 if (token == NULL) {
4503 DEBUG(0, ("File does not begin with username"));
4507 add_sid_to_token(&token->token, &sid);
4511 /* And a new user... */
4514 *tokens = SMB_REALLOC_ARRAY(*tokens, struct user_token, *num_tokens);
4515 if (*tokens == NULL) {
4516 DEBUG(0, ("Could not realloc tokens\n"));
4520 token = &((*tokens)[*num_tokens-1]);
4522 fstrcpy(token->name, line);
4523 token->token.num_sids = 0;
4524 token->token.user_sids = NULL;
4533 * Show the list of all users that have access to a share
4536 static void show_userlist(struct rpc_pipe_client *pipe_hnd,
4537 TALLOC_CTX *mem_ctx,
4538 const char *netname,
4540 struct user_token *tokens)
4543 SEC_DESC *share_sd = NULL;
4544 SEC_DESC *root_sd = NULL;
4545 struct cli_state *cli = rpc_pipe_np_smb_conn(pipe_hnd);
4547 union srvsvc_NetShareInfo info;
4552 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4559 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4560 DEBUG(1, ("Coult not query secdesc for share %s\n",
4565 share_sd = info.info502->sd_buf.sd;
4566 if (share_sd == NULL) {
4567 DEBUG(1, ("Got no secdesc for share %s\n",
4573 if (!cli_send_tconX(cli, netname, "A:", "", 0)) {
4577 fnum = cli_nt_create(cli, "\\", READ_CONTROL_ACCESS);
4580 root_sd = cli_query_secdesc(cli, fnum, mem_ctx);
4583 for (i=0; i<num_tokens; i++) {
4586 if (share_sd != NULL) {
4587 if (!se_access_check(share_sd, &tokens[i].token,
4588 1, &acc_granted, &status)) {
4589 DEBUG(1, ("Could not check share_sd for "
4595 if (!NT_STATUS_IS_OK(status))
4599 if (root_sd == NULL) {
4600 d_printf(" %s\n", tokens[i].name);
4604 if (!se_access_check(root_sd, &tokens[i].token,
4605 1, &acc_granted, &status)) {
4606 DEBUG(1, ("Could not check root_sd for user %s\n",
4611 if (!NT_STATUS_IS_OK(status))
4614 d_printf(" %s\n", tokens[i].name);
4618 cli_close(cli, fnum);
4630 static void collect_share(const char *name, uint32 m,
4631 const char *comment, void *state)
4633 struct share_list *share_list = (struct share_list *)state;
4635 if (m != STYPE_DISKTREE)
4638 share_list->num_shares += 1;
4639 share_list->shares = SMB_REALLOC_ARRAY(share_list->shares, char *, share_list->num_shares);
4640 if (!share_list->shares) {
4641 share_list->num_shares = 0;
4644 share_list->shares[share_list->num_shares-1] = SMB_STRDUP(name);
4648 * List shares on a remote RPC server, including the security descriptors.
4650 * All parameters are provided by the run_rpc_command function, except for
4651 * argc, argv which are passed through.
4653 * @param domain_sid The domain sid acquired from the remote server.
4654 * @param cli A cli_state connected to the server.
4655 * @param mem_ctx Talloc context, destroyed on completion of the function.
4656 * @param argc Standard main() style argc.
4657 * @param argv Standard main() style argv. Initial components are already
4660 * @return Normal NTSTATUS return.
4663 static NTSTATUS rpc_share_allowedusers_internals(struct net_context *c,
4664 const DOM_SID *domain_sid,
4665 const char *domain_name,
4666 struct cli_state *cli,
4667 struct rpc_pipe_client *pipe_hnd,
4668 TALLOC_CTX *mem_ctx,
4678 struct user_token *tokens = NULL;
4681 struct share_list share_list;
4686 f = fopen(argv[0], "r");
4690 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno)));
4691 return NT_STATUS_UNSUCCESSFUL;
4694 r = get_user_tokens_from_file(f, &num_tokens, &tokens);
4700 DEBUG(0, ("Could not read users from file\n"));
4701 return NT_STATUS_UNSUCCESSFUL;
4704 for (i=0; i<num_tokens; i++)
4705 collect_alias_memberships(&tokens[i].token);
4707 init_enum_hnd(&hnd, 0);
4709 share_list.num_shares = 0;
4710 share_list.shares = NULL;
4712 ret = cli_RNetShareEnum(cli, collect_share, &share_list);
4715 DEBUG(0, ("Error returning browse list: %s\n",
4720 for (i = 0; i < share_list.num_shares; i++) {
4721 char *netname = share_list.shares[i];
4723 if (netname[strlen(netname)-1] == '$')
4726 d_printf("%s\n", netname);
4728 show_userlist(pipe_hnd, mem_ctx, netname,
4729 num_tokens, tokens);
4732 for (i=0; i<num_tokens; i++) {
4733 free_user_token(&tokens[i].token);
4736 SAFE_FREE(share_list.shares);
4738 return NT_STATUS_OK;
4741 static int rpc_share_allowedusers(struct net_context *c, int argc,
4746 if (c->display_usage) {
4748 "net rpc share allowedusers\n"
4749 " List allowed users\n");
4753 result = run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
4754 rpc_aliaslist_internals,
4759 result = run_rpc_command(c, NULL, &ndr_table_lsarpc.syntax_id, 0,
4765 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4766 rpc_share_allowedusers_internals,
4770 int net_usersidlist(struct net_context *c, int argc, const char **argv)
4773 struct user_token *tokens = NULL;
4777 net_usersidlist_usage(c, argc, argv);
4781 if (!get_user_tokens(c, &num_tokens, &tokens)) {
4782 DEBUG(0, ("Could not get the user/sid list\n"));
4786 for (i=0; i<num_tokens; i++) {
4787 dump_user_token(&tokens[i]);
4788 free_user_token(&tokens[i].token);
4795 int net_usersidlist_usage(struct net_context *c, int argc, const char **argv)
4797 d_printf("net usersidlist\n"
4798 "\tprints out a list of all users the running winbind knows\n"
4799 "\tabout, together with all their SIDs. This is used as\n"
4800 "\tinput to the 'net rpc share allowedusers' command.\n\n");
4802 net_common_flags_usage(c, argc, argv);
4807 * 'net rpc share' entrypoint.
4808 * @param argc Standard main() style argc.
4809 * @param argv Standard main() style argv. Initial components are already
4813 int net_rpc_share(struct net_context *c, int argc, const char **argv)
4815 struct functable func[] = {
4821 "net rpc share add\n"
4829 "net rpc share delete\n"
4834 rpc_share_allowedusers,
4836 "Modify allowed users",
4837 "net rpc share allowedusers\n"
4838 " Modify allowed users"
4844 "Migrate share to local server",
4845 "net rpc share migrate\n"
4846 " Migrate share to local server"
4853 "net rpc share list\n"
4856 {NULL, NULL, 0, NULL, NULL}
4861 if (c->display_usage) {
4865 " Alias for net rpc share list\n");
4866 net_display_usage_from_functable(func);
4870 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
4871 rpc_share_list_internals,
4875 return net_run_function(c, argc, argv, "net rpc share", func);
4878 static NTSTATUS rpc_sh_share_list(struct net_context *c,
4879 TALLOC_CTX *mem_ctx,
4880 struct rpc_sh_ctx *ctx,
4881 struct rpc_pipe_client *pipe_hnd,
4882 int argc, const char **argv)
4884 return rpc_share_list_internals(c, ctx->domain_sid, ctx->domain_name,
4885 ctx->cli, pipe_hnd, mem_ctx,
4889 static NTSTATUS rpc_sh_share_add(struct net_context *c,
4890 TALLOC_CTX *mem_ctx,
4891 struct rpc_sh_ctx *ctx,
4892 struct rpc_pipe_client *pipe_hnd,
4893 int argc, const char **argv)
4897 uint32_t parm_err = 0;
4898 union srvsvc_NetShareInfo info;
4899 struct srvsvc_NetShareInfo2 info2;
4901 if ((argc < 2) || (argc > 3)) {
4902 d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
4904 return NT_STATUS_INVALID_PARAMETER;
4907 info2.name = argv[0];
4908 info2.type = STYPE_DISKTREE;
4909 info2.comment = (argc == 3) ? argv[2] : "";
4910 info2.permissions = 0;
4911 info2.max_users = 0;
4912 info2.current_users = 0;
4913 info2.path = argv[1];
4914 info2.password = NULL;
4916 info.info2 = &info2;
4918 status = rpccli_srvsvc_NetShareAdd(pipe_hnd, mem_ctx,
4928 static NTSTATUS rpc_sh_share_delete(struct net_context *c,
4929 TALLOC_CTX *mem_ctx,
4930 struct rpc_sh_ctx *ctx,
4931 struct rpc_pipe_client *pipe_hnd,
4932 int argc, const char **argv)
4938 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
4939 return NT_STATUS_INVALID_PARAMETER;
4942 status = rpccli_srvsvc_NetShareDel(pipe_hnd, mem_ctx,
4951 static NTSTATUS rpc_sh_share_info(struct net_context *c,
4952 TALLOC_CTX *mem_ctx,
4953 struct rpc_sh_ctx *ctx,
4954 struct rpc_pipe_client *pipe_hnd,
4955 int argc, const char **argv)
4957 union srvsvc_NetShareInfo info;
4962 d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
4963 return NT_STATUS_INVALID_PARAMETER;
4966 status = rpccli_srvsvc_NetShareGetInfo(pipe_hnd, mem_ctx,
4972 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
4976 d_printf("Name: %s\n", info.info2->name);
4977 d_printf("Comment: %s\n", info.info2->comment);
4978 d_printf("Path: %s\n", info.info2->path);
4979 d_printf("Password: %s\n", info.info2->password);
4982 return werror_to_ntstatus(result);
4985 struct rpc_sh_cmd *net_rpc_share_cmds(struct net_context *c, TALLOC_CTX *mem_ctx,
4986 struct rpc_sh_ctx *ctx)
4988 static struct rpc_sh_cmd cmds[] = {
4990 { "list", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_list,
4991 "List available shares" },
4993 { "add", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_add,
4996 { "delete", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_delete,
4999 { "info", NULL, &ndr_table_srvsvc.syntax_id, rpc_sh_share_info,
5000 "Get information about a share" },
5002 { NULL, NULL, 0, NULL, NULL }
5008 /****************************************************************************/
5010 static int rpc_file_usage(struct net_context *c, int argc, const char **argv)
5012 return net_file_usage(c, argc, argv);
5016 * Close a file on a remote RPC server.
5018 * All parameters are provided by the run_rpc_command function, except for
5019 * argc, argv which are passed through.
5021 * @param c A net_context structure.
5022 * @param domain_sid The domain sid acquired from the remote server.
5023 * @param cli A cli_state connected to the server.
5024 * @param mem_ctx Talloc context, destroyed on completion of the function.
5025 * @param argc Standard main() style argc.
5026 * @param argv Standard main() style argv. Initial components are already
5029 * @return Normal NTSTATUS return.
5031 static NTSTATUS rpc_file_close_internals(struct net_context *c,
5032 const DOM_SID *domain_sid,
5033 const char *domain_name,
5034 struct cli_state *cli,
5035 struct rpc_pipe_client *pipe_hnd,
5036 TALLOC_CTX *mem_ctx,
5040 return rpccli_srvsvc_NetFileClose(pipe_hnd, mem_ctx,
5042 atoi(argv[0]), NULL);
5046 * Close a file on a remote RPC server.
5048 * @param argc Standard main() style argc.
5049 * @param argv Standard main() style argv. Initial components are already
5052 * @return A shell status integer (0 for success).
5054 static int rpc_file_close(struct net_context *c, int argc, const char **argv)
5056 if (argc < 1 || c->display_usage) {
5057 return rpc_file_usage(c, argc, argv);
5060 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
5061 rpc_file_close_internals,
5066 * Formatted print of open file info
5068 * @param r struct srvsvc_NetFileInfo3 contents
5071 static void display_file_info_3(struct srvsvc_NetFileInfo3 *r)
5073 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
5074 r->fid, r->user, r->permissions, r->num_locks, r->path);
5078 * List open files on a remote RPC server.
5080 * All parameters are provided by the run_rpc_command function, except for
5081 * argc, argv which are passed through.
5083 * @param c A net_context structure.
5084 * @param domain_sid The domain sid acquired from the remote server.
5085 * @param cli A cli_state connected to the server.
5086 * @param mem_ctx Talloc context, destroyed on completion of the function.
5087 * @param argc Standard main() style argc.
5088 * @param argv Standard main() style argv. Initial components are already
5091 * @return Normal NTSTATUS return.
5094 static NTSTATUS rpc_file_list_internals(struct net_context *c,
5095 const DOM_SID *domain_sid,
5096 const char *domain_name,
5097 struct cli_state *cli,
5098 struct rpc_pipe_client *pipe_hnd,
5099 TALLOC_CTX *mem_ctx,
5103 struct srvsvc_NetFileInfoCtr info_ctr;
5104 struct srvsvc_NetFileCtr3 ctr3;
5107 uint32 preferred_len = 0xffffffff, i;
5108 const char *username=NULL;
5109 uint32_t total_entries = 0;
5110 uint32_t resume_handle = 0;
5112 /* if argc > 0, must be user command */
5114 username = smb_xstrdup(argv[0]);
5116 ZERO_STRUCT(info_ctr);
5120 info_ctr.ctr.ctr3 = &ctr3;
5122 status = rpccli_srvsvc_NetFileEnum(pipe_hnd, mem_ctx,
5132 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
5135 /* Display results */
5138 "\nEnumerating open files on remote server:\n\n"
5139 "\nFileId Opened by Perms Locks Path"
5140 "\n------ --------- ----- ----- ---- \n");
5141 for (i = 0; i < total_entries; i++)
5142 display_file_info_3(&info_ctr.ctr.ctr3->array[i]);
5144 return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
5148 * List files for a user on a remote RPC server.
5150 * @param argc Standard main() style argc.
5151 * @param argv Standard main() style argv. Initial components are already
5154 * @return A shell status integer (0 for success)..
5157 static int rpc_file_user(struct net_context *c, int argc, const char **argv)
5159 if (argc < 1 || c->display_usage) {
5160 return rpc_file_usage(c, argc, argv);
5163 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
5164 rpc_file_list_internals,
5169 * 'net rpc file' entrypoint.
5170 * @param argc Standard main() style argc.
5171 * @param argv Standard main() style argv. Initial components are already
5175 int net_rpc_file(struct net_context *c, int argc, const char **argv)
5177 struct functable func[] = {
5182 "Close opened file",
5183 "net rpc file close\n"
5184 " Close opened file"
5190 "List files opened by user",
5191 "net rpc file user\n"
5192 " List files opened by user"
5199 "Display information about opened file",
5200 "net rpc file info\n"
5201 " Display information about opened file"
5204 {NULL, NULL, 0, NULL, NULL}
5208 if (c->display_usage) {
5209 d_printf("Usage:\n");
5210 d_printf("net rpc file\n"
5211 " List opened files\n");
5212 net_display_usage_from_functable(func);
5216 return run_rpc_command(c, NULL, &ndr_table_srvsvc.syntax_id, 0,
5217 rpc_file_list_internals,
5221 return net_run_function(c, argc, argv, "net rpc file", func);
5225 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
5227 * All parameters are provided by the run_rpc_command function, except for
5228 * argc, argv which are passed through.
5230 * @param c A net_context structure.
5231 * @param domain_sid The domain sid acquired from the remote server.
5232 * @param cli A cli_state connected to the server.
5233 * @param mem_ctx Talloc context, destroyed on completion of the function.
5234 * @param argc Standard main() style argc.
5235 * @param argv Standard main() style argv. Initial components are already
5238 * @return Normal NTSTATUS return.
5241 static NTSTATUS rpc_shutdown_abort_internals(struct net_context *c,
5242 const DOM_SID *domain_sid,
5243 const char *domain_name,
5244 struct cli_state *cli,
5245 struct rpc_pipe_client *pipe_hnd,
5246 TALLOC_CTX *mem_ctx,
5250 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5252 result = rpccli_initshutdown_Abort(pipe_hnd, mem_ctx, NULL, NULL);
5254 if (NT_STATUS_IS_OK(result)) {
5255 d_printf("\nShutdown successfully aborted\n");
5256 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
5258 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
5264 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
5266 * All parameters are provided by the run_rpc_command function, except for
5267 * argc, argv which are passed through.
5269 * @param c A net_context structure.
5270 * @param domain_sid The domain sid acquired from the remote server.
5271 * @param cli A cli_state connected to the server.
5272 * @param mem_ctx Talloc context, destroyed on completion of the function.
5273 * @param argc Standard main() style argc.
5274 * @param argv Standard main() style argv. Initial components are already
5277 * @return Normal NTSTATUS return.
5280 static NTSTATUS rpc_reg_shutdown_abort_internals(struct net_context *c,
5281 const DOM_SID *domain_sid,
5282 const char *domain_name,
5283 struct cli_state *cli,
5284 struct rpc_pipe_client *pipe_hnd,
5285 TALLOC_CTX *mem_ctx,
5289 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5291 result = rpccli_winreg_AbortSystemShutdown(pipe_hnd, mem_ctx, NULL, NULL);
5293 if (NT_STATUS_IS_OK(result)) {
5294 d_printf("\nShutdown successfully aborted\n");
5295 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
5297 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
5303 * ABORT the shutdown of a remote RPC server.
5305 * @param argc Standard main() style argc.
5306 * @param argv Standard main() style argv. Initial components are already
5309 * @return A shell status integer (0 for success).
5312 static int rpc_shutdown_abort(struct net_context *c, int argc,
5317 if (c->display_usage) {
5319 "net rpc abortshutdown\n"
5320 " Abort a scheduled shutdown\n");
5324 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5325 rpc_shutdown_abort_internals, argc, argv);
5330 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
5332 return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5333 rpc_reg_shutdown_abort_internals,
5338 * Shut down a remote RPC Server via initshutdown pipe.
5340 * All parameters are provided by the run_rpc_command function, except for
5341 * argc, argv which are passed through.
5343 * @param c A net_context structure.
5344 * @param domain_sid The domain sid acquired from the remote server.
5345 * @param cli A cli_state connected to the server.
5346 * @param mem_ctx Talloc context, destroyed on completion of the function.
5347 * @param argc Standard main() style argc.
5348 * @param argv Standard main() style argv. Initial components are already
5351 * @return Normal NTSTATUS return.
5354 NTSTATUS rpc_init_shutdown_internals(struct net_context *c,
5355 const DOM_SID *domain_sid,
5356 const char *domain_name,
5357 struct cli_state *cli,
5358 struct rpc_pipe_client *pipe_hnd,
5359 TALLOC_CTX *mem_ctx,
5363 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5364 const char *msg = "This machine will be shutdown shortly";
5365 uint32 timeout = 20;
5366 struct initshutdown_String msg_string;
5367 struct initshutdown_String_sub s;
5369 if (c->opt_comment) {
5370 msg = c->opt_comment;
5372 if (c->opt_timeout) {
5373 timeout = c->opt_timeout;
5377 msg_string.name = &s;
5379 /* create an entry */
5380 result = rpccli_initshutdown_Init(pipe_hnd, mem_ctx, NULL,
5381 &msg_string, timeout, c->opt_force, c->opt_reboot,
5384 if (NT_STATUS_IS_OK(result)) {
5385 d_printf("\nShutdown of remote machine succeeded\n");
5386 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5388 DEBUG(1,("Shutdown of remote machine failed!\n"));
5394 * Shut down a remote RPC Server via winreg pipe.
5396 * All parameters are provided by the run_rpc_command function, except for
5397 * argc, argv which are passed through.
5399 * @param c A net_context structure.
5400 * @param domain_sid The domain sid acquired from the remote server.
5401 * @param cli A cli_state connected to the server.
5402 * @param mem_ctx Talloc context, destroyed on completion of the function.
5403 * @param argc Standard main() style argc.
5404 * @param argv Standard main() style argv. Initial components are already
5407 * @return Normal NTSTATUS return.
5410 NTSTATUS rpc_reg_shutdown_internals(struct net_context *c,
5411 const DOM_SID *domain_sid,
5412 const char *domain_name,
5413 struct cli_state *cli,
5414 struct rpc_pipe_client *pipe_hnd,
5415 TALLOC_CTX *mem_ctx,
5419 const char *msg = "This machine will be shutdown shortly";
5420 uint32 timeout = 20;
5421 struct initshutdown_String msg_string;
5422 struct initshutdown_String_sub s;
5426 if (c->opt_comment) {
5427 msg = c->opt_comment;
5430 msg_string.name = &s;
5432 if (c->opt_timeout) {
5433 timeout = c->opt_timeout;
5436 /* create an entry */
5437 result = rpccli_winreg_InitiateSystemShutdown(pipe_hnd, mem_ctx, NULL,
5438 &msg_string, timeout, c->opt_force, c->opt_reboot,
5441 if (NT_STATUS_IS_OK(result)) {
5442 d_printf("\nShutdown of remote machine succeeded\n");
5444 d_fprintf(stderr, "\nShutdown of remote machine failed\n");
5445 if ( W_ERROR_EQUAL(werr, WERR_MACHINE_LOCKED) )
5446 d_fprintf(stderr, "\nMachine locked, use -f switch to force\n");
5448 d_fprintf(stderr, "\nresult was: %s\n", dos_errstr(werr));
5455 * Shut down a remote RPC server.
5457 * @param argc Standard main() style argc.
5458 * @param argv Standard main() style argv. Initial components are already
5461 * @return A shell status integer (0 for success).
5464 static int rpc_shutdown(struct net_context *c, int argc, const char **argv)
5468 if (c->display_usage) {
5470 "net rpc shutdown\n"
5471 " Shut down a remote RPC server\n");
5475 rc = run_rpc_command(c, NULL, &ndr_table_initshutdown.syntax_id, 0,
5476 rpc_init_shutdown_internals, argc, argv);
5479 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5480 rc = run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
5481 rpc_reg_shutdown_internals, argc, argv);
5487 /***************************************************************************
5488 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5489 ***************************************************************************/
5492 * Add interdomain trust account to the RPC server.
5493 * All parameters (except for argc and argv) are passed by run_rpc_command
5496 * @param c A net_context structure.
5497 * @param domain_sid The domain sid acquired from the server.
5498 * @param cli A cli_state connected to the server.
5499 * @param mem_ctx Talloc context, destroyed on completion of the function.
5500 * @param argc Standard main() style argc.
5501 * @param argv Standard main() style argv. Initial components are already
5504 * @return normal NTSTATUS return code.
5507 static NTSTATUS rpc_trustdom_add_internals(struct net_context *c,
5508 const DOM_SID *domain_sid,
5509 const char *domain_name,
5510 struct cli_state *cli,
5511 struct rpc_pipe_client *pipe_hnd,
5512 TALLOC_CTX *mem_ctx,
5516 POLICY_HND connect_pol, domain_pol, user_pol;
5517 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5519 struct lsa_String lsa_acct_name;
5521 uint32 acct_flags=0;
5523 uint32_t access_granted = 0;
5524 union samr_UserInfo info;
5525 unsigned int orig_timeout;
5528 d_printf("Usage: net rpc trustdom add <domain_name> "
5529 "<trust password>\n");
5530 return NT_STATUS_INVALID_PARAMETER;
5534 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5537 if (asprintf(&acct_name, "%s$", argv[0]) < 0) {
5538 return NT_STATUS_NO_MEMORY;
5541 strupper_m(acct_name);
5543 init_lsa_String(&lsa_acct_name, acct_name);
5545 /* Get samr policy handle */
5546 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5548 MAXIMUM_ALLOWED_ACCESS,
5550 if (!NT_STATUS_IS_OK(result)) {
5554 /* Get domain policy handle */
5555 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5557 MAXIMUM_ALLOWED_ACCESS,
5558 CONST_DISCARD(struct dom_sid2 *, domain_sid),
5560 if (!NT_STATUS_IS_OK(result)) {
5564 /* This call can take a long time - allow the server to time out.
5565 * 35 seconds should do it. */
5567 orig_timeout = rpccli_set_timeout(pipe_hnd, 35000);
5569 /* Create trusting domain's account */
5570 acb_info = ACB_NORMAL;
5571 acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
5572 SEC_STD_WRITE_DAC | SEC_STD_DELETE |
5573 SAMR_USER_ACCESS_SET_PASSWORD |
5574 SAMR_USER_ACCESS_GET_ATTRIBUTES |
5575 SAMR_USER_ACCESS_SET_ATTRIBUTES;
5577 result = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
5586 /* And restore our original timeout. */
5587 rpccli_set_timeout(pipe_hnd, orig_timeout);
5589 if (!NT_STATUS_IS_OK(result)) {
5590 d_printf("net rpc trustdom add: create user %s failed %s\n",
5591 acct_name, nt_errstr(result));
5597 struct samr_LogonHours hours;
5598 struct lsa_BinaryString parameters;
5599 const int units_per_week = 168;
5600 struct samr_CryptPassword crypt_pwd;
5602 ZERO_STRUCT(notime);
5604 ZERO_STRUCT(parameters);
5606 hours.bits = talloc_array(mem_ctx, uint8_t, units_per_week);
5608 result = NT_STATUS_NO_MEMORY;
5611 hours.units_per_week = units_per_week;
5612 memset(hours.bits, 0xFF, units_per_week);
5614 init_samr_CryptPassword(argv[1],
5615 &cli->user_session_key,
5618 init_samr_user_info23(&info.info23,
5619 notime, notime, notime,
5620 notime, notime, notime,
5621 NULL, NULL, NULL, NULL, NULL,
5622 NULL, NULL, NULL, NULL, ¶meters,
5623 0, 0, ACB_DOMTRUST, SAMR_FIELD_ACCT_FLAGS,
5625 0, 0, 0, 0, 0, 0, 0,
5626 crypt_pwd.data, 24);
5628 result = rpccli_samr_SetUserInfo2(pipe_hnd, mem_ctx,
5633 if (!NT_STATUS_IS_OK(result)) {
5634 DEBUG(0,("Could not set trust account password: %s\n",
5635 nt_errstr(result)));
5641 SAFE_FREE(acct_name);
5646 * Create interdomain trust account for a remote domain.
5648 * @param argc Standard argc.
5649 * @param argv Standard argv without initial components.
5651 * @return Integer status (0 means success).
5654 static int rpc_trustdom_add(struct net_context *c, int argc, const char **argv)
5656 if (argc > 0 && !c->display_usage) {
5657 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5658 rpc_trustdom_add_internals, argc, argv);
5661 "net rpc trustdom add <domain_name> <trust password>\n");
5668 * Remove interdomain trust account from the RPC server.
5669 * All parameters (except for argc and argv) are passed by run_rpc_command
5672 * @param c A net_context structure.
5673 * @param domain_sid The domain sid acquired from the server.
5674 * @param cli A cli_state connected to the server.
5675 * @param mem_ctx Talloc context, destroyed on completion of the function.
5676 * @param argc Standard main() style argc.
5677 * @param argv Standard main() style argv. Initial components are already
5680 * @return normal NTSTATUS return code.
5683 static NTSTATUS rpc_trustdom_del_internals(struct net_context *c,
5684 const DOM_SID *domain_sid,
5685 const char *domain_name,
5686 struct cli_state *cli,
5687 struct rpc_pipe_client *pipe_hnd,
5688 TALLOC_CTX *mem_ctx,
5692 POLICY_HND connect_pol, domain_pol, user_pol;
5693 NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
5695 DOM_SID trust_acct_sid;
5696 struct samr_Ids user_rids, name_types;
5697 struct lsa_String lsa_acct_name;
5700 d_printf("Usage: net rpc trustdom del <domain_name>\n");
5701 return NT_STATUS_INVALID_PARAMETER;
5705 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5707 acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]);
5709 if (acct_name == NULL)
5710 return NT_STATUS_NO_MEMORY;
5712 strupper_m(acct_name);
5714 /* Get samr policy handle */
5715 result = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
5717 MAXIMUM_ALLOWED_ACCESS,
5719 if (!NT_STATUS_IS_OK(result)) {
5723 /* Get domain policy handle */
5724 result = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
5726 MAXIMUM_ALLOWED_ACCESS,
5727 CONST_DISCARD(struct dom_sid2 *, domain_sid),
5729 if (!NT_STATUS_IS_OK(result)) {
5733 init_lsa_String(&lsa_acct_name, acct_name);
5735 result = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
5742 if (!NT_STATUS_IS_OK(result)) {
5743 d_printf("net rpc trustdom del: LookupNames on user %s failed %s\n",
5744 acct_name, nt_errstr(result) );
5748 result = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
5750 MAXIMUM_ALLOWED_ACCESS,
5754 if (!NT_STATUS_IS_OK(result)) {
5755 d_printf("net rpc trustdom del: OpenUser on user %s failed %s\n",
5756 acct_name, nt_errstr(result) );
5760 /* append the rid to the domain sid */
5761 sid_copy(&trust_acct_sid, domain_sid);
5762 if (!sid_append_rid(&trust_acct_sid, user_rids.ids[0])) {
5766 /* remove the sid */
5768 result = rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd, mem_ctx,
5771 if (!NT_STATUS_IS_OK(result)) {
5772 d_printf("net rpc trustdom del: RemoveMemberFromForeignDomain on user %s failed %s\n",
5773 acct_name, nt_errstr(result) );
5779 result = rpccli_samr_DeleteUser(pipe_hnd, mem_ctx,
5782 if (!NT_STATUS_IS_OK(result)) {
5783 d_printf("net rpc trustdom del: DeleteUser on user %s failed %s\n",
5784 acct_name, nt_errstr(result) );
5788 if (!NT_STATUS_IS_OK(result)) {
5789 d_printf("Could not set trust account password: %s\n",
5799 * Delete interdomain trust account for a remote domain.
5801 * @param argc Standard argc.
5802 * @param argv Standard argv without initial components.
5804 * @return Integer status (0 means success).
5807 static int rpc_trustdom_del(struct net_context *c, int argc, const char **argv)
5809 if (argc > 0 && !c->display_usage) {
5810 return run_rpc_command(c, NULL, &ndr_table_samr.syntax_id, 0,
5811 rpc_trustdom_del_internals, argc, argv);
5814 "net rpc trustdom del <domain>\n");
5819 static NTSTATUS rpc_trustdom_get_pdc(struct net_context *c,
5820 struct cli_state *cli,
5821 TALLOC_CTX *mem_ctx,
5822 const char *domain_name)
5824 char *dc_name = NULL;
5825 const char *buffer = NULL;
5826 struct rpc_pipe_client *netr;
5829 /* Use NetServerEnum2 */
5831 if (cli_get_pdc_name(cli, domain_name, &dc_name)) {
5833 return NT_STATUS_OK;
5836 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
5837 for domain %s\n", domain_name));
5839 /* Try netr_GetDcName */
5841 status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
5843 if (!NT_STATUS_IS_OK(status)) {
5847 status = rpccli_netr_GetDcName(netr, mem_ctx,
5854 if (NT_STATUS_IS_OK(status)) {
5858 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
5859 for domain %s\n", domain_name));
5865 * Establish trust relationship to a trusting domain.
5866 * Interdomain account must already be created on remote PDC.
5868 * @param c A net_context structure.
5869 * @param argc Standard argc.
5870 * @param argv Standard argv without initial components.
5872 * @return Integer status (0 means success).
5875 static int rpc_trustdom_establish(struct net_context *c, int argc,
5878 struct cli_state *cli = NULL;
5879 struct sockaddr_storage server_ss;
5880 struct rpc_pipe_client *pipe_hnd = NULL;
5881 POLICY_HND connect_hnd;
5882 TALLOC_CTX *mem_ctx;
5884 DOM_SID *domain_sid;
5889 union lsa_PolicyInformation *info = NULL;
5892 * Connect to \\server\ipc$ as 'our domain' account with password
5895 if (argc != 1 || c->display_usage) {
5897 "net rpc trustdom establish <domain_name>\n");
5901 domain_name = smb_xstrdup(argv[0]);
5902 strupper_m(domain_name);
5904 /* account name used at first is our domain's name with '$' */
5905 asprintf(&acct_name, "%s$", lp_workgroup());
5906 strupper_m(acct_name);
5909 * opt_workgroup will be used by connection functions further,
5910 * hence it should be set to remote domain name instead of ours
5912 if (c->opt_workgroup) {
5913 c->opt_workgroup = smb_xstrdup(domain_name);
5916 c->opt_user_name = acct_name;
5918 /* find the domain controller */
5919 if (!net_find_pdc(&server_ss, pdc_name, domain_name)) {
5920 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name));
5924 /* connect to ipc$ as username/password */
5925 nt_status = connect_to_ipc(c, &cli, &server_ss, pdc_name);
5926 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT)) {
5928 /* Is it trusting domain account for sure ? */
5929 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5930 nt_errstr(nt_status)));
5934 /* store who we connected to */
5936 saf_store( domain_name, pdc_name );
5939 * Connect to \\server\ipc$ again (this time anonymously)
5942 nt_status = connect_to_ipc_anonymous(c, &cli, &server_ss,
5945 if (NT_STATUS_IS_ERR(nt_status)) {
5946 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5947 domain_name, nt_errstr(nt_status)));
5951 if (!(mem_ctx = talloc_init("establishing trust relationship to "
5952 "domain %s", domain_name))) {
5953 DEBUG(0, ("talloc_init() failed\n"));
5958 /* Make sure we're talking to a proper server */
5960 nt_status = rpc_trustdom_get_pdc(c, cli, mem_ctx, domain_name);
5961 if (!NT_STATUS_IS_OK(nt_status)) {
5963 talloc_destroy(mem_ctx);
5968 * Call LsaOpenPolicy and LsaQueryInfo
5971 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
5973 if (!NT_STATUS_IS_OK(nt_status)) {
5974 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
5976 talloc_destroy(mem_ctx);
5980 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, true, SEC_RIGHTS_QUERY_VALUE,
5982 if (NT_STATUS_IS_ERR(nt_status)) {
5983 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5984 nt_errstr(nt_status)));
5986 talloc_destroy(mem_ctx);
5990 /* Querying info level 5 */
5992 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
5994 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
5996 if (NT_STATUS_IS_ERR(nt_status)) {
5997 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5998 nt_errstr(nt_status)));
6000 talloc_destroy(mem_ctx);
6004 domain_sid = info->account_domain.sid;
6006 /* There should be actually query info level 3 (following nt serv behaviour),
6007 but I still don't know if it's _really_ necessary */
6010 * Store the password in secrets db
6013 if (!pdb_set_trusteddom_pw(domain_name, c->opt_password, domain_sid)) {
6014 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6016 talloc_destroy(mem_ctx);
6021 * Close the pipes and clean up
6024 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6025 if (NT_STATUS_IS_ERR(nt_status)) {
6026 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
6027 nt_errstr(nt_status)));
6029 talloc_destroy(mem_ctx);
6035 talloc_destroy(mem_ctx);
6037 d_printf("Trust to domain %s established\n", domain_name);
6042 * Revoke trust relationship to the remote domain.
6044 * @param c A net_context structure.
6045 * @param argc Standard argc.
6046 * @param argv Standard argv without initial components.
6048 * @return Integer status (0 means success).
6051 static int rpc_trustdom_revoke(struct net_context *c, int argc,
6057 if (argc < 1 || c->display_usage) {
6059 "net rpc trustdom revoke <domain_name>\n"
6060 " Revoke trust relationship\n"
6061 " domain_name\tName of domain to revoke trust\n");
6065 /* generate upper cased domain name */
6066 domain_name = smb_xstrdup(argv[0]);
6067 strupper_m(domain_name);
6069 /* delete password of the trust */
6070 if (!pdb_del_trusteddom_pw(domain_name)) {
6071 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
6078 SAFE_FREE(domain_name);
6082 static NTSTATUS rpc_query_domain_sid(struct net_context *c,
6083 const DOM_SID *domain_sid,
6084 const char *domain_name,
6085 struct cli_state *cli,
6086 struct rpc_pipe_client *pipe_hnd,
6087 TALLOC_CTX *mem_ctx,
6092 sid_to_fstring(str_sid, domain_sid);
6093 d_printf("%s\n", str_sid);
6094 return NT_STATUS_OK;
6097 static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
6099 fstring ascii_sid, padding;
6100 int pad_len, col_len = 20;
6102 /* convert sid into ascii string */
6103 sid_to_fstring(ascii_sid, dom_sid);
6105 /* calculate padding space for d_printf to look nicer */
6106 pad_len = col_len - strlen(trusted_dom_name);
6107 padding[pad_len] = 0;
6108 do padding[--pad_len] = ' '; while (pad_len);
6110 d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
6113 static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
6114 TALLOC_CTX *mem_ctx,
6117 const char *trusted_dom_name)
6120 union lsa_TrustedDomainInfo *info = NULL;
6121 char *cleartextpwd = NULL;
6122 uint8_t nt_hash[16];
6125 nt_status = rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd, mem_ctx,
6128 LSA_TRUSTED_DOMAIN_INFO_PASSWORD,
6130 if (NT_STATUS_IS_ERR(nt_status)) {
6131 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
6132 nt_errstr(nt_status)));
6136 data = data_blob(info->password.password->data,
6137 info->password.password->length);
6139 if (!rpccli_get_pwd_hash(pipe_hnd, nt_hash)) {
6140 DEBUG(0, ("Could not retrieve password hash\n"));
6144 cleartextpwd = decrypt_trustdom_secret(nt_hash, &data);
6146 if (cleartextpwd == NULL) {
6147 DEBUG(0,("retrieved NULL password\n"));
6148 nt_status = NT_STATUS_UNSUCCESSFUL;
6152 if (!pdb_set_trusteddom_pw(trusted_dom_name, cleartextpwd, &dom_sid)) {
6153 DEBUG(0, ("Storing password for trusted domain failed.\n"));
6154 nt_status = NT_STATUS_UNSUCCESSFUL;
6158 #ifdef DEBUG_PASSWORD
6159 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
6160 "password: [%s]\n", trusted_dom_name,
6161 sid_string_dbg(&dom_sid), cleartextpwd));
6165 SAFE_FREE(cleartextpwd);
6166 data_blob_free(&data);
6171 static int rpc_trustdom_vampire(struct net_context *c, int argc,
6174 /* common variables */
6175 TALLOC_CTX* mem_ctx;
6176 struct cli_state *cli = NULL;
6177 struct rpc_pipe_client *pipe_hnd = NULL;
6179 const char *domain_name = NULL;
6180 DOM_SID *queried_dom_sid;
6181 POLICY_HND connect_hnd;
6182 union lsa_PolicyInformation *info = NULL;
6184 /* trusted domains listing variables */
6185 unsigned int enum_ctx = 0;
6187 struct lsa_DomainList dom_list;
6190 if (c->display_usage) {
6192 "net rpc trustdom vampire\n"
6193 " Vampire trust relationship from remote server\n");
6198 * Listing trusted domains (stored in secrets.tdb, if local)
6201 mem_ctx = talloc_init("trust relationships vampire");
6204 * set domain and pdc name to local samba server (default)
6205 * or to remote one given in command line
6208 if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6209 domain_name = c->opt_workgroup;
6210 c->opt_target_workgroup = c->opt_workgroup;
6212 fstrcpy(pdc_name, global_myname());
6213 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6214 c->opt_target_workgroup = domain_name;
6217 /* open \PIPE\lsarpc and open policy handle */
6218 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6219 if (!NT_STATUS_IS_OK(nt_status)) {
6220 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6221 nt_errstr(nt_status)));
6222 talloc_destroy(mem_ctx);
6226 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6228 if (!NT_STATUS_IS_OK(nt_status)) {
6229 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6230 nt_errstr(nt_status) ));
6232 talloc_destroy(mem_ctx);
6236 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, SEC_RIGHTS_QUERY_VALUE,
6238 if (NT_STATUS_IS_ERR(nt_status)) {
6239 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6240 nt_errstr(nt_status)));
6242 talloc_destroy(mem_ctx);
6246 /* query info level 5 to obtain sid of a domain being queried */
6247 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6249 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6252 if (NT_STATUS_IS_ERR(nt_status)) {
6253 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6254 nt_errstr(nt_status)));
6256 talloc_destroy(mem_ctx);
6260 queried_dom_sid = info->account_domain.sid;
6263 * Keep calling LsaEnumTrustdom over opened pipe until
6264 * the end of enumeration is reached
6267 d_printf("Vampire trusted domains:\n\n");
6270 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6275 if (NT_STATUS_IS_ERR(nt_status)) {
6276 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6277 nt_errstr(nt_status)));
6279 talloc_destroy(mem_ctx);
6283 for (i = 0; i < dom_list.count; i++) {
6285 print_trusted_domain(dom_list.domains[i].sid,
6286 dom_list.domains[i].name.string);
6288 nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd,
6289 *dom_list.domains[i].sid,
6290 dom_list.domains[i].name.string);
6291 if (!NT_STATUS_IS_OK(nt_status)) {
6293 talloc_destroy(mem_ctx);
6299 * in case of no trusted domains say something rather
6300 * than just display blank line
6302 if (!dom_list.count) d_printf("none\n");
6304 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6306 /* close this connection before doing next one */
6307 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6308 if (NT_STATUS_IS_ERR(nt_status)) {
6309 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6310 nt_errstr(nt_status)));
6312 talloc_destroy(mem_ctx);
6316 /* close lsarpc pipe and connection to IPC$ */
6319 talloc_destroy(mem_ctx);
6323 static int rpc_trustdom_list(struct net_context *c, int argc, const char **argv)
6325 /* common variables */
6326 TALLOC_CTX* mem_ctx;
6327 struct cli_state *cli = NULL, *remote_cli = NULL;
6328 struct rpc_pipe_client *pipe_hnd = NULL;
6330 const char *domain_name = NULL;
6331 DOM_SID *queried_dom_sid;
6333 int ascii_dom_name_len;
6334 POLICY_HND connect_hnd;
6335 union lsa_PolicyInformation *info = NULL;
6337 /* trusted domains listing variables */
6338 unsigned int num_domains, enum_ctx = 0;
6339 int i, pad_len, col_len = 20;
6340 struct lsa_DomainList dom_list;
6343 /* trusting domains listing variables */
6344 POLICY_HND domain_hnd;
6345 struct samr_SamArray *trusts = NULL;
6347 if (c->display_usage) {
6349 "net rpc trustdom list\n"
6350 " List trust relationships\n");
6355 * Listing trusted domains (stored in secrets.tdb, if local)
6358 mem_ctx = talloc_init("trust relationships listing");
6361 * set domain and pdc name to local samba server (default)
6362 * or to remote one given in command line
6365 if (StrCaseCmp(c->opt_workgroup, lp_workgroup())) {
6366 domain_name = c->opt_workgroup;
6367 c->opt_target_workgroup = c->opt_workgroup;
6369 fstrcpy(pdc_name, global_myname());
6370 domain_name = talloc_strdup(mem_ctx, lp_workgroup());
6371 c->opt_target_workgroup = domain_name;
6374 /* open \PIPE\lsarpc and open policy handle */
6375 nt_status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
6376 if (!NT_STATUS_IS_OK(nt_status)) {
6377 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6378 nt_errstr(nt_status)));
6379 talloc_destroy(mem_ctx);
6383 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
6385 if (!NT_STATUS_IS_OK(nt_status)) {
6386 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6387 nt_errstr(nt_status) ));
6389 talloc_destroy(mem_ctx);
6393 nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, false, SEC_RIGHTS_QUERY_VALUE,
6395 if (NT_STATUS_IS_ERR(nt_status)) {
6396 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6397 nt_errstr(nt_status)));
6399 talloc_destroy(mem_ctx);
6403 /* query info level 5 to obtain sid of a domain being queried */
6404 nt_status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
6406 LSA_POLICY_INFO_ACCOUNT_DOMAIN,
6409 if (NT_STATUS_IS_ERR(nt_status)) {
6410 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6411 nt_errstr(nt_status)));
6413 talloc_destroy(mem_ctx);
6417 queried_dom_sid = info->account_domain.sid;
6420 * Keep calling LsaEnumTrustdom over opened pipe until
6421 * the end of enumeration is reached
6424 d_printf("Trusted domains list:\n\n");
6427 nt_status = rpccli_lsa_EnumTrustDom(pipe_hnd, mem_ctx,
6432 if (NT_STATUS_IS_ERR(nt_status)) {
6433 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6434 nt_errstr(nt_status)));
6436 talloc_destroy(mem_ctx);
6440 for (i = 0; i < dom_list.count; i++) {
6441 print_trusted_domain(dom_list.domains[i].sid,
6442 dom_list.domains[i].name.string);
6446 * in case of no trusted domains say something rather
6447 * than just display blank line
6449 if (!dom_list.count) d_printf("none\n");
6451 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6453 /* close this connection before doing next one */
6454 nt_status = rpccli_lsa_Close(pipe_hnd, mem_ctx, &connect_hnd);
6455 if (NT_STATUS_IS_ERR(nt_status)) {
6456 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6457 nt_errstr(nt_status)));
6459 talloc_destroy(mem_ctx);
6463 TALLOC_FREE(pipe_hnd);
6466 * Listing trusting domains (stored in passdb backend, if local)
6469 d_printf("\nTrusting domains list:\n\n");
6472 * Open \PIPE\samr and get needed policy handles
6474 nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
6476 if (!NT_STATUS_IS_OK(nt_status)) {
6477 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
6479 talloc_destroy(mem_ctx);
6484 nt_status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
6486 SA_RIGHT_SAM_OPEN_DOMAIN,
6488 if (!NT_STATUS_IS_OK(nt_status)) {
6489 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6490 nt_errstr(nt_status)));
6492 talloc_destroy(mem_ctx);
6496 /* SamrOpenDomain - we have to open domain policy handle in order to be
6497 able to enumerate accounts*/
6498 nt_status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
6500 SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
6503 if (!NT_STATUS_IS_OK(nt_status)) {
6504 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6505 nt_errstr(nt_status)));
6507 talloc_destroy(mem_ctx);
6512 * perform actual enumeration
6515 enum_ctx = 0; /* reset enumeration context from last enumeration */
6518 nt_status = rpccli_samr_EnumDomainUsers(pipe_hnd, mem_ctx,
6525 if (NT_STATUS_IS_ERR(nt_status)) {
6526 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6527 nt_errstr(nt_status)));
6529 talloc_destroy(mem_ctx);
6533 for (i = 0; i < num_domains; i++) {
6535 char *str = CONST_DISCARD(char *, trusts->entries[i].name.string);
6538 * get each single domain's sid (do we _really_ need this ?):
6539 * 1) connect to domain's pdc
6540 * 2) query the pdc for domain's sid
6543 /* get rid of '$' tail */
6544 ascii_dom_name_len = strlen(str);
6545 if (ascii_dom_name_len && ascii_dom_name_len < FSTRING_LEN)
6546 str[ascii_dom_name_len - 1] = '\0';
6548 /* calculate padding space for d_printf to look nicer */
6549 pad_len = col_len - strlen(str);
6550 padding[pad_len] = 0;
6551 do padding[--pad_len] = ' '; while (pad_len);
6553 /* set opt_* variables to remote domain */
6555 c->opt_workgroup = talloc_strdup(mem_ctx, str);
6556 c->opt_target_workgroup = c->opt_workgroup;
6558 d_printf("%s%s", str, padding);
6560 /* connect to remote domain controller */
6561 nt_status = net_make_ipc_connection(c,
6562 NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS,
6564 if (NT_STATUS_IS_OK(nt_status)) {
6565 /* query for domain's sid */
6566 if (run_rpc_command(
6568 &ndr_table_lsarpc.syntax_id, 0,
6569 rpc_query_domain_sid, argc,
6571 d_fprintf(stderr, "couldn't get domain's sid\n");
6573 cli_shutdown(remote_cli);
6576 d_fprintf(stderr, "domain controller is not "
6578 nt_errstr(nt_status));
6582 if (!num_domains) d_printf("none\n");
6584 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
6586 /* close opened samr and domain policy handles */
6587 nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_hnd);
6588 if (!NT_STATUS_IS_OK(nt_status)) {
6589 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
6592 nt_status = rpccli_samr_Close(pipe_hnd, mem_ctx, &connect_hnd);
6593 if (!NT_STATUS_IS_OK(nt_status)) {
6594 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
6597 /* close samr pipe and connection to IPC$ */
6600 talloc_destroy(mem_ctx);
6605 * Entrypoint for 'net rpc trustdom' code.
6607 * @param argc Standard argc.
6608 * @param argv Standard argv without initial components.
6610 * @return Integer status (0 means success).
6613 static int rpc_trustdom(struct net_context *c, int argc, const char **argv)
6615 struct functable func[] = {
6620 "Add trusted domain's account",
6621 "net rpc trustdom add\n"
6622 " Add trusted domain's account"
6628 "Remove trusted domain's account",
6629 "net rpc trustdom del\n"
6630 " Remove trusted domain's account"
6634 rpc_trustdom_establish,
6636 "Establish trust relationship",
6637 "net rpc trustdom establish\n"
6638 " Establish trust relationship"
6642 rpc_trustdom_revoke,
6644 "Revoke trust relationship",
6645 "net rpc trustdom revoke\n"
6646 " Revoke trust relationship"
6652 "List domain trusts",
6653 "net rpc trustdom list\n"
6654 " List domain trusts"
6658 rpc_trustdom_vampire,
6660 "Vampire trusts from remote server",
6661 "net rpc trustdom vampire\n"
6662 " Vampire trusts from remote server"
6664 {NULL, NULL, 0, NULL, NULL}
6667 return net_run_function(c, argc, argv, "net rpc trustdom", func);
6671 * Check if a server will take rpc commands
6672 * @param flags Type of server to connect to (PDC, DMB, localhost)
6673 * if the host is not explicitly specified
6674 * @return bool (true means rpc supported)
6676 bool net_rpc_check(struct net_context *c, unsigned flags)
6678 struct cli_state *cli;
6680 struct sockaddr_storage server_ss;
6681 char *server_name = NULL;
6684 /* flags (i.e. server type) may depend on command */
6685 if (!net_find_server(c, NULL, flags, &server_ss, &server_name))
6688 if ((cli = cli_initialise()) == NULL) {
6692 status = cli_connect(cli, server_name, &server_ss);
6693 if (!NT_STATUS_IS_OK(status))
6695 if (!attempt_netbios_session_request(&cli, global_myname(),
6696 server_name, &server_ss))
6698 if (!cli_negprot(cli))
6700 if (cli->protocol < PROTOCOL_NT1)
6709 /* dump sam database via samsync rpc calls */
6710 static int rpc_samdump(struct net_context *c, int argc, const char **argv) {
6711 if (c->display_usage) {
6714 " Dump remote SAM database\n");
6718 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6719 NET_FLAGS_ANONYMOUS,
6720 rpc_samdump_internals, argc, argv);
6723 /* syncronise sam database via samsync rpc calls */
6724 static int rpc_vampire(struct net_context *c, int argc, const char **argv)
6726 struct functable func[] = {
6731 "Dump remote SAM database to ldif",
6732 "net rpc vampire ldif\n"
6733 " Dump remote SAM database to LDIF file or stdout"
6739 "Dump remote SAM database to Kerberos Keytab",
6740 "net rpc vampire keytab\n"
6741 " Dump remote SAM database to Kerberos keytab file"
6744 {NULL, NULL, 0, NULL, NULL}
6748 if (c->display_usage) {
6751 " Vampire remote SAM database\n");
6755 return run_rpc_command(c, NULL, &ndr_table_netlogon.syntax_id,
6756 NET_FLAGS_ANONYMOUS,
6757 rpc_vampire_internals,
6761 return net_run_function(c, argc, argv, "net rpc vampire", func);
6765 * Migrate everything from a print server.
6767 * @param c A net_context structure.
6768 * @param argc Standard main() style argc.
6769 * @param argv Standard main() style argv. Initial components are already
6772 * @return A shell status integer (0 for success).
6774 * The order is important !
6775 * To successfully add drivers the print queues have to exist !
6776 * Applying ACLs should be the last step, because you're easily locked out.
6779 static int rpc_printer_migrate_all(struct net_context *c, int argc,
6784 if (c->display_usage) {
6786 "net rpc printer migrate all\n"
6787 " Migrate everything from a print server\n");
6792 d_printf("no server to migrate\n");
6796 ret = run_rpc_command(c, NULL, &syntax_spoolss, 0,
6797 rpc_printer_migrate_printers_internals, argc,
6802 ret = run_rpc_command(c, NULL, &syntax_spoolss, 0,
6803 rpc_printer_migrate_drivers_internals, argc,
6808 ret = run_rpc_command(c, NULL, &syntax_spoolss, 0,
6809 rpc_printer_migrate_forms_internals, argc, argv);
6813 ret = run_rpc_command(c, NULL, &syntax_spoolss, 0,
6814 rpc_printer_migrate_settings_internals, argc,
6819 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
6820 rpc_printer_migrate_security_internals, argc,
6826 * Migrate print drivers from a print server.
6828 * @param c A net_context structure.
6829 * @param argc Standard main() style argc.
6830 * @param argv Standard main() style argv. Initial components are already
6833 * @return A shell status integer (0 for success).
6835 static int rpc_printer_migrate_drivers(struct net_context *c, int argc,
6838 if (c->display_usage) {
6840 "net rpc printer migrate drivers\n"
6841 " Migrate print-drivers from a print-server\n");
6846 d_printf("no server to migrate\n");
6850 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
6851 rpc_printer_migrate_drivers_internals,
6856 * Migrate print-forms from a print-server.
6858 * @param c A net_context structure.
6859 * @param argc Standard main() style argc.
6860 * @param argv Standard main() style argv. Initial components are already
6863 * @return A shell status integer (0 for success).
6865 static int rpc_printer_migrate_forms(struct net_context *c, int argc,
6868 if (c->display_usage) {
6870 "net rpc printer migrate forms\n"
6871 " Migrate print-forms from a print-server\n");
6876 d_printf("no server to migrate\n");
6880 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
6881 rpc_printer_migrate_forms_internals,
6886 * Migrate printers from a print-server.
6888 * @param c A net_context structure.
6889 * @param argc Standard main() style argc.
6890 * @param argv Standard main() style argv. Initial components are already
6893 * @return A shell status integer (0 for success).
6895 static int rpc_printer_migrate_printers(struct net_context *c, int argc,
6898 if (c->display_usage) {
6900 "net rpc printer migrate printers\n"
6901 " Migrate printers from a print-server\n");
6906 d_printf("no server to migrate\n");
6910 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
6911 rpc_printer_migrate_printers_internals,
6916 * Migrate printer-ACLs from a print-server
6918 * @param c A net_context structure.
6919 * @param argc Standard main() style argc.
6920 * @param argv Standard main() style argv. Initial components are already
6923 * @return A shell status integer (0 for success).
6925 static int rpc_printer_migrate_security(struct net_context *c, int argc,
6928 if (c->display_usage) {
6930 "net rpc printer migrate security\n"
6931 " Migrate printer-ACLs from a print-server\n");
6936 d_printf("no server to migrate\n");
6940 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
6941 rpc_printer_migrate_security_internals,
6946 * Migrate printer-settings from a print-server.
6948 * @param c A net_context structure.
6949 * @param argc Standard main() style argc.
6950 * @param argv Standard main() style argv. Initial components are already
6953 * @return A shell status integer (0 for success).
6955 static int rpc_printer_migrate_settings(struct net_context *c, int argc,
6958 if (c->display_usage) {
6960 "net rpc printer migrate settings\n"
6961 " Migrate printer-settings from a print-server\n");
6966 d_printf("no server to migrate\n");
6970 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
6971 rpc_printer_migrate_settings_internals,
6976 * 'net rpc printer' entrypoint.
6978 * @param c A net_context structure.
6979 * @param argc Standard main() style argc.
6980 * @param argv Standard main() style argv. Initial components are already
6984 int rpc_printer_migrate(struct net_context *c, int argc, const char **argv)
6987 /* ouch: when addriver and setdriver are called from within
6988 rpc_printer_migrate_drivers_internals, the printer-queue already
6991 struct functable func[] = {
6994 rpc_printer_migrate_all,
6996 "Migrate all from remote to local print server",
6997 "net rpc printer migrate all\n"
6998 " Migrate all from remote to local print server"
7002 rpc_printer_migrate_drivers,
7004 "Migrate drivers to local server",
7005 "net rpc printer migrate drivers\n"
7006 " Migrate drivers to local server"
7010 rpc_printer_migrate_forms,
7012 "Migrate froms to local server",
7013 "net rpc printer migrate forms\n"
7014 " Migrate froms to local server"
7018 rpc_printer_migrate_printers,
7020 "Migrate printers to local server",
7021 "net rpc printer migrate printers\n"
7022 " Migrate printers to local server"
7026 rpc_printer_migrate_security,
7028 "Mirgate printer ACLs to local server",
7029 "net rpc printer migrate security\n"
7030 " Mirgate printer ACLs to local server"
7034 rpc_printer_migrate_settings,
7036 "Migrate printer settings to local server",
7037 "net rpc printer migrate settings\n"
7038 " Migrate printer settings to local server"
7040 {NULL, NULL, 0, NULL, NULL}
7043 return net_run_function(c, argc, argv, "net rpc printer migrate",func);
7048 * List printers on a remote RPC server.
7050 * @param c A net_context structure.
7051 * @param argc Standard main() style argc.
7052 * @param argv Standard main() style argv. Initial components are already
7055 * @return A shell status integer (0 for success).
7057 static int rpc_printer_list(struct net_context *c, int argc, const char **argv)
7059 if (c->display_usage) {
7061 "net rpc printer list\n"
7062 " List printers on a remote RPC server\n");
7066 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
7067 rpc_printer_list_internals,
7072 * List printer-drivers on a remote RPC server.
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
7079 * @return A shell status integer (0 for success).
7081 static int rpc_printer_driver_list(struct net_context *c, int argc,
7084 if (c->display_usage) {
7086 "net rpc printer driver\n"
7087 " List printer-drivers on a remote RPC server\n");
7091 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
7092 rpc_printer_driver_list_internals,
7097 * Publish printer in ADS via MSRPC.
7099 * @param c A net_context structure.
7100 * @param argc Standard main() style argc.
7101 * @param argv Standard main() style argv. Initial components are already
7104 * @return A shell status integer (0 for success).
7106 static int rpc_printer_publish_publish(struct net_context *c, int argc,
7109 if (c->display_usage) {
7111 "net rpc printer publish publish\n"
7112 " Publish printer in ADS via MSRPC\n");
7116 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
7117 rpc_printer_publish_publish_internals,
7122 * Update printer in ADS via MSRPC.
7124 * @param c A net_context structure.
7125 * @param argc Standard main() style argc.
7126 * @param argv Standard main() style argv. Initial components are already
7129 * @return A shell status integer (0 for success).
7131 static int rpc_printer_publish_update(struct net_context *c, int argc, const char **argv)
7133 if (c->display_usage) {
7135 "net rpc printer publish update\n"
7136 " Update printer in ADS via MSRPC\n");
7140 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
7141 rpc_printer_publish_update_internals,
7146 * UnPublish printer in ADS via MSRPC.
7148 * @param c A net_context structure.
7149 * @param argc Standard main() style argc.
7150 * @param argv Standard main() style argv. Initial components are already
7153 * @return A shell status integer (0 for success).
7155 static int rpc_printer_publish_unpublish(struct net_context *c, int argc,
7158 if (c->display_usage) {
7160 "net rpc printer publish unpublish\n"
7161 " UnPublish printer in ADS via MSRPC\n");
7165 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
7166 rpc_printer_publish_unpublish_internals,
7171 * List published printers via MSRPC.
7173 * @param c A net_context structure.
7174 * @param argc Standard main() style argc.
7175 * @param argv Standard main() style argv. Initial components are already
7178 * @return A shell status integer (0 for success).
7180 static int rpc_printer_publish_list(struct net_context *c, int argc,
7183 if (c->display_usage) {
7185 "net rpc printer publish list\n"
7186 " List published printers via MSRPC\n");
7190 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
7191 rpc_printer_publish_list_internals,
7197 * Publish printer in ADS.
7199 * @param c A net_context structure.
7200 * @param argc Standard main() style argc.
7201 * @param argv Standard main() style argv. Initial components are already
7204 * @return A shell status integer (0 for success).
7206 static int rpc_printer_publish(struct net_context *c, int argc,
7210 struct functable func[] = {
7213 rpc_printer_publish_publish,
7215 "Publish printer in AD",
7216 "net rpc printer publish publish\n"
7217 " Publish printer in AD"
7221 rpc_printer_publish_update,
7223 "Update printer in AD",
7224 "net rpc printer publish update\n"
7225 " Update printer in AD"
7229 rpc_printer_publish_unpublish,
7231 "Unpublish printer",
7232 "net rpc printer publish unpublish\n"
7233 " Unpublish printer"
7237 rpc_printer_publish_list,
7239 "List published printers",
7240 "net rpc printer publish list\n"
7241 " List published printers"
7243 {NULL, NULL, 0, NULL, NULL}
7247 if (c->display_usage) {
7248 d_printf("Usage:\n");
7249 d_printf("net rpc printer publish\n"
7250 " List published printers\n"
7251 " Alias of net rpc printer publish list\n");
7252 net_display_usage_from_functable(func);
7255 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
7256 rpc_printer_publish_list_internals,
7260 return net_run_function(c, argc, argv, "net rpc printer publish",func);
7266 * Display rpc printer help page.
7268 * @param c A net_context structure.
7269 * @param argc Standard main() style argc.
7270 * @param argv Standard main() style argv. Initial components are already
7273 int rpc_printer_usage(struct net_context *c, int argc, const char **argv)
7275 d_printf("net rpc printer LIST [printer] [misc. options] [targets]\n"
7276 "\tlists all printers on print-server\n\n");
7277 d_printf("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
7278 "\tlists all printer-drivers on print-server\n\n");
7279 d_printf("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
7280 "\tpublishes printer settings in Active Directory\n"
7281 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n");
7282 d_printf("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
7283 "\n\tmigrates printers from remote to local server\n\n");
7284 d_printf("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
7285 "\n\tmigrates printer-settings from remote to local server\n\n");
7286 d_printf("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
7287 "\n\tmigrates printer-drivers from remote to local server\n\n");
7288 d_printf("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
7289 "\n\tmigrates printer-forms from remote to local server\n\n");
7290 d_printf("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
7291 "\n\tmigrates printer-ACLs from remote to local server\n\n");
7292 d_printf("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
7293 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
7294 "\tremote to local print-server\n\n");
7295 net_common_methods_usage(c, argc, argv);
7296 net_common_flags_usage(c, argc, argv);
7298 "\t-v or --verbose\t\t\tgive verbose output\n"
7299 "\t --destination\t\tmigration target server (default: localhost)\n");
7305 * 'net rpc printer' entrypoint.
7307 * @param c A net_context structure.
7308 * @param argc Standard main() style argc.
7309 * @param argv Standard main() style argv. Initial components are already
7312 int net_rpc_printer(struct net_context *c, int argc, const char **argv)
7314 struct functable func[] = {
7319 "List all printers on print server",
7320 "net rpc printer list\n"
7321 " List all printers on print server"
7325 rpc_printer_migrate,
7327 "Migrate printer to local server",
7328 "net rpc printer migrate\n"
7329 " Migrate printer to local server"
7333 rpc_printer_driver_list,
7335 "List printer drivers",
7336 "net rpc printer driver\n"
7337 " List printer drivers"
7341 rpc_printer_publish,
7343 "Publish printer in AD",
7344 "net rpc printer publish\n"
7345 " Publish printer in AD"
7347 {NULL, NULL, 0, NULL, NULL}
7351 if (c->display_usage) {
7352 d_printf("Usage:\n");
7353 d_printf("net rpc printer\n"
7354 " List printers\n");
7355 net_display_usage_from_functable(func);
7358 return run_rpc_command(c, NULL, &syntax_spoolss, 0,
7359 rpc_printer_list_internals,
7363 return net_run_function(c, argc, argv, "net rpc printer", func);
7367 * 'net rpc' entrypoint.
7369 * @param c A net_context structure.
7370 * @param argc Standard main() style argc.
7371 * @param argv Standard main() style argv. Initial components are already
7375 int net_rpc(struct net_context *c, int argc, const char **argv)
7377 struct functable func[] = {
7382 "Modify global audit settings",
7384 " Modify global audit settings"
7390 "Show basic info about a domain",
7392 " Show basic info about a domain"
7406 "Join a domain created in server manager",
7408 " Join a domain created in server manager"
7414 "Test that a join is valid",
7415 "net rpc testjoin\n"
7416 " Test that a join is valid"
7422 "List/modify users",
7424 " List/modify users"
7430 "Change a user password",
7431 "net rpc password\n"
7432 " Change a user password\n"
7433 " Alias for net rpc user password"
7439 "List/modify groups",
7441 " List/modify groups"
7447 "List/modify shares",
7449 " List/modify shares"
7463 "List/modify printers",
7465 " List/modify printers"
7469 net_rpc_changetrustpw,
7471 "Change trust account password",
7472 "net rpc changetrustpw\n"
7473 " Change trust account password"
7479 "Modify domain trusts",
7480 "net rpc trustdom\n"
7481 " Modify domain trusts"
7487 "Abort a remote shutdown",
7488 "net rpc abortshutdown\n"
7489 " Abort a remote shutdown"
7495 "Shutdown a remote server",
7496 "net rpc shutdown\n"
7497 " Shutdown a remote server"
7503 "Dump SAM data of remote NT PDC",
7505 " Dump SAM data of remote NT PDC"
7511 "Sync a remote NT PDC's data into local passdb",
7513 " Sync a remote NT PDC's data into local passdb"
7519 "Fetch the domain sid into local secrets.tdb",
7521 " Fetch the domain sid into local secrets.tdb"
7527 "Manage privileges assigned to SID",
7529 " Manage privileges assigned to SID"
7535 "Start/stop/query remote services",
7537 " Start/stop/query remote services"
7543 "Manage registry hives",
7544 "net rpc registry\n"
7545 " Manage registry hives"
7551 "Open interactive shell on remote server",
7553 " Open interactive shell on remote server"
7555 {NULL, NULL, 0, NULL, NULL}
7557 return net_run_function(c, argc, argv, "net rpc", func);