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
;
125 /* make use of cli_state handed over as an argument, if possible */
127 nt_status
= net_make_ipc_connection(c
, conn_flags
, &cli
);
128 if (!NT_STATUS_IS_OK(nt_status
)) {
129 DEBUG(1, ("failed to make ipc connection: %s\n",
130 nt_errstr(nt_status
)));
143 if (!(mem_ctx
= talloc_init("run_rpc_command"))) {
144 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
)) {
154 if (!(conn_flags
& NET_FLAGS_NO_PIPE
)) {
155 if (lp_client_schannel()
156 && (ndr_syntax_id_equal(interface
,
157 &ndr_table_netlogon
.syntax_id
))) {
158 /* Always try and create an schannel netlogon pipe. */
159 nt_status
= cli_rpc_pipe_open_schannel(
160 cli
, interface
, NCACN_NP
,
161 PIPE_AUTH_LEVEL_PRIVACY
, domain_name
,
163 if (!NT_STATUS_IS_OK(nt_status
)) {
164 DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
165 nt_errstr(nt_status
) ));
169 if (conn_flags
& NET_FLAGS_SEAL
) {
170 nt_status
= cli_rpc_pipe_open_ntlmssp(
172 (conn_flags
& NET_FLAGS_TCP
) ?
173 NCACN_IP_TCP
: NCACN_NP
,
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
) ));
192 nt_status
= fn(c
, domain_sid
, domain_name
, cli
, pipe_hnd
, mem_ctx
, argc
, argv
);
194 if (!NT_STATUS_IS_OK(nt_status
)) {
195 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
);
208 /* close the connection only if it was opened here */
213 talloc_destroy(mem_ctx
);
218 * Force a change of the trust acccount password.
220 * All parameters are provided by the run_rpc_command function, except for
221 * argc, argv which are passed through.
223 * @param domain_sid The domain sid acquired from the remote server.
224 * @param cli A cli_state connected to the server.
225 * @param mem_ctx Talloc context, destroyed on completion of the function.
226 * @param argc Standard main() style argc.
227 * @param argv Standard main() style argv. Initial components are already
230 * @return Normal NTSTATUS return.
233 static NTSTATUS
rpc_changetrustpw_internals(struct net_context
*c
,
234 const DOM_SID
*domain_sid
,
235 const char *domain_name
,
236 struct cli_state
*cli
,
237 struct rpc_pipe_client
*pipe_hnd
,
243 return trust_pw_find_change_and_store_it(pipe_hnd
, mem_ctx
, c
->opt_target_workgroup
);
247 * Force a change of the trust acccount password.
249 * @param argc Standard main() style argc.
250 * @param argv Standard main() style argv. Initial components are already
253 * @return A shell status integer (0 for success).
256 int net_rpc_changetrustpw(struct net_context
*c
, int argc
, const char **argv
)
258 if (c
->display_usage
) {
260 "net rpc changetrustpw\n"
261 " Change the machine trust password\n");
265 return run_rpc_command(c
, NULL
, &ndr_table_netlogon
.syntax_id
,
266 NET_FLAGS_ANONYMOUS
| NET_FLAGS_PDC
,
267 rpc_changetrustpw_internals
,
272 * Join a domain, the old way.
274 * This uses 'machinename' as the inital password, and changes it.
276 * The password should be created with 'server manager' or equiv first.
278 * All parameters are provided by the run_rpc_command function, except for
279 * argc, argv which are passed through.
281 * @param domain_sid The domain sid acquired from the remote server.
282 * @param cli A cli_state connected to the server.
283 * @param mem_ctx Talloc context, destroyed on completion of the function.
284 * @param argc Standard main() style argc.
285 * @param argv Standard main() style argv. Initial components are already
288 * @return Normal NTSTATUS return.
291 static NTSTATUS
rpc_oldjoin_internals(struct net_context
*c
,
292 const DOM_SID
*domain_sid
,
293 const char *domain_name
,
294 struct cli_state
*cli
,
295 struct rpc_pipe_client
*pipe_hnd
,
301 fstring trust_passwd
;
302 unsigned char orig_trust_passwd_hash
[16];
304 uint32 sec_channel_type
;
306 result
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_netlogon
.syntax_id
,
308 if (!NT_STATUS_IS_OK(result
)) {
309 DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
312 nt_errstr(result
) ));
317 check what type of join - if the user want's to join as
318 a BDC, the server must agree that we are a BDC.
321 sec_channel_type
= get_sec_channel_type(argv
[0]);
323 sec_channel_type
= get_sec_channel_type(NULL
);
326 fstrcpy(trust_passwd
, global_myname());
327 strlower_m(trust_passwd
);
330 * Machine names can be 15 characters, but the max length on
331 * a password is 14. --jerry
334 trust_passwd
[14] = '\0';
336 E_md4hash(trust_passwd
, orig_trust_passwd_hash
);
338 result
= trust_pw_change_and_store_it(pipe_hnd
, mem_ctx
, c
->opt_target_workgroup
,
339 orig_trust_passwd_hash
,
342 if (NT_STATUS_IS_OK(result
))
343 printf("Joined domain %s.\n", c
->opt_target_workgroup
);
346 if (!secrets_store_domain_sid(c
->opt_target_workgroup
, domain_sid
)) {
347 DEBUG(0, ("error storing domain sid for %s\n", c
->opt_target_workgroup
));
348 result
= NT_STATUS_UNSUCCESSFUL
;
355 * Join a domain, the old way.
357 * @param argc Standard main() style argc.
358 * @param argv Standard main() style argv. Initial components are already
361 * @return A shell status integer (0 for success).
364 static int net_rpc_perform_oldjoin(struct net_context
*c
, int argc
, const char **argv
)
366 return run_rpc_command(c
, NULL
, &ndr_table_netlogon
.syntax_id
,
367 NET_FLAGS_NO_PIPE
| NET_FLAGS_ANONYMOUS
| NET_FLAGS_PDC
,
368 rpc_oldjoin_internals
,
373 * Join a domain, the old way. This function exists to allow
374 * the message to be displayed when oldjoin was explicitly
375 * requested, but not when it was implied by "net rpc join".
377 * @param argc Standard main() style argc.
378 * @param argv Standard main() style argv. Initial components are already
381 * @return A shell status integer (0 for success).
384 static int net_rpc_oldjoin(struct net_context
*c
, int argc
, const char **argv
)
388 if (c
->display_usage
) {
391 " Join a domain the old way\n");
395 rc
= net_rpc_perform_oldjoin(c
, argc
, argv
);
398 d_fprintf(stderr
, "Failed to join domain\n");
405 * 'net rpc join' entrypoint.
406 * @param argc Standard main() style argc.
407 * @param argv Standard main() style argv. Initial components are already
410 * Main 'net_rpc_join()' (where the admin username/password is used) is
412 * Try to just change the password, but if that doesn't work, use/prompt
413 * for a username/password.
416 int net_rpc_join(struct net_context
*c
, int argc
, const char **argv
)
418 if (c
->display_usage
) {
420 "net rpc join -U <username>[%%password] <type>\n"
422 " username\tName of the admin user"
423 " password\tPassword of the admin user, will "
424 "prompt if not specified\n"
425 " type\tCan be one of the following:\n"
426 "\t\tMEMBER\tJoin as member server (default)\n"
427 "\t\tBDC\tJoin as BDC\n"
428 "\t\tPDC\tJoin as PDC\n");
432 if (lp_server_role() == ROLE_STANDALONE
) {
433 d_printf("cannot join as standalone machine\n");
437 if (strlen(global_myname()) > 15) {
438 d_printf("Our netbios name can be at most 15 chars long, "
439 "\"%s\" is %u chars long\n",
440 global_myname(), (unsigned int)strlen(global_myname()));
444 if ((net_rpc_perform_oldjoin(c
, argc
, argv
) == 0))
447 return net_rpc_join_newstyle(c
, argc
, argv
);
451 * display info about a rpc domain
453 * All parameters are provided by the run_rpc_command function, except for
454 * argc, argv which are passed through.
456 * @param domain_sid The domain sid acquired from the remote server
457 * @param cli A cli_state connected to the server.
458 * @param mem_ctx Talloc context, destroyed on completion of the function.
459 * @param argc Standard main() style argc.
460 * @param argv Standard main() style argv. Initial components are already
463 * @return Normal NTSTATUS return.
466 NTSTATUS
rpc_info_internals(struct net_context
*c
,
467 const DOM_SID
*domain_sid
,
468 const char *domain_name
,
469 struct cli_state
*cli
,
470 struct rpc_pipe_client
*pipe_hnd
,
475 POLICY_HND connect_pol
, domain_pol
;
476 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
477 union samr_DomainInfo
*info
= NULL
;
480 sid_to_fstring(sid_str
, domain_sid
);
482 /* Get sam policy handle */
483 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
485 MAXIMUM_ALLOWED_ACCESS
,
487 if (!NT_STATUS_IS_OK(result
)) {
488 d_fprintf(stderr
, "Could not connect to SAM: %s\n", nt_errstr(result
));
492 /* Get domain policy handle */
493 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
495 MAXIMUM_ALLOWED_ACCESS
,
496 CONST_DISCARD(struct dom_sid2
*, domain_sid
),
498 if (!NT_STATUS_IS_OK(result
)) {
499 d_fprintf(stderr
, "Could not open domain: %s\n", nt_errstr(result
));
503 result
= rpccli_samr_QueryDomainInfo(pipe_hnd
, mem_ctx
,
507 if (NT_STATUS_IS_OK(result
)) {
508 d_printf("Domain Name: %s\n", info
->info2
.domain_name
.string
);
509 d_printf("Domain SID: %s\n", sid_str
);
510 d_printf("Sequence number: %llu\n",
511 (unsigned long long)info
->info2
.sequence_num
);
512 d_printf("Num users: %u\n", info
->info2
.num_users
);
513 d_printf("Num domain groups: %u\n", info
->info2
.num_groups
);
514 d_printf("Num local groups: %u\n", info
->info2
.num_aliases
);
522 * 'net rpc info' entrypoint.
523 * @param argc Standard main() style argc.
524 * @param argv Standard main() style argv. Initial components are already
528 int net_rpc_info(struct net_context
*c
, int argc
, const char **argv
)
530 if (c
->display_usage
) {
533 " Display information about the domain\n");
537 return run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
,
538 NET_FLAGS_PDC
, rpc_info_internals
,
543 * Fetch domain SID into the local secrets.tdb.
545 * All parameters are provided by the run_rpc_command function, except for
546 * argc, argv which are passed through.
548 * @param domain_sid The domain sid acquired from the remote server.
549 * @param cli A cli_state connected to the server.
550 * @param mem_ctx Talloc context, destroyed on completion of the function.
551 * @param argc Standard main() style argc.
552 * @param argv Standard main() style argv. Initial components are already
555 * @return Normal NTSTATUS return.
558 static NTSTATUS
rpc_getsid_internals(struct net_context
*c
,
559 const DOM_SID
*domain_sid
,
560 const char *domain_name
,
561 struct cli_state
*cli
,
562 struct rpc_pipe_client
*pipe_hnd
,
569 sid_to_fstring(sid_str
, domain_sid
);
570 d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
571 sid_str
, domain_name
);
573 if (!secrets_store_domain_sid(domain_name
, domain_sid
)) {
574 DEBUG(0,("Can't store domain SID\n"));
575 return NT_STATUS_UNSUCCESSFUL
;
582 * 'net rpc getsid' entrypoint.
583 * @param argc Standard main() style argc.
584 * @param argv Standard main() style argv. Initial components are already
588 int net_rpc_getsid(struct net_context
*c
, int argc
, const char **argv
)
590 if (c
->display_usage
) {
593 " Fetch domain SID into local secrets.tdb\n");
597 return run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
,
598 NET_FLAGS_ANONYMOUS
| NET_FLAGS_PDC
,
599 rpc_getsid_internals
,
603 /****************************************************************************/
606 * Basic usage function for 'net rpc user'.
607 * @param argc Standard main() style argc.
608 * @param argv Standard main() style argv. Initial components are already
612 static int rpc_user_usage(struct net_context
*c
, int argc
, const char **argv
)
614 return net_user_usage(c
, argc
, argv
);
618 * Add a new user to a remote RPC server.
620 * @param argc Standard main() style argc.
621 * @param argv Standard main() style argv. Initial components are already
624 * @return A shell status integer (0 for success).
627 static int rpc_user_add(struct net_context
*c
, int argc
, const char **argv
)
629 NET_API_STATUS status
;
630 struct USER_INFO_1 info1
;
631 uint32_t parm_error
= 0;
633 if (argc
< 1 || c
->display_usage
) {
634 rpc_user_usage(c
, argc
, argv
);
640 info1
.usri1_name
= argv
[0];
642 info1
.usri1_password
= argv
[1];
645 status
= NetUserAdd(c
->opt_host
, 1, (uint8_t *)&info1
, &parm_error
);
648 d_fprintf(stderr
, "Failed to add user '%s' with: %s.\n",
649 argv
[0], libnetapi_get_error_string(c
->netapi_ctx
,
653 d_printf("Added user '%s'.\n", argv
[0]);
660 * Rename a user on a remote RPC server.
662 * @param argc Standard main() style argc.
663 * @param argv Standard main() style argv. Initial components are already
666 * @return A shell status integer (0 for success).
669 static int rpc_user_rename(struct net_context
*c
, int argc
, const char **argv
)
671 NET_API_STATUS status
;
672 struct USER_INFO_0 u0
;
673 uint32_t parm_err
= 0;
675 if (argc
!= 2 || c
->display_usage
) {
676 rpc_user_usage(c
, argc
, argv
);
680 u0
.usri0_name
= argv
[1];
682 status
= NetUserSetInfo(c
->opt_host
, argv
[0],
683 0, (uint8_t *)&u0
, &parm_err
);
685 d_fprintf(stderr
, "Failed to rename user from %s to %s - %s\n",
687 libnetapi_get_error_string(c
->netapi_ctx
, status
));
689 d_printf("Renamed user from %s to %s\n", argv
[0], argv
[1]);
696 * Delete a user from a remote RPC server.
698 * @param argc Standard main() style argc.
699 * @param argv Standard main() style argv. Initial components are already
702 * @return A shell status integer (0 for success).
705 static int rpc_user_delete(struct net_context
*c
, int argc
, const char **argv
)
707 NET_API_STATUS status
;
709 if (argc
< 1 || c
->display_usage
) {
710 rpc_user_usage(c
, argc
, argv
);
714 status
= NetUserDel(c
->opt_host
, argv
[0]);
717 d_fprintf(stderr
, "Failed to delete user '%s' with: %s.\n",
719 libnetapi_get_error_string(c
->netapi_ctx
, status
));
722 d_printf("Deleted user '%s'.\n", argv
[0]);
729 * Set a user's password on a remote RPC server.
731 * @param argc Standard main() style argc.
732 * @param argv Standard main() style argv. Initial components are already
735 * @return A shell status integer (0 for success).
738 static int rpc_user_password(struct net_context
*c
, int argc
, const char **argv
)
740 NET_API_STATUS status
;
742 struct USER_INFO_1003 u1003
;
743 uint32_t parm_err
= 0;
745 if (argc
< 1 || c
->display_usage
) {
746 rpc_user_usage(c
, argc
, argv
);
751 u1003
.usri1003_password
= argv
[1];
753 if (asprintf(&prompt
, "Enter new password for %s:", argv
[0]) == -1) {
756 u1003
.usri1003_password
= getpass(prompt
);
760 status
= NetUserSetInfo(c
->opt_host
, argv
[0], 1003, (uint8_t *)&u1003
, &parm_err
);
762 /* Display results */
764 d_fprintf(stderr
, "Failed to set password for '%s' with: %s.\n",
765 argv
[0], libnetapi_get_error_string(c
->netapi_ctx
,
774 * List a user's groups from a remote RPC server.
776 * @param argc Standard main() style argc.
777 * @param argv Standard main() style argv. Initial components are already
780 * @return A shell status integer (0 for success)
783 static int rpc_user_info(struct net_context
*c
, int argc
, const char **argv
)
786 NET_API_STATUS status
;
787 struct GROUP_USERS_INFO_0
*u0
= NULL
;
788 uint32_t entries_read
= 0;
789 uint32_t total_entries
= 0;
793 if (argc
< 1 || c
->display_usage
) {
794 rpc_user_usage(c
, argc
, argv
);
798 status
= NetUserGetGroups(c
->opt_host
,
801 (uint8_t **)(void *)&u0
,
806 d_fprintf(stderr
, "Failed to get groups for '%s' with: %s.\n",
807 argv
[0], libnetapi_get_error_string(c
->netapi_ctx
,
812 for (i
=0; i
< entries_read
; i
++) {
813 printf("%s\n", u0
->grui0_name
);
821 * List users on a remote RPC server.
823 * All parameters are provided by the run_rpc_command function, except for
824 * argc, argv which are passed through.
826 * @param domain_sid The domain sid acquired from the remote server.
827 * @param cli A cli_state connected to the server.
828 * @param mem_ctx Talloc context, destroyed on completion of the function.
829 * @param argc Standard main() style argc.
830 * @param argv Standard main() style argv. Initial components are already
833 * @return Normal NTSTATUS return.
836 static int rpc_user_list(struct net_context
*c
, int argc
, const char **argv
)
838 NET_API_STATUS status
;
839 uint32_t start_idx
=0, num_entries
, i
, loop_count
= 0;
840 struct NET_DISPLAY_USER
*info
= NULL
;
843 /* Query domain users */
844 if (c
->opt_long_list_entries
)
845 d_printf("\nUser name Comment"
846 "\n-----------------------------\n");
848 uint32_t max_entries
, max_size
;
850 get_query_dispinfo_params(
851 loop_count
, &max_entries
, &max_size
);
853 status
= NetQueryDisplayInformation(c
->opt_host
,
860 if (status
!= 0 && status
!= ERROR_MORE_DATA
) {
864 info
= (struct NET_DISPLAY_USER
*)buffer
;
866 for (i
= 0; i
< num_entries
; i
++) {
868 if (c
->opt_long_list_entries
)
869 printf("%-21.21s %s\n", info
->usri1_name
,
870 info
->usri1_comment
);
872 printf("%s\n", info
->usri1_name
);
876 NetApiBufferFree(buffer
);
879 start_idx
+= num_entries
;
881 } while (status
== ERROR_MORE_DATA
);
887 * 'net rpc user' entrypoint.
888 * @param argc Standard main() style argc.
889 * @param argv Standard main() style argv. Initial components are already
893 int net_rpc_user(struct net_context
*c
, int argc
, const char **argv
)
895 NET_API_STATUS status
;
897 struct functable func
[] = {
902 "Add specified user",
904 " Add specified user"
910 "List domain groups of user",
911 "net rpc user info\n"
912 " Lis domain groups of user"
918 "Remove specified user",
919 "net rpc user delete\n"
920 " Remove specified user"
926 "Change user password",
927 "net rpc user password\n"
928 " Change user password"
934 "Rename specified user",
935 "net rpc user rename\n"
936 " Rename specified user"
938 {NULL
, NULL
, 0, NULL
, NULL
}
941 status
= libnetapi_init(&c
->netapi_ctx
);
945 libnetapi_set_username(c
->netapi_ctx
, c
->opt_user_name
);
946 libnetapi_set_password(c
->netapi_ctx
, c
->opt_password
);
947 if (c
->opt_kerberos
) {
948 libnetapi_set_use_kerberos(c
->netapi_ctx
);
952 if (c
->display_usage
) {
953 d_printf("Usage:\n");
954 d_printf("net rpc user\n"
955 " List all users\n");
956 net_display_usage_from_functable(func
);
960 return rpc_user_list(c
, argc
, argv
);
963 return net_run_function(c
, argc
, argv
, "net rpc user", func
);
966 static NTSTATUS
rpc_sh_user_list(struct net_context
*c
,
968 struct rpc_sh_ctx
*ctx
,
969 struct rpc_pipe_client
*pipe_hnd
,
970 int argc
, const char **argv
)
972 return werror_to_ntstatus(W_ERROR(rpc_user_list(c
, argc
, argv
)));
975 static NTSTATUS
rpc_sh_user_info(struct net_context
*c
,
977 struct rpc_sh_ctx
*ctx
,
978 struct rpc_pipe_client
*pipe_hnd
,
979 int argc
, const char **argv
)
981 return werror_to_ntstatus(W_ERROR(rpc_user_info(c
, argc
, argv
)));
984 static NTSTATUS
rpc_sh_handle_user(struct net_context
*c
,
986 struct rpc_sh_ctx
*ctx
,
987 struct rpc_pipe_client
*pipe_hnd
,
988 int argc
, const char **argv
,
990 struct net_context
*c
,
992 struct rpc_sh_ctx
*ctx
,
993 struct rpc_pipe_client
*pipe_hnd
,
994 POLICY_HND
*user_hnd
,
995 int argc
, const char **argv
))
997 POLICY_HND connect_pol
, domain_pol
, user_pol
;
998 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1001 enum lsa_SidType type
;
1004 d_fprintf(stderr
, "usage: %s <username>\n", ctx
->whoami
);
1005 return NT_STATUS_INVALID_PARAMETER
;
1008 ZERO_STRUCT(connect_pol
);
1009 ZERO_STRUCT(domain_pol
);
1010 ZERO_STRUCT(user_pol
);
1012 result
= net_rpc_lookup_name(c
, mem_ctx
, rpc_pipe_np_smb_conn(pipe_hnd
),
1013 argv
[0], NULL
, NULL
, &sid
, &type
);
1014 if (!NT_STATUS_IS_OK(result
)) {
1015 d_fprintf(stderr
, "Could not lookup %s: %s\n", argv
[0],
1020 if (type
!= SID_NAME_USER
) {
1021 d_fprintf(stderr
, "%s is a %s, not a user\n", argv
[0],
1022 sid_type_lookup(type
));
1023 result
= NT_STATUS_NO_SUCH_USER
;
1027 if (!sid_peek_check_rid(ctx
->domain_sid
, &sid
, &rid
)) {
1028 d_fprintf(stderr
, "%s is not in our domain\n", argv
[0]);
1029 result
= NT_STATUS_NO_SUCH_USER
;
1033 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
1035 MAXIMUM_ALLOWED_ACCESS
,
1037 if (!NT_STATUS_IS_OK(result
)) {
1041 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
1043 MAXIMUM_ALLOWED_ACCESS
,
1046 if (!NT_STATUS_IS_OK(result
)) {
1050 result
= rpccli_samr_OpenUser(pipe_hnd
, mem_ctx
,
1052 MAXIMUM_ALLOWED_ACCESS
,
1055 if (!NT_STATUS_IS_OK(result
)) {
1059 result
= fn(c
, mem_ctx
, ctx
, pipe_hnd
, &user_pol
, argc
-1, argv
+1);
1062 if (is_valid_policy_hnd(&user_pol
)) {
1063 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &user_pol
);
1065 if (is_valid_policy_hnd(&domain_pol
)) {
1066 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &domain_pol
);
1068 if (is_valid_policy_hnd(&connect_pol
)) {
1069 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &connect_pol
);
1074 static NTSTATUS
rpc_sh_user_show_internals(struct net_context
*c
,
1075 TALLOC_CTX
*mem_ctx
,
1076 struct rpc_sh_ctx
*ctx
,
1077 struct rpc_pipe_client
*pipe_hnd
,
1078 POLICY_HND
*user_hnd
,
1079 int argc
, const char **argv
)
1082 union samr_UserInfo
*info
= NULL
;
1085 d_fprintf(stderr
, "usage: %s show <username>\n", ctx
->whoami
);
1086 return NT_STATUS_INVALID_PARAMETER
;
1089 result
= rpccli_samr_QueryUserInfo(pipe_hnd
, mem_ctx
,
1093 if (!NT_STATUS_IS_OK(result
)) {
1097 d_printf("user rid: %d, group rid: %d\n",
1099 info
->info21
.primary_gid
);
1104 static NTSTATUS
rpc_sh_user_show(struct net_context
*c
,
1105 TALLOC_CTX
*mem_ctx
,
1106 struct rpc_sh_ctx
*ctx
,
1107 struct rpc_pipe_client
*pipe_hnd
,
1108 int argc
, const char **argv
)
1110 return rpc_sh_handle_user(c
, mem_ctx
, ctx
, pipe_hnd
, argc
, argv
,
1111 rpc_sh_user_show_internals
);
1114 #define FETCHSTR(name, rec) \
1115 do { if (strequal(ctx->thiscmd, name)) { \
1116 oldval = talloc_strdup(mem_ctx, info->info21.rec.string); } \
1119 #define SETSTR(name, rec, flag) \
1120 do { if (strequal(ctx->thiscmd, name)) { \
1121 init_lsa_String(&(info->info21.rec), argv[0]); \
1122 info->info21.fields_present |= SAMR_FIELD_##flag; } \
1125 static NTSTATUS
rpc_sh_user_str_edit_internals(struct net_context
*c
,
1126 TALLOC_CTX
*mem_ctx
,
1127 struct rpc_sh_ctx
*ctx
,
1128 struct rpc_pipe_client
*pipe_hnd
,
1129 POLICY_HND
*user_hnd
,
1130 int argc
, const char **argv
)
1133 const char *username
;
1134 const char *oldval
= "";
1135 union samr_UserInfo
*info
= NULL
;
1138 d_fprintf(stderr
, "usage: %s <username> [new value|NULL]\n",
1140 return NT_STATUS_INVALID_PARAMETER
;
1143 result
= rpccli_samr_QueryUserInfo(pipe_hnd
, mem_ctx
,
1147 if (!NT_STATUS_IS_OK(result
)) {
1151 username
= talloc_strdup(mem_ctx
, info
->info21
.account_name
.string
);
1153 FETCHSTR("fullname", full_name
);
1154 FETCHSTR("homedir", home_directory
);
1155 FETCHSTR("homedrive", home_drive
);
1156 FETCHSTR("logonscript", logon_script
);
1157 FETCHSTR("profilepath", profile_path
);
1158 FETCHSTR("description", description
);
1161 d_printf("%s's %s: [%s]\n", username
, ctx
->thiscmd
, oldval
);
1165 if (strcmp(argv
[0], "NULL") == 0) {
1169 ZERO_STRUCT(info
->info21
);
1171 SETSTR("fullname", full_name
, FULL_NAME
);
1172 SETSTR("homedir", home_directory
, HOME_DIRECTORY
);
1173 SETSTR("homedrive", home_drive
, HOME_DRIVE
);
1174 SETSTR("logonscript", logon_script
, LOGON_SCRIPT
);
1175 SETSTR("profilepath", profile_path
, PROFILE_PATH
);
1176 SETSTR("description", description
, DESCRIPTION
);
1178 result
= rpccli_samr_SetUserInfo(pipe_hnd
, mem_ctx
,
1183 d_printf("Set %s's %s from [%s] to [%s]\n", username
,
1184 ctx
->thiscmd
, oldval
, argv
[0]);
1191 #define HANDLEFLG(name, rec) \
1192 do { if (strequal(ctx->thiscmd, name)) { \
1193 oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
1195 newflags = oldflags | ACB_##rec; \
1197 newflags = oldflags & ~ACB_##rec; \
1200 static NTSTATUS
rpc_sh_user_str_edit(struct net_context
*c
,
1201 TALLOC_CTX
*mem_ctx
,
1202 struct rpc_sh_ctx
*ctx
,
1203 struct rpc_pipe_client
*pipe_hnd
,
1204 int argc
, const char **argv
)
1206 return rpc_sh_handle_user(c
, mem_ctx
, ctx
, pipe_hnd
, argc
, argv
,
1207 rpc_sh_user_str_edit_internals
);
1210 static NTSTATUS
rpc_sh_user_flag_edit_internals(struct net_context
*c
,
1211 TALLOC_CTX
*mem_ctx
,
1212 struct rpc_sh_ctx
*ctx
,
1213 struct rpc_pipe_client
*pipe_hnd
,
1214 POLICY_HND
*user_hnd
,
1215 int argc
, const char **argv
)
1218 const char *username
;
1219 const char *oldval
= "unknown";
1220 uint32 oldflags
, newflags
;
1222 union samr_UserInfo
*info
= NULL
;
1225 ((argc
== 1) && !strequal(argv
[0], "yes") &&
1226 !strequal(argv
[0], "no"))) {
1227 d_fprintf(stderr
, "usage: %s <username> [yes|no]\n",
1229 return NT_STATUS_INVALID_PARAMETER
;
1232 newval
= strequal(argv
[0], "yes");
1234 result
= rpccli_samr_QueryUserInfo(pipe_hnd
, mem_ctx
,
1238 if (!NT_STATUS_IS_OK(result
)) {
1242 username
= talloc_strdup(mem_ctx
, info
->info21
.account_name
.string
);
1243 oldflags
= info
->info21
.acct_flags
;
1244 newflags
= info
->info21
.acct_flags
;
1246 HANDLEFLG("disabled", DISABLED
);
1247 HANDLEFLG("pwnotreq", PWNOTREQ
);
1248 HANDLEFLG("autolock", AUTOLOCK
);
1249 HANDLEFLG("pwnoexp", PWNOEXP
);
1252 d_printf("%s's %s flag: %s\n", username
, ctx
->thiscmd
, oldval
);
1256 ZERO_STRUCT(info
->info21
);
1258 info
->info21
.acct_flags
= newflags
;
1259 info
->info21
.fields_present
= SAMR_FIELD_ACCT_FLAGS
;
1261 result
= rpccli_samr_SetUserInfo(pipe_hnd
, mem_ctx
,
1266 if (NT_STATUS_IS_OK(result
)) {
1267 d_printf("Set %s's %s flag from [%s] to [%s]\n", username
,
1268 ctx
->thiscmd
, oldval
, argv
[0]);
1276 static NTSTATUS
rpc_sh_user_flag_edit(struct net_context
*c
,
1277 TALLOC_CTX
*mem_ctx
,
1278 struct rpc_sh_ctx
*ctx
,
1279 struct rpc_pipe_client
*pipe_hnd
,
1280 int argc
, const char **argv
)
1282 return rpc_sh_handle_user(c
, mem_ctx
, ctx
, pipe_hnd
, argc
, argv
,
1283 rpc_sh_user_flag_edit_internals
);
1286 struct rpc_sh_cmd
*net_rpc_user_edit_cmds(struct net_context
*c
,
1287 TALLOC_CTX
*mem_ctx
,
1288 struct rpc_sh_ctx
*ctx
)
1290 static struct rpc_sh_cmd cmds
[] = {
1292 { "fullname", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_str_edit
,
1293 "Show/Set a user's full name" },
1295 { "homedir", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_str_edit
,
1296 "Show/Set a user's home directory" },
1298 { "homedrive", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_str_edit
,
1299 "Show/Set a user's home drive" },
1301 { "logonscript", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_str_edit
,
1302 "Show/Set a user's logon script" },
1304 { "profilepath", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_str_edit
,
1305 "Show/Set a user's profile path" },
1307 { "description", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_str_edit
,
1308 "Show/Set a user's description" },
1310 { "disabled", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_flag_edit
,
1311 "Show/Set whether a user is disabled" },
1313 { "autolock", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_flag_edit
,
1314 "Show/Set whether a user locked out" },
1316 { "pwnotreq", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_flag_edit
,
1317 "Show/Set whether a user does not need a password" },
1319 { "pwnoexp", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_flag_edit
,
1320 "Show/Set whether a user's password does not expire" },
1322 { NULL
, NULL
, 0, NULL
, NULL
}
1328 struct rpc_sh_cmd
*net_rpc_user_cmds(struct net_context
*c
,
1329 TALLOC_CTX
*mem_ctx
,
1330 struct rpc_sh_ctx
*ctx
)
1332 static struct rpc_sh_cmd cmds
[] = {
1334 { "list", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_list
,
1335 "List available users" },
1337 { "info", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_info
,
1338 "List the domain groups a user is member of" },
1340 { "show", NULL
, &ndr_table_samr
.syntax_id
, rpc_sh_user_show
,
1341 "Show info about a user" },
1343 { "edit", net_rpc_user_edit_cmds
, 0, NULL
,
1344 "Show/Modify a user's fields" },
1346 { NULL
, NULL
, 0, NULL
, NULL
}
1352 /****************************************************************************/
1355 * Basic usage function for 'net rpc group'.
1356 * @param argc Standard main() style argc.
1357 * @param argv Standard main() style argv. Initial components are already
1361 static int rpc_group_usage(struct net_context
*c
, int argc
, const char **argv
)
1363 return net_group_usage(c
, argc
, argv
);
1367 * Delete group on a remote RPC server.
1369 * All parameters are provided by the run_rpc_command function, except for
1370 * argc, argv which are passed through.
1372 * @param domain_sid The domain sid acquired from the remote server.
1373 * @param cli A cli_state connected to the server.
1374 * @param mem_ctx Talloc context, destroyed on completion of the function.
1375 * @param argc Standard main() style argc.
1376 * @param argv Standard main() style argv. Initial components are already
1379 * @return Normal NTSTATUS return.
1382 static NTSTATUS
rpc_group_delete_internals(struct net_context
*c
,
1383 const DOM_SID
*domain_sid
,
1384 const char *domain_name
,
1385 struct cli_state
*cli
,
1386 struct rpc_pipe_client
*pipe_hnd
,
1387 TALLOC_CTX
*mem_ctx
,
1391 POLICY_HND connect_pol
, domain_pol
, group_pol
, user_pol
;
1392 bool group_is_primary
= false;
1393 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1395 struct samr_RidTypeArray
*rids
= NULL
;
1398 /* DOM_GID *user_gids; */
1400 struct samr_Ids group_rids
, name_types
;
1401 struct lsa_String lsa_acct_name
;
1402 union samr_UserInfo
*info
= NULL
;
1404 if (argc
< 1 || c
->display_usage
) {
1405 rpc_group_usage(c
, argc
,argv
);
1406 return NT_STATUS_OK
; /* ok? */
1409 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
1411 MAXIMUM_ALLOWED_ACCESS
,
1414 if (!NT_STATUS_IS_OK(result
)) {
1415 d_fprintf(stderr
, "Request samr_Connect2 failed\n");
1419 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
1421 MAXIMUM_ALLOWED_ACCESS
,
1422 CONST_DISCARD(struct dom_sid2
*, domain_sid
),
1425 if (!NT_STATUS_IS_OK(result
)) {
1426 d_fprintf(stderr
, "Request open_domain failed\n");
1430 init_lsa_String(&lsa_acct_name
, argv
[0]);
1432 result
= rpccli_samr_LookupNames(pipe_hnd
, mem_ctx
,
1438 if (!NT_STATUS_IS_OK(result
)) {
1439 d_fprintf(stderr
, "Lookup of '%s' failed\n",argv
[0]);
1443 switch (name_types
.ids
[0])
1445 case SID_NAME_DOM_GRP
:
1446 result
= rpccli_samr_OpenGroup(pipe_hnd
, mem_ctx
,
1448 MAXIMUM_ALLOWED_ACCESS
,
1451 if (!NT_STATUS_IS_OK(result
)) {
1452 d_fprintf(stderr
, "Request open_group failed");
1456 group_rid
= group_rids
.ids
[0];
1458 result
= rpccli_samr_QueryGroupMember(pipe_hnd
, mem_ctx
,
1462 if (!NT_STATUS_IS_OK(result
)) {
1463 d_fprintf(stderr
, "Unable to query group members of %s",argv
[0]);
1467 if (c
->opt_verbose
) {
1468 d_printf("Domain Group %s (rid: %d) has %d members\n",
1469 argv
[0],group_rid
, rids
->count
);
1472 /* Check if group is anyone's primary group */
1473 for (i
= 0; i
< rids
->count
; i
++)
1475 result
= rpccli_samr_OpenUser(pipe_hnd
, mem_ctx
,
1477 MAXIMUM_ALLOWED_ACCESS
,
1481 if (!NT_STATUS_IS_OK(result
)) {
1482 d_fprintf(stderr
, "Unable to open group member %d\n",
1487 result
= rpccli_samr_QueryUserInfo(pipe_hnd
, mem_ctx
,
1492 if (!NT_STATUS_IS_OK(result
)) {
1493 d_fprintf(stderr
, "Unable to lookup userinfo for group member %d\n",
1498 if (info
->info21
.primary_gid
== group_rid
) {
1499 if (c
->opt_verbose
) {
1500 d_printf("Group is primary group of %s\n",
1501 info
->info21
.account_name
.string
);
1503 group_is_primary
= true;
1506 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &user_pol
);
1509 if (group_is_primary
) {
1510 d_fprintf(stderr
, "Unable to delete group because some "
1511 "of it's members have it as primary group\n");
1512 result
= NT_STATUS_MEMBERS_PRIMARY_GROUP
;
1516 /* remove all group members */
1517 for (i
= 0; i
< rids
->count
; i
++)
1520 d_printf("Remove group member %d...",
1522 result
= rpccli_samr_DeleteGroupMember(pipe_hnd
, mem_ctx
,
1526 if (NT_STATUS_IS_OK(result
)) {
1531 d_printf("failed\n");
1536 result
= rpccli_samr_DeleteDomainGroup(pipe_hnd
, mem_ctx
,
1540 /* removing a local group is easier... */
1541 case SID_NAME_ALIAS
:
1542 result
= rpccli_samr_OpenAlias(pipe_hnd
, mem_ctx
,
1544 MAXIMUM_ALLOWED_ACCESS
,
1548 if (!NT_STATUS_IS_OK(result
)) {
1549 d_fprintf(stderr
, "Request open_alias failed\n");
1553 result
= rpccli_samr_DeleteDomAlias(pipe_hnd
, mem_ctx
,
1557 d_fprintf(stderr
, "%s is of type %s. This command is only for deleting local or global groups\n",
1558 argv
[0],sid_type_lookup(name_types
.ids
[0]));
1559 result
= NT_STATUS_UNSUCCESSFUL
;
1563 if (NT_STATUS_IS_OK(result
)) {
1565 d_printf("Deleted %s '%s'\n",sid_type_lookup(name_types
.ids
[0]),argv
[0]);
1567 d_fprintf(stderr
, "Deleting of %s failed: %s\n",argv
[0],
1568 get_friendly_nt_error_msg(result
));
1576 static int rpc_group_delete(struct net_context
*c
, int argc
, const char **argv
)
1578 return run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
, 0,
1579 rpc_group_delete_internals
, argc
,argv
);
1582 static int rpc_group_add_internals(struct net_context
*c
, int argc
, const char **argv
)
1584 NET_API_STATUS status
;
1585 struct GROUP_INFO_1 info1
;
1586 uint32_t parm_error
= 0;
1588 if (argc
!= 1 || c
->display_usage
) {
1589 rpc_group_usage(c
, argc
, argv
);
1595 info1
.grpi1_name
= argv
[0];
1596 if (c
->opt_comment
&& strlen(c
->opt_comment
) > 0) {
1597 info1
.grpi1_comment
= c
->opt_comment
;
1600 status
= NetGroupAdd(c
->opt_host
, 1, (uint8_t *)&info1
, &parm_error
);
1603 d_fprintf(stderr
, "Failed to add group '%s' with: %s.\n",
1604 argv
[0], libnetapi_get_error_string(c
->netapi_ctx
,
1608 d_printf("Added group '%s'.\n", argv
[0]);
1614 static int rpc_alias_add_internals(struct net_context
*c
, int argc
, const char **argv
)
1616 NET_API_STATUS status
;
1617 struct LOCALGROUP_INFO_1 info1
;
1618 uint32_t parm_error
= 0;
1620 if (argc
!= 1 || c
->display_usage
) {
1621 rpc_group_usage(c
, argc
, argv
);
1627 info1
.lgrpi1_name
= argv
[0];
1628 if (c
->opt_comment
&& strlen(c
->opt_comment
) > 0) {
1629 info1
.lgrpi1_comment
= c
->opt_comment
;
1632 status
= NetLocalGroupAdd(c
->opt_host
, 1, (uint8_t *)&info1
, &parm_error
);
1635 d_fprintf(stderr
, "Failed to add alias '%s' with: %s.\n",
1636 argv
[0], libnetapi_get_error_string(c
->netapi_ctx
,
1640 d_printf("Added alias '%s'.\n", argv
[0]);
1646 static int rpc_group_add(struct net_context
*c
, int argc
, const char **argv
)
1648 if (c
->opt_localgroup
)
1649 return rpc_alias_add_internals(c
, argc
, argv
);
1651 return rpc_group_add_internals(c
, argc
, argv
);
1654 static NTSTATUS
get_sid_from_name(struct cli_state
*cli
,
1655 TALLOC_CTX
*mem_ctx
,
1658 enum lsa_SidType
*type
)
1660 DOM_SID
*sids
= NULL
;
1661 enum lsa_SidType
*types
= NULL
;
1662 struct rpc_pipe_client
*pipe_hnd
;
1664 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
1666 result
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_lsarpc
.syntax_id
,
1668 if (!NT_STATUS_IS_OK(result
)) {
1672 result
= rpccli_lsa_open_policy(pipe_hnd
, mem_ctx
, false,
1673 SEC_RIGHTS_MAXIMUM_ALLOWED
, &lsa_pol
);
1675 if (!NT_STATUS_IS_OK(result
)) {
1679 result
= rpccli_lsa_lookup_names(pipe_hnd
, mem_ctx
, &lsa_pol
, 1,
1680 &name
, NULL
, 1, &sids
, &types
);
1682 if (NT_STATUS_IS_OK(result
)) {
1683 sid_copy(sid
, &sids
[0]);
1687 rpccli_lsa_Close(pipe_hnd
, mem_ctx
, &lsa_pol
);
1691 TALLOC_FREE(pipe_hnd
);
1694 if (!NT_STATUS_IS_OK(result
) && (StrnCaseCmp(name
, "S-", 2) == 0)) {
1696 /* Try as S-1-5-whatever */
1700 if (string_to_sid(&tmp_sid
, name
)) {
1701 sid_copy(sid
, &tmp_sid
);
1702 *type
= SID_NAME_UNKNOWN
;
1703 result
= NT_STATUS_OK
;
1710 static NTSTATUS
rpc_add_groupmem(struct rpc_pipe_client
*pipe_hnd
,
1711 TALLOC_CTX
*mem_ctx
,
1712 const DOM_SID
*group_sid
,
1715 POLICY_HND connect_pol
, domain_pol
;
1718 POLICY_HND group_pol
;
1720 struct samr_Ids rids
, rid_types
;
1721 struct lsa_String lsa_acct_name
;
1725 sid_copy(&sid
, group_sid
);
1727 if (!sid_split_rid(&sid
, &group_rid
)) {
1728 return NT_STATUS_UNSUCCESSFUL
;
1731 /* Get sam policy handle */
1732 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
1734 MAXIMUM_ALLOWED_ACCESS
,
1736 if (!NT_STATUS_IS_OK(result
)) {
1740 /* Get domain policy handle */
1741 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
1743 MAXIMUM_ALLOWED_ACCESS
,
1746 if (!NT_STATUS_IS_OK(result
)) {
1750 init_lsa_String(&lsa_acct_name
, member
);
1752 result
= rpccli_samr_LookupNames(pipe_hnd
, mem_ctx
,
1759 if (!NT_STATUS_IS_OK(result
)) {
1760 d_fprintf(stderr
, "Could not lookup up group member %s\n", member
);
1764 result
= rpccli_samr_OpenGroup(pipe_hnd
, mem_ctx
,
1766 MAXIMUM_ALLOWED_ACCESS
,
1770 if (!NT_STATUS_IS_OK(result
)) {
1774 result
= rpccli_samr_AddGroupMember(pipe_hnd
, mem_ctx
,
1777 0x0005); /* unknown flags */
1780 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &connect_pol
);
1784 static NTSTATUS
rpc_add_aliasmem(struct rpc_pipe_client
*pipe_hnd
,
1785 TALLOC_CTX
*mem_ctx
,
1786 const DOM_SID
*alias_sid
,
1789 POLICY_HND connect_pol
, domain_pol
;
1792 POLICY_HND alias_pol
;
1795 enum lsa_SidType member_type
;
1799 sid_copy(&sid
, alias_sid
);
1801 if (!sid_split_rid(&sid
, &alias_rid
)) {
1802 return NT_STATUS_UNSUCCESSFUL
;
1805 result
= get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd
), mem_ctx
,
1806 member
, &member_sid
, &member_type
);
1808 if (!NT_STATUS_IS_OK(result
)) {
1809 d_fprintf(stderr
, "Could not lookup up group member %s\n", member
);
1813 /* Get sam policy handle */
1814 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
1816 MAXIMUM_ALLOWED_ACCESS
,
1818 if (!NT_STATUS_IS_OK(result
)) {
1822 /* Get domain policy handle */
1823 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
1825 MAXIMUM_ALLOWED_ACCESS
,
1828 if (!NT_STATUS_IS_OK(result
)) {
1832 result
= rpccli_samr_OpenAlias(pipe_hnd
, mem_ctx
,
1834 MAXIMUM_ALLOWED_ACCESS
,
1838 if (!NT_STATUS_IS_OK(result
)) {
1842 result
= rpccli_samr_AddAliasMember(pipe_hnd
, mem_ctx
,
1846 if (!NT_STATUS_IS_OK(result
)) {
1851 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &connect_pol
);
1855 static NTSTATUS
rpc_group_addmem_internals(struct net_context
*c
,
1856 const DOM_SID
*domain_sid
,
1857 const char *domain_name
,
1858 struct cli_state
*cli
,
1859 struct rpc_pipe_client
*pipe_hnd
,
1860 TALLOC_CTX
*mem_ctx
,
1865 enum lsa_SidType group_type
;
1867 if (argc
!= 2 || c
->display_usage
) {
1869 "net rpc group addmem <group> <member>\n"
1870 " Add a member to a group\n"
1871 " group\tGroup to add member to\n"
1872 " member\tMember to add to group\n");
1873 return NT_STATUS_UNSUCCESSFUL
;
1876 if (!NT_STATUS_IS_OK(get_sid_from_name(cli
, mem_ctx
, argv
[0],
1877 &group_sid
, &group_type
))) {
1878 d_fprintf(stderr
, "Could not lookup group name %s\n", argv
[0]);
1879 return NT_STATUS_UNSUCCESSFUL
;
1882 if (group_type
== SID_NAME_DOM_GRP
) {
1883 NTSTATUS result
= rpc_add_groupmem(pipe_hnd
, mem_ctx
,
1884 &group_sid
, argv
[1]);
1886 if (!NT_STATUS_IS_OK(result
)) {
1887 d_fprintf(stderr
, "Could not add %s to %s: %s\n",
1888 argv
[1], argv
[0], nt_errstr(result
));
1893 if (group_type
== SID_NAME_ALIAS
) {
1894 NTSTATUS result
= rpc_add_aliasmem(pipe_hnd
, mem_ctx
,
1895 &group_sid
, argv
[1]);
1897 if (!NT_STATUS_IS_OK(result
)) {
1898 d_fprintf(stderr
, "Could not add %s to %s: %s\n",
1899 argv
[1], argv
[0], nt_errstr(result
));
1904 d_fprintf(stderr
, "Can only add members to global or local groups "
1905 "which %s is not\n", argv
[0]);
1907 return NT_STATUS_UNSUCCESSFUL
;
1910 static int rpc_group_addmem(struct net_context
*c
, int argc
, const char **argv
)
1912 return run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
, 0,
1913 rpc_group_addmem_internals
,
1917 static NTSTATUS
rpc_del_groupmem(struct net_context
*c
,
1918 struct rpc_pipe_client
*pipe_hnd
,
1919 TALLOC_CTX
*mem_ctx
,
1920 const DOM_SID
*group_sid
,
1923 POLICY_HND connect_pol
, domain_pol
;
1926 POLICY_HND group_pol
;
1928 struct samr_Ids rids
, rid_types
;
1929 struct lsa_String lsa_acct_name
;
1933 sid_copy(&sid
, group_sid
);
1935 if (!sid_split_rid(&sid
, &group_rid
))
1936 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
))
1946 /* Get domain policy handle */
1947 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
1949 MAXIMUM_ALLOWED_ACCESS
,
1952 if (!NT_STATUS_IS_OK(result
))
1955 init_lsa_String(&lsa_acct_name
, member
);
1957 result
= rpccli_samr_LookupNames(pipe_hnd
, mem_ctx
,
1963 if (!NT_STATUS_IS_OK(result
)) {
1964 d_fprintf(stderr
, "Could not lookup up group member %s\n", member
);
1968 result
= rpccli_samr_OpenGroup(pipe_hnd
, mem_ctx
,
1970 MAXIMUM_ALLOWED_ACCESS
,
1974 if (!NT_STATUS_IS_OK(result
))
1977 result
= rpccli_samr_DeleteGroupMember(pipe_hnd
, mem_ctx
,
1982 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &connect_pol
);
1986 static NTSTATUS
rpc_del_aliasmem(struct rpc_pipe_client
*pipe_hnd
,
1987 TALLOC_CTX
*mem_ctx
,
1988 const DOM_SID
*alias_sid
,
1991 POLICY_HND connect_pol
, domain_pol
;
1994 POLICY_HND alias_pol
;
1997 enum lsa_SidType member_type
;
2001 sid_copy(&sid
, alias_sid
);
2003 if (!sid_split_rid(&sid
, &alias_rid
))
2004 return NT_STATUS_UNSUCCESSFUL
;
2006 result
= get_sid_from_name(rpc_pipe_np_smb_conn(pipe_hnd
), mem_ctx
,
2007 member
, &member_sid
, &member_type
);
2009 if (!NT_STATUS_IS_OK(result
)) {
2010 d_fprintf(stderr
, "Could not lookup up group member %s\n", member
);
2014 /* Get sam policy handle */
2015 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
2017 MAXIMUM_ALLOWED_ACCESS
,
2019 if (!NT_STATUS_IS_OK(result
)) {
2023 /* Get domain policy handle */
2024 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
2026 MAXIMUM_ALLOWED_ACCESS
,
2029 if (!NT_STATUS_IS_OK(result
)) {
2033 result
= rpccli_samr_OpenAlias(pipe_hnd
, mem_ctx
,
2035 MAXIMUM_ALLOWED_ACCESS
,
2039 if (!NT_STATUS_IS_OK(result
))
2042 result
= rpccli_samr_DeleteAliasMember(pipe_hnd
, mem_ctx
,
2046 if (!NT_STATUS_IS_OK(result
))
2050 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &connect_pol
);
2054 static NTSTATUS
rpc_group_delmem_internals(struct net_context
*c
,
2055 const DOM_SID
*domain_sid
,
2056 const char *domain_name
,
2057 struct cli_state
*cli
,
2058 struct rpc_pipe_client
*pipe_hnd
,
2059 TALLOC_CTX
*mem_ctx
,
2064 enum lsa_SidType group_type
;
2066 if (argc
!= 2 || c
->display_usage
) {
2068 "net rpc group delmem <group> <member>\n"
2069 " Delete a member from a group\n"
2070 " group\tGroup to delete member from\n"
2071 " member\tMember to delete from group\n");
2072 return NT_STATUS_UNSUCCESSFUL
;
2075 if (!NT_STATUS_IS_OK(get_sid_from_name(cli
, mem_ctx
, argv
[0],
2076 &group_sid
, &group_type
))) {
2077 d_fprintf(stderr
, "Could not lookup group name %s\n", argv
[0]);
2078 return NT_STATUS_UNSUCCESSFUL
;
2081 if (group_type
== SID_NAME_DOM_GRP
) {
2082 NTSTATUS result
= rpc_del_groupmem(c
, pipe_hnd
, mem_ctx
,
2083 &group_sid
, argv
[1]);
2085 if (!NT_STATUS_IS_OK(result
)) {
2086 d_fprintf(stderr
, "Could not del %s from %s: %s\n",
2087 argv
[1], argv
[0], nt_errstr(result
));
2092 if (group_type
== SID_NAME_ALIAS
) {
2093 NTSTATUS result
= rpc_del_aliasmem(pipe_hnd
, mem_ctx
,
2094 &group_sid
, argv
[1]);
2096 if (!NT_STATUS_IS_OK(result
)) {
2097 d_fprintf(stderr
, "Could not del %s from %s: %s\n",
2098 argv
[1], argv
[0], nt_errstr(result
));
2103 d_fprintf(stderr
, "Can only delete members from global or local groups "
2104 "which %s is not\n", argv
[0]);
2106 return NT_STATUS_UNSUCCESSFUL
;
2109 static int rpc_group_delmem(struct net_context
*c
, int argc
, const char **argv
)
2111 return run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
, 0,
2112 rpc_group_delmem_internals
,
2117 * List groups on a remote RPC server.
2119 * All parameters are provided by the run_rpc_command function, except for
2120 * argc, argv which are passes through.
2122 * @param domain_sid The domain sid acquired from the remote server.
2123 * @param cli A cli_state connected to the server.
2124 * @param mem_ctx Talloc context, destroyed on completion of the function.
2125 * @param argc Standard main() style argc.
2126 * @param argv Standard main() style argv. Initial components are already
2129 * @return Normal NTSTATUS return.
2132 static NTSTATUS
rpc_group_list_internals(struct net_context
*c
,
2133 const DOM_SID
*domain_sid
,
2134 const char *domain_name
,
2135 struct cli_state
*cli
,
2136 struct rpc_pipe_client
*pipe_hnd
,
2137 TALLOC_CTX
*mem_ctx
,
2141 POLICY_HND connect_pol
, domain_pol
;
2142 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
2143 uint32 start_idx
=0, max_entries
=250, num_entries
, i
, loop_count
= 0;
2144 struct samr_SamArray
*groups
= NULL
;
2145 bool global
= false;
2147 bool builtin
= false;
2149 if (c
->display_usage
) {
2151 "net rpc group list [global] [local] [builtin]\n"
2152 " List groups on RPC server\n"
2153 " global\tList global groups\n"
2154 " local\tList local groups\n"
2155 " builtin\tList builtin groups\n"
2156 " If none of global, local or builtin is "
2157 "specified, all three options are considered set\n");
2158 return NT_STATUS_OK
;
2167 for (i
=0; i
<argc
; i
++) {
2168 if (strequal(argv
[i
], "global"))
2171 if (strequal(argv
[i
], "local"))
2174 if (strequal(argv
[i
], "builtin"))
2178 /* Get sam policy handle */
2180 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
2182 MAXIMUM_ALLOWED_ACCESS
,
2184 if (!NT_STATUS_IS_OK(result
)) {
2188 /* Get domain policy handle */
2190 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
2192 MAXIMUM_ALLOWED_ACCESS
,
2193 CONST_DISCARD(struct dom_sid2
*, domain_sid
),
2195 if (!NT_STATUS_IS_OK(result
)) {
2199 /* Query domain groups */
2200 if (c
->opt_long_list_entries
)
2201 d_printf("\nGroup name Comment"
2202 "\n-----------------------------\n");
2204 uint32_t max_size
, total_size
, returned_size
;
2205 union samr_DispInfo info
;
2209 get_query_dispinfo_params(
2210 loop_count
, &max_entries
, &max_size
);
2212 result
= rpccli_samr_QueryDisplayInfo(pipe_hnd
, mem_ctx
,
2221 num_entries
= info
.info3
.count
;
2222 start_idx
+= info
.info3
.count
;
2224 if (!NT_STATUS_IS_OK(result
) &&
2225 !NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
))
2228 for (i
= 0; i
< num_entries
; i
++) {
2230 const char *group
= NULL
;
2231 const char *desc
= NULL
;
2233 group
= info
.info3
.entries
[i
].account_name
.string
;
2234 desc
= info
.info3
.entries
[i
].description
.string
;
2236 if (c
->opt_long_list_entries
)
2237 printf("%-21.21s %-50.50s\n",
2240 printf("%s\n", group
);
2242 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
2243 /* query domain aliases */
2248 result
= rpccli_samr_EnumDomainAliases(pipe_hnd
, mem_ctx
,
2254 if (!NT_STATUS_IS_OK(result
) &&
2255 !NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
))
2258 for (i
= 0; i
< num_entries
; i
++) {
2260 const char *description
= NULL
;
2262 if (c
->opt_long_list_entries
) {
2264 POLICY_HND alias_pol
;
2265 union samr_AliasInfo
*info
= NULL
;
2267 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd
, mem_ctx
,
2270 groups
->entries
[i
].idx
,
2272 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd
, mem_ctx
,
2276 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd
, mem_ctx
,
2278 description
= info
->description
.string
;
2282 if (description
!= NULL
) {
2283 printf("%-21.21s %-50.50s\n",
2284 groups
->entries
[i
].name
.string
,
2287 printf("%s\n", groups
->entries
[i
].name
.string
);
2290 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
2291 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &domain_pol
);
2292 /* Get builtin policy handle */
2294 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
2296 MAXIMUM_ALLOWED_ACCESS
,
2297 CONST_DISCARD(struct dom_sid2
*, &global_sid_Builtin
),
2299 if (!NT_STATUS_IS_OK(result
)) {
2302 /* query builtin aliases */
2305 if (!builtin
) break;
2307 result
= rpccli_samr_EnumDomainAliases(pipe_hnd
, mem_ctx
,
2313 if (!NT_STATUS_IS_OK(result
) &&
2314 !NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
))
2317 for (i
= 0; i
< num_entries
; i
++) {
2319 const char *description
= NULL
;
2321 if (c
->opt_long_list_entries
) {
2323 POLICY_HND alias_pol
;
2324 union samr_AliasInfo
*info
= NULL
;
2326 if ((NT_STATUS_IS_OK(rpccli_samr_OpenAlias(pipe_hnd
, mem_ctx
,
2329 groups
->entries
[i
].idx
,
2331 (NT_STATUS_IS_OK(rpccli_samr_QueryAliasInfo(pipe_hnd
, mem_ctx
,
2335 (NT_STATUS_IS_OK(rpccli_samr_Close(pipe_hnd
, mem_ctx
,
2337 description
= info
->description
.string
;
2341 if (description
!= NULL
) {
2342 printf("%-21.21s %-50.50s\n",
2343 groups
->entries
[i
].name
.string
,
2346 printf("%s\n", groups
->entries
[i
].name
.string
);
2349 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
2355 static int rpc_group_list(struct net_context
*c
, int argc
, const char **argv
)
2357 return run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
, 0,
2358 rpc_group_list_internals
,
2362 static NTSTATUS
rpc_list_group_members(struct net_context
*c
,
2363 struct rpc_pipe_client
*pipe_hnd
,
2364 TALLOC_CTX
*mem_ctx
,
2365 const char *domain_name
,
2366 const DOM_SID
*domain_sid
,
2367 POLICY_HND
*domain_pol
,
2371 POLICY_HND group_pol
;
2372 uint32 num_members
, *group_rids
;
2374 struct samr_RidTypeArray
*rids
= NULL
;
2375 struct lsa_Strings names
;
2376 struct samr_Ids types
;
2379 sid_to_fstring(sid_str
, domain_sid
);
2381 result
= rpccli_samr_OpenGroup(pipe_hnd
, mem_ctx
,
2383 MAXIMUM_ALLOWED_ACCESS
,
2387 if (!NT_STATUS_IS_OK(result
))
2390 result
= rpccli_samr_QueryGroupMember(pipe_hnd
, mem_ctx
,
2394 if (!NT_STATUS_IS_OK(result
))
2397 num_members
= rids
->count
;
2398 group_rids
= rids
->rids
;
2400 while (num_members
> 0) {
2401 int this_time
= 512;
2403 if (num_members
< this_time
)
2404 this_time
= num_members
;
2406 result
= rpccli_samr_LookupRids(pipe_hnd
, mem_ctx
,
2413 if (!NT_STATUS_IS_OK(result
))
2416 /* We only have users as members, but make the output
2417 the same as the output of alias members */
2419 for (i
= 0; i
< this_time
; i
++) {
2421 if (c
->opt_long_list_entries
) {
2422 printf("%s-%d %s\\%s %d\n", sid_str
,
2423 group_rids
[i
], domain_name
,
2424 names
.names
[i
].string
,
2427 printf("%s\\%s\n", domain_name
,
2428 names
.names
[i
].string
);
2432 num_members
-= this_time
;
2436 return NT_STATUS_OK
;
2439 static NTSTATUS
rpc_list_alias_members(struct net_context
*c
,
2440 struct rpc_pipe_client
*pipe_hnd
,
2441 TALLOC_CTX
*mem_ctx
,
2442 POLICY_HND
*domain_pol
,
2446 struct rpc_pipe_client
*lsa_pipe
;
2447 POLICY_HND alias_pol
, lsa_pol
;
2449 DOM_SID
*alias_sids
;
2452 enum lsa_SidType
*types
;
2454 struct lsa_SidArray sid_array
;
2456 result
= rpccli_samr_OpenAlias(pipe_hnd
, mem_ctx
,
2458 MAXIMUM_ALLOWED_ACCESS
,
2462 if (!NT_STATUS_IS_OK(result
))
2465 result
= rpccli_samr_GetMembersInAlias(pipe_hnd
, mem_ctx
,
2469 if (!NT_STATUS_IS_OK(result
)) {
2470 d_fprintf(stderr
, "Couldn't list alias members\n");
2474 num_members
= sid_array
.num_sids
;
2476 if (num_members
== 0) {
2477 return NT_STATUS_OK
;
2480 result
= cli_rpc_pipe_open_noauth(rpc_pipe_np_smb_conn(pipe_hnd
),
2481 &ndr_table_lsarpc
.syntax_id
,
2483 if (!NT_STATUS_IS_OK(result
)) {
2484 d_fprintf(stderr
, "Couldn't open LSA pipe. Error was %s\n",
2485 nt_errstr(result
) );
2489 result
= rpccli_lsa_open_policy(lsa_pipe
, mem_ctx
, true,
2490 SEC_RIGHTS_MAXIMUM_ALLOWED
, &lsa_pol
);
2492 if (!NT_STATUS_IS_OK(result
)) {
2493 d_fprintf(stderr
, "Couldn't open LSA policy handle\n");
2494 TALLOC_FREE(lsa_pipe
);
2498 alias_sids
= TALLOC_ZERO_ARRAY(mem_ctx
, DOM_SID
, num_members
);
2500 d_fprintf(stderr
, "Out of memory\n");
2501 TALLOC_FREE(lsa_pipe
);
2502 return NT_STATUS_NO_MEMORY
;
2505 for (i
=0; i
<num_members
; i
++) {
2506 sid_copy(&alias_sids
[i
], sid_array
.sids
[i
].sid
);
2509 result
= rpccli_lsa_lookup_sids(lsa_pipe
, mem_ctx
, &lsa_pol
,
2510 num_members
, alias_sids
,
2511 &domains
, &names
, &types
);
2513 if (!NT_STATUS_IS_OK(result
) &&
2514 !NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
)) {
2515 d_fprintf(stderr
, "Couldn't lookup SIDs\n");
2516 TALLOC_FREE(lsa_pipe
);
2520 for (i
= 0; i
< num_members
; i
++) {
2522 sid_to_fstring(sid_str
, &alias_sids
[i
]);
2524 if (c
->opt_long_list_entries
) {
2525 printf("%s %s\\%s %d\n", sid_str
,
2526 domains
[i
] ? domains
[i
] : "*unknown*",
2527 names
[i
] ? names
[i
] : "*unknown*", types
[i
]);
2530 printf("%s\\%s\n", domains
[i
], names
[i
]);
2532 printf("%s\n", sid_str
);
2536 TALLOC_FREE(lsa_pipe
);
2537 return NT_STATUS_OK
;
2540 static NTSTATUS
rpc_group_members_internals(struct net_context
*c
,
2541 const DOM_SID
*domain_sid
,
2542 const char *domain_name
,
2543 struct cli_state
*cli
,
2544 struct rpc_pipe_client
*pipe_hnd
,
2545 TALLOC_CTX
*mem_ctx
,
2550 POLICY_HND connect_pol
, domain_pol
;
2551 struct samr_Ids rids
, rid_types
;
2552 struct lsa_String lsa_acct_name
;
2554 /* Get sam policy handle */
2556 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
2558 MAXIMUM_ALLOWED_ACCESS
,
2561 if (!NT_STATUS_IS_OK(result
))
2564 /* Get domain policy handle */
2566 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
2568 MAXIMUM_ALLOWED_ACCESS
,
2569 CONST_DISCARD(struct dom_sid2
*, domain_sid
),
2572 if (!NT_STATUS_IS_OK(result
))
2575 init_lsa_String(&lsa_acct_name
, argv
[0]); /* sure? */
2577 result
= rpccli_samr_LookupNames(pipe_hnd
, mem_ctx
,
2584 if (!NT_STATUS_IS_OK(result
)) {
2586 /* Ok, did not find it in the global sam, try with builtin */
2588 DOM_SID sid_Builtin
;
2590 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &domain_pol
);
2592 sid_copy(&sid_Builtin
, &global_sid_Builtin
);
2594 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
2596 MAXIMUM_ALLOWED_ACCESS
,
2600 if (!NT_STATUS_IS_OK(result
)) {
2601 d_fprintf(stderr
, "Couldn't find group %s\n", argv
[0]);
2605 result
= rpccli_samr_LookupNames(pipe_hnd
, mem_ctx
,
2612 if (!NT_STATUS_IS_OK(result
)) {
2613 d_fprintf(stderr
, "Couldn't find group %s\n", argv
[0]);
2618 if (rids
.count
!= 1) {
2619 d_fprintf(stderr
, "Couldn't find group %s\n", argv
[0]);
2623 if (rid_types
.ids
[0] == SID_NAME_DOM_GRP
) {
2624 return rpc_list_group_members(c
, pipe_hnd
, mem_ctx
, domain_name
,
2625 domain_sid
, &domain_pol
,
2629 if (rid_types
.ids
[0] == SID_NAME_ALIAS
) {
2630 return rpc_list_alias_members(c
, pipe_hnd
, mem_ctx
, &domain_pol
,
2634 return NT_STATUS_NO_SUCH_GROUP
;
2637 static int rpc_group_members(struct net_context
*c
, int argc
, const char **argv
)
2639 if (argc
!= 1 || c
->display_usage
) {
2640 return rpc_group_usage(c
, argc
, argv
);
2643 return run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
, 0,
2644 rpc_group_members_internals
,
2648 static int rpc_group_rename_internals(struct net_context
*c
, int argc
, const char **argv
)
2650 NET_API_STATUS status
;
2651 struct GROUP_INFO_0 g0
;
2655 d_printf("Usage: 'net rpc group rename group newname'\n");
2659 g0
.grpi0_name
= argv
[1];
2661 status
= NetGroupSetInfo(c
->opt_host
,
2668 d_fprintf(stderr
, "Renaming group %s failed with: %s\n",
2669 argv
[0], libnetapi_get_error_string(c
->netapi_ctx
,
2677 static int rpc_group_rename(struct net_context
*c
, int argc
, const char **argv
)
2679 if (argc
!= 2 || c
->display_usage
) {
2680 return rpc_group_usage(c
, argc
, argv
);
2683 return rpc_group_rename_internals(c
, argc
, argv
);
2687 * 'net rpc group' entrypoint.
2688 * @param argc Standard main() style argc.
2689 * @param argv Standard main() style argv. Initial components are already
2693 int net_rpc_group(struct net_context
*c
, int argc
, const char **argv
)
2695 NET_API_STATUS status
;
2697 struct functable func
[] = {
2702 "Create specified group",
2703 "net rpc group add\n"
2704 " Create specified group"
2710 "Delete specified group",
2711 "net rpc group delete\n"
2712 " Delete specified group"
2718 "Add member to group",
2719 "net rpc group addmem\n"
2720 " Add member to group"
2726 "Remove member from group",
2727 "net rpc group delmem\n"
2728 " Remove member from group"
2735 "net rpc group list\n"
2742 "List group members",
2743 "net rpc group members\n"
2744 " List group members"
2751 "net rpc group rename\n"
2754 {NULL
, NULL
, 0, NULL
, NULL
}
2757 status
= libnetapi_init(&c
->netapi_ctx
);
2761 libnetapi_set_username(c
->netapi_ctx
, c
->opt_user_name
);
2762 libnetapi_set_password(c
->netapi_ctx
, c
->opt_password
);
2763 if (c
->opt_kerberos
) {
2764 libnetapi_set_use_kerberos(c
->netapi_ctx
);
2768 if (c
->display_usage
) {
2769 d_printf("Usage:\n");
2770 d_printf("net rpc group\n"
2771 " Alias for net rpc group list global local "
2773 net_display_usage_from_functable(func
);
2777 return run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
, 0,
2778 rpc_group_list_internals
,
2782 return net_run_function(c
, argc
, argv
, "net rpc group", func
);
2785 /****************************************************************************/
2787 static int rpc_share_usage(struct net_context
*c
, int argc
, const char **argv
)
2789 return net_share_usage(c
, argc
, argv
);
2793 * Add a share on a remote RPC server.
2795 * @param argc Standard main() style argc.
2796 * @param argv Standard main() style argv. Initial components are already
2799 * @return A shell status integer (0 for success).
2802 static int rpc_share_add(struct net_context
*c
, int argc
, const char **argv
)
2804 NET_API_STATUS status
;
2807 uint32 type
= STYPE_DISKTREE
; /* only allow disk shares to be added */
2808 uint32 num_users
=0, perms
=0;
2809 char *password
=NULL
; /* don't allow a share password */
2810 struct SHARE_INFO_2 i2
;
2811 uint32_t parm_error
= 0;
2813 if ((argc
< 1) || !strchr(argv
[0], '=') || c
->display_usage
) {
2814 return rpc_share_usage(c
, argc
, argv
);
2817 if ((sharename
= talloc_strdup(c
, argv
[0])) == NULL
) {
2821 path
= strchr(sharename
, '=');
2828 i2
.shi2_netname
= sharename
;
2829 i2
.shi2_type
= type
;
2830 i2
.shi2_remark
= c
->opt_comment
;
2831 i2
.shi2_permissions
= perms
;
2832 i2
.shi2_max_uses
= c
->opt_maxusers
;
2833 i2
.shi2_current_uses
= num_users
;
2834 i2
.shi2_path
= path
;
2835 i2
.shi2_passwd
= password
;
2837 status
= NetShareAdd(c
->opt_host
,
2842 printf("NetShareAdd failed with: %s\n",
2843 libnetapi_get_error_string(c
->netapi_ctx
, status
));
2850 * Delete a share on a remote RPC server.
2852 * @param domain_sid The domain sid acquired from the remote server.
2853 * @param argc Standard main() style argc.
2854 * @param argv Standard main() style argv. Initial components are already
2857 * @return A shell status integer (0 for success).
2859 static int rpc_share_delete(struct net_context
*c
, int argc
, const char **argv
)
2861 if (argc
< 1 || c
->display_usage
) {
2862 return rpc_share_usage(c
, argc
, argv
);
2865 return NetShareDel(c
->opt_host
, argv
[0], 0);
2869 * Formatted print of share info
2871 * @param r pointer to SHARE_INFO_1 to format
2874 static void display_share_info_1(struct net_context
*c
,
2875 struct SHARE_INFO_1
*r
)
2877 if (c
->opt_long_list_entries
) {
2878 d_printf("%-12s %-8.8s %-50s\n",
2880 net_share_type_str(r
->shi1_type
& ~(STYPE_TEMPORARY
|STYPE_HIDDEN
)),
2883 d_printf("%s\n", r
->shi1_netname
);
2887 static WERROR
get_share_info(struct net_context
*c
,
2888 struct rpc_pipe_client
*pipe_hnd
,
2889 TALLOC_CTX
*mem_ctx
,
2893 struct srvsvc_NetShareInfoCtr
*info_ctr
)
2897 union srvsvc_NetShareInfo info
;
2899 /* no specific share requested, enumerate all */
2902 uint32_t preferred_len
= 0xffffffff;
2903 uint32_t total_entries
= 0;
2904 uint32_t resume_handle
= 0;
2906 info_ctr
->level
= level
;
2908 status
= rpccli_srvsvc_NetShareEnumAll(pipe_hnd
, mem_ctx
,
2918 /* request just one share */
2919 status
= rpccli_srvsvc_NetShareGetInfo(pipe_hnd
, mem_ctx
,
2926 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
)) {
2931 ZERO_STRUCTP(info_ctr
);
2933 info_ctr
->level
= level
;
2938 struct srvsvc_NetShareCtr1
*ctr1
;
2940 ctr1
= TALLOC_ZERO_P(mem_ctx
, struct srvsvc_NetShareCtr1
);
2941 W_ERROR_HAVE_NO_MEMORY(ctr1
);
2944 ctr1
->array
= info
.info1
;
2946 info_ctr
->ctr
.ctr1
= ctr1
;
2950 struct srvsvc_NetShareCtr2
*ctr2
;
2952 ctr2
= TALLOC_ZERO_P(mem_ctx
, struct srvsvc_NetShareCtr2
);
2953 W_ERROR_HAVE_NO_MEMORY(ctr2
);
2956 ctr2
->array
= info
.info2
;
2958 info_ctr
->ctr
.ctr2
= ctr2
;
2962 struct srvsvc_NetShareCtr502
*ctr502
;
2964 ctr502
= TALLOC_ZERO_P(mem_ctx
, struct srvsvc_NetShareCtr502
);
2965 W_ERROR_HAVE_NO_MEMORY(ctr502
);
2968 ctr502
->array
= info
.info502
;
2970 info_ctr
->ctr
.ctr502
= ctr502
;
2978 * 'net rpc share list' entrypoint.
2979 * @param argc Standard main() style argc.
2980 * @param argv Standard main() style argv. Initial components are already
2983 static int rpc_share_list(struct net_context
*c
, int argc
, const char **argv
)
2985 NET_API_STATUS status
;
2986 struct SHARE_INFO_1
*i1
= NULL
;
2987 uint32_t entries_read
= 0;
2988 uint32_t total_entries
= 0;
2989 uint32_t resume_handle
= 0;
2990 uint32_t i
, level
= 1;
2992 if (c
->display_usage
) {
2994 "net rpc share list\n"
2995 " List shares on remote server\n");
2999 status
= NetShareEnum(c
->opt_host
,
3001 (uint8_t **)(void *)&i1
,
3010 /* Display results */
3012 if (c
->opt_long_list_entries
) {
3014 "\nEnumerating shared resources (exports) on remote server:\n\n"
3015 "\nShare name Type Description\n"
3016 "---------- ---- -----------\n");
3018 for (i
= 0; i
< entries_read
; i
++)
3019 display_share_info_1(c
, &i1
[i
]);
3024 static bool check_share_availability(struct cli_state
*cli
, const char *netname
)
3026 if (!cli_send_tconX(cli
, netname
, "A:", "", 0)) {
3027 d_printf("skipping [%s]: not a file share.\n", netname
);
3037 static bool check_share_sanity(struct net_context
*c
, struct cli_state
*cli
,
3038 const char *netname
, uint32 type
)
3040 /* only support disk shares */
3041 if (! ( type
== STYPE_DISKTREE
|| type
== (STYPE_DISKTREE
| STYPE_HIDDEN
)) ) {
3042 printf("share [%s] is not a diskshare (type: %x)\n", netname
, type
);
3046 /* skip builtin shares */
3047 /* FIXME: should print$ be added too ? */
3048 if (strequal(netname
,"IPC$") || strequal(netname
,"ADMIN$") ||
3049 strequal(netname
,"global"))
3052 if (c
->opt_exclude
&& in_list(netname
, c
->opt_exclude
, false)) {
3053 printf("excluding [%s]\n", netname
);
3057 return check_share_availability(cli
, netname
);
3061 * Migrate shares from a remote RPC server to the local RPC server.
3063 * All parameters are provided by the run_rpc_command function, except for
3064 * argc, argv which are passed through.
3066 * @param domain_sid The domain sid acquired from the remote server.
3067 * @param cli A cli_state connected to the server.
3068 * @param mem_ctx Talloc context, destroyed on completion of the function.
3069 * @param argc Standard main() style argc.
3070 * @param argv Standard main() style argv. Initial components are already
3073 * @return Normal NTSTATUS return.
3076 static NTSTATUS
rpc_share_migrate_shares_internals(struct net_context
*c
,
3077 const DOM_SID
*domain_sid
,
3078 const char *domain_name
,
3079 struct cli_state
*cli
,
3080 struct rpc_pipe_client
*pipe_hnd
,
3081 TALLOC_CTX
*mem_ctx
,
3086 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
3087 struct srvsvc_NetShareInfoCtr ctr_src
;
3089 struct rpc_pipe_client
*srvsvc_pipe
= NULL
;
3090 struct cli_state
*cli_dst
= NULL
;
3091 uint32 level
= 502; /* includes secdesc */
3092 uint32_t parm_error
= 0;
3094 result
= get_share_info(c
, pipe_hnd
, mem_ctx
, level
, argc
, argv
,
3096 if (!W_ERROR_IS_OK(result
))
3099 /* connect destination PI_SRVSVC */
3100 nt_status
= connect_dst_pipe(c
, &cli_dst
, &srvsvc_pipe
,
3101 &ndr_table_srvsvc
.syntax_id
);
3102 if (!NT_STATUS_IS_OK(nt_status
))
3106 for (i
= 0; i
< ctr_src
.ctr
.ctr502
->count
; i
++) {
3108 union srvsvc_NetShareInfo info
;
3109 struct srvsvc_NetShareInfo502 info502
=
3110 ctr_src
.ctr
.ctr502
->array
[i
];
3112 /* reset error-code */
3113 nt_status
= NT_STATUS_UNSUCCESSFUL
;
3115 if (!check_share_sanity(c
, cli
, info502
.name
, info502
.type
))
3118 /* finally add the share on the dst server */
3120 printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n",
3121 info502
.name
, info502
.path
, info502
.comment
);
3123 info
.info502
= &info502
;
3125 nt_status
= rpccli_srvsvc_NetShareAdd(srvsvc_pipe
, mem_ctx
,
3126 srvsvc_pipe
->desthost
,
3132 if (W_ERROR_V(result
) == W_ERROR_V(WERR_ALREADY_EXISTS
)) {
3133 printf(" [%s] does already exist\n",
3138 if (!NT_STATUS_IS_OK(nt_status
) || !W_ERROR_IS_OK(result
)) {
3139 printf("cannot add share: %s\n", dos_errstr(result
));
3145 nt_status
= NT_STATUS_OK
;
3149 cli_shutdown(cli_dst
);
3157 * Migrate shares from a RPC server to another.
3159 * @param argc Standard main() style argc.
3160 * @param argv Standard main() style argv. Initial components are already
3163 * @return A shell status integer (0 for success).
3165 static int rpc_share_migrate_shares(struct net_context
*c
, int argc
,
3168 if (c
->display_usage
) {
3170 "net rpc share migrate shares\n"
3171 " Migrate shares to local server\n");
3176 printf("no server to migrate\n");
3180 return run_rpc_command(c
, NULL
, &ndr_table_srvsvc
.syntax_id
, 0,
3181 rpc_share_migrate_shares_internals
,
3188 * @param f file_info
3189 * @param mask current search mask
3190 * @param state arg-pointer
3193 static void copy_fn(const char *mnt
, file_info
*f
,
3194 const char *mask
, void *state
)
3196 static NTSTATUS nt_status
;
3197 static struct copy_clistate
*local_state
;
3198 static fstring filename
, new_mask
;
3201 struct net_context
*c
;
3203 local_state
= (struct copy_clistate
*)state
;
3204 nt_status
= NT_STATUS_UNSUCCESSFUL
;
3208 if (strequal(f
->name
, ".") || strequal(f
->name
, ".."))
3211 DEBUG(3,("got mask: %s, name: %s\n", mask
, f
->name
));
3214 if (f
->mode
& aDIR
) {
3216 DEBUG(3,("got dir: %s\n", f
->name
));
3218 fstrcpy(dir
, local_state
->cwd
);
3220 fstrcat(dir
, f
->name
);
3222 switch (net_mode_share
)
3224 case NET_MODE_SHARE_MIGRATE
:
3225 /* create that directory */
3226 nt_status
= net_copy_file(c
, local_state
->mem_ctx
,
3227 local_state
->cli_share_src
,
3228 local_state
->cli_share_dst
,
3230 c
->opt_acls
? true : false,
3231 c
->opt_attrs
? true : false,
3232 c
->opt_timestamps
? true:false,
3236 d_fprintf(stderr
, "Unsupported mode %d\n", net_mode_share
);
3240 if (!NT_STATUS_IS_OK(nt_status
))
3241 printf("could not handle dir %s: %s\n",
3242 dir
, nt_errstr(nt_status
));
3244 /* search below that directory */
3245 fstrcpy(new_mask
, dir
);
3246 fstrcat(new_mask
, "\\*");
3248 old_dir
= local_state
->cwd
;
3249 local_state
->cwd
= dir
;
3250 if (!sync_files(local_state
, new_mask
))
3251 printf("could not handle files\n");
3252 local_state
->cwd
= old_dir
;
3259 fstrcpy(filename
, local_state
->cwd
);
3260 fstrcat(filename
, "\\");
3261 fstrcat(filename
, f
->name
);
3263 DEBUG(3,("got file: %s\n", filename
));
3265 switch (net_mode_share
)
3267 case NET_MODE_SHARE_MIGRATE
:
3268 nt_status
= net_copy_file(c
, local_state
->mem_ctx
,
3269 local_state
->cli_share_src
,
3270 local_state
->cli_share_dst
,
3272 c
->opt_acls
? true : false,
3273 c
->opt_attrs
? true : false,
3274 c
->opt_timestamps
? true: false,
3278 d_fprintf(stderr
, "Unsupported file mode %d\n", net_mode_share
);
3282 if (!NT_STATUS_IS_OK(nt_status
))
3283 printf("could not handle file %s: %s\n",
3284 filename
, nt_errstr(nt_status
));
3289 * sync files, can be called recursivly to list files
3290 * and then call copy_fn for each file
3292 * @param cp_clistate pointer to the copy_clistate we work with
3293 * @param mask the current search mask
3295 * @return Boolean result
3297 static bool sync_files(struct copy_clistate
*cp_clistate
, const char *mask
)
3299 struct cli_state
*targetcli
;
3300 char *targetpath
= NULL
;
3302 DEBUG(3,("calling cli_list with mask: %s\n", mask
));
3304 if ( !cli_resolve_path(talloc_tos(), "", cp_clistate
->cli_share_src
,
3305 mask
, &targetcli
, &targetpath
) ) {
3306 d_fprintf(stderr
, "cli_resolve_path %s failed with error: %s\n",
3307 mask
, cli_errstr(cp_clistate
->cli_share_src
));
3311 if (cli_list(targetcli
, targetpath
, cp_clistate
->attribute
, copy_fn
, cp_clistate
) == -1) {
3312 d_fprintf(stderr
, "listing %s failed with error: %s\n",
3313 mask
, cli_errstr(targetcli
));
3322 * Set the top level directory permissions before we do any further copies.
3323 * Should set up ACL inheritance.
3326 bool copy_top_level_perms(struct net_context
*c
,
3327 struct copy_clistate
*cp_clistate
,
3328 const char *sharename
)
3330 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
3332 switch (net_mode_share
) {
3333 case NET_MODE_SHARE_MIGRATE
:
3334 DEBUG(3,("calling net_copy_fileattr for '.' directory in share %s\n", sharename
));
3335 nt_status
= net_copy_fileattr(c
,
3336 cp_clistate
->mem_ctx
,
3337 cp_clistate
->cli_share_src
,
3338 cp_clistate
->cli_share_dst
,
3340 c
->opt_acls
? true : false,
3341 c
->opt_attrs
? true : false,
3342 c
->opt_timestamps
? true: false,
3346 d_fprintf(stderr
, "Unsupported mode %d\n", net_mode_share
);
3350 if (!NT_STATUS_IS_OK(nt_status
)) {
3351 printf("Could handle directory attributes for top level directory of share %s. Error %s\n",
3352 sharename
, nt_errstr(nt_status
));
3360 * Sync all files inside a remote share to another share (over smb).
3362 * All parameters are provided by the run_rpc_command function, except for
3363 * argc, argv which are passed through.
3365 * @param domain_sid The domain sid acquired from the remote server.
3366 * @param cli A cli_state connected to the server.
3367 * @param mem_ctx Talloc context, destroyed on completion of the function.
3368 * @param argc Standard main() style argc.
3369 * @param argv Standard main() style argv. Initial components are already
3372 * @return Normal NTSTATUS return.
3375 static NTSTATUS
rpc_share_migrate_files_internals(struct net_context
*c
,
3376 const DOM_SID
*domain_sid
,
3377 const char *domain_name
,
3378 struct cli_state
*cli
,
3379 struct rpc_pipe_client
*pipe_hnd
,
3380 TALLOC_CTX
*mem_ctx
,
3385 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
3386 struct srvsvc_NetShareInfoCtr ctr_src
;
3389 struct copy_clistate cp_clistate
;
3390 bool got_src_share
= false;
3391 bool got_dst_share
= false;
3392 const char *mask
= "\\*";
3395 dst
= SMB_STRDUP(c
->opt_destination
?c
->opt_destination
:"127.0.0.1");
3397 nt_status
= NT_STATUS_NO_MEMORY
;
3401 result
= get_share_info(c
, pipe_hnd
, mem_ctx
, level
, argc
, argv
,
3404 if (!W_ERROR_IS_OK(result
))
3407 for (i
= 0; i
< ctr_src
.ctr
.ctr502
->count
; i
++) {
3409 struct srvsvc_NetShareInfo502 info502
=
3410 ctr_src
.ctr
.ctr502
->array
[i
];
3412 if (!check_share_sanity(c
, cli
, info502
.name
, info502
.type
))
3415 /* one might not want to mirror whole discs :) */
3416 if (strequal(info502
.name
, "print$") || info502
.name
[1] == '$') {
3417 d_printf("skipping [%s]: builtin/hidden share\n", info502
.name
);
3421 switch (net_mode_share
)
3423 case NET_MODE_SHARE_MIGRATE
:
3427 d_fprintf(stderr
, "Unsupported mode %d\n", net_mode_share
);
3430 printf(" [%s] files and directories %s ACLs, %s DOS Attributes %s\n",
3432 c
->opt_acls
? "including" : "without",
3433 c
->opt_attrs
? "including" : "without",
3434 c
->opt_timestamps
? "(preserving timestamps)" : "");
3436 cp_clistate
.mem_ctx
= mem_ctx
;
3437 cp_clistate
.cli_share_src
= NULL
;
3438 cp_clistate
.cli_share_dst
= NULL
;
3439 cp_clistate
.cwd
= NULL
;
3440 cp_clistate
.attribute
= aSYSTEM
| aHIDDEN
| aDIR
;
3443 /* open share source */
3444 nt_status
= connect_to_service(c
, &cp_clistate
.cli_share_src
,
3445 &cli
->dest_ss
, cli
->desthost
,
3446 info502
.name
, "A:");
3447 if (!NT_STATUS_IS_OK(nt_status
))
3450 got_src_share
= true;
3452 if (net_mode_share
== NET_MODE_SHARE_MIGRATE
) {
3453 /* open share destination */
3454 nt_status
= connect_to_service(c
, &cp_clistate
.cli_share_dst
,
3455 NULL
, dst
, info502
.name
, "A:");
3456 if (!NT_STATUS_IS_OK(nt_status
))
3459 got_dst_share
= true;
3462 if (!copy_top_level_perms(c
, &cp_clistate
, info502
.name
)) {
3463 d_fprintf(stderr
, "Could not handle the top level directory permissions for the share: %s\n", info502
.name
);
3464 nt_status
= NT_STATUS_UNSUCCESSFUL
;
3468 if (!sync_files(&cp_clistate
, mask
)) {
3469 d_fprintf(stderr
, "could not handle files for share: %s\n", info502
.name
);
3470 nt_status
= NT_STATUS_UNSUCCESSFUL
;
3475 nt_status
= NT_STATUS_OK
;
3480 cli_shutdown(cp_clistate
.cli_share_src
);
3483 cli_shutdown(cp_clistate
.cli_share_dst
);
3490 static int rpc_share_migrate_files(struct net_context
*c
, int argc
, const char **argv
)
3492 if (c
->display_usage
) {
3494 "net share migrate files\n"
3495 " Migrate files to local server\n");
3500 d_printf("no server to migrate\n");
3504 return run_rpc_command(c
, NULL
, &ndr_table_srvsvc
.syntax_id
, 0,
3505 rpc_share_migrate_files_internals
,
3510 * Migrate share-ACLs from a remote RPC server to the local RPC server.
3512 * All parameters are provided by the run_rpc_command function, except for
3513 * argc, argv which are passed through.
3515 * @param domain_sid The domain sid acquired from the remote server.
3516 * @param cli A cli_state connected to the server.
3517 * @param mem_ctx Talloc context, destroyed on completion of the function.
3518 * @param argc Standard main() style argc.
3519 * @param argv Standard main() style argv. Initial components are already
3522 * @return Normal NTSTATUS return.
3525 static NTSTATUS
rpc_share_migrate_security_internals(struct net_context
*c
,
3526 const DOM_SID
*domain_sid
,
3527 const char *domain_name
,
3528 struct cli_state
*cli
,
3529 struct rpc_pipe_client
*pipe_hnd
,
3530 TALLOC_CTX
*mem_ctx
,
3535 NTSTATUS nt_status
= NT_STATUS_UNSUCCESSFUL
;
3536 struct srvsvc_NetShareInfoCtr ctr_src
;
3537 union srvsvc_NetShareInfo info
;
3539 struct rpc_pipe_client
*srvsvc_pipe
= NULL
;
3540 struct cli_state
*cli_dst
= NULL
;
3541 uint32 level
= 502; /* includes secdesc */
3542 uint32_t parm_error
= 0;
3544 result
= get_share_info(c
, pipe_hnd
, mem_ctx
, level
, argc
, argv
,
3547 if (!W_ERROR_IS_OK(result
))
3550 /* connect destination PI_SRVSVC */
3551 nt_status
= connect_dst_pipe(c
, &cli_dst
, &srvsvc_pipe
,
3552 &ndr_table_srvsvc
.syntax_id
);
3553 if (!NT_STATUS_IS_OK(nt_status
))
3557 for (i
= 0; i
< ctr_src
.ctr
.ctr502
->count
; i
++) {
3559 struct srvsvc_NetShareInfo502 info502
=
3560 ctr_src
.ctr
.ctr502
->array
[i
];
3562 /* reset error-code */
3563 nt_status
= NT_STATUS_UNSUCCESSFUL
;
3565 if (!check_share_sanity(c
, cli
, info502
.name
, info502
.type
))
3568 printf("migrating: [%s], path: %s, comment: %s, including share-ACLs\n",
3569 info502
.name
, info502
.path
, info502
.comment
);
3572 display_sec_desc(info502
.sd_buf
.sd
);
3574 /* FIXME: shouldn't we be able to just set the security descriptor ? */
3575 info
.info502
= &info502
;
3577 /* finally modify the share on the dst server */
3578 nt_status
= rpccli_srvsvc_NetShareSetInfo(srvsvc_pipe
, mem_ctx
,
3579 srvsvc_pipe
->desthost
,
3585 if (!NT_STATUS_IS_OK(nt_status
) || !W_ERROR_IS_OK(result
)) {
3586 printf("cannot set share-acl: %s\n", dos_errstr(result
));
3592 nt_status
= NT_STATUS_OK
;
3596 cli_shutdown(cli_dst
);
3604 * Migrate share-acls from a RPC server to another.
3606 * @param argc Standard main() style argc.
3607 * @param argv Standard main() style argv. Initial components are already
3610 * @return A shell status integer (0 for success).
3612 static int rpc_share_migrate_security(struct net_context
*c
, int argc
,
3615 if (c
->display_usage
) {
3617 "net rpc share migrate security\n"
3618 " Migrate share-acls to local server\n");
3623 d_printf("no server to migrate\n");
3627 return run_rpc_command(c
, NULL
, &ndr_table_srvsvc
.syntax_id
, 0,
3628 rpc_share_migrate_security_internals
,
3633 * Migrate shares (including share-definitions, share-acls and files with acls/attrs)
3634 * from one server to another.
3636 * @param argc Standard main() style argc.
3637 * @param argv Standard main() style argv. Initial components are already
3640 * @return A shell status integer (0 for success).
3643 static int rpc_share_migrate_all(struct net_context
*c
, int argc
,
3648 if (c
->display_usage
) {
3650 "net rpc share migrate all\n"
3651 " Migrates shares including all share settings\n");
3656 d_printf("no server to migrate\n");
3660 /* order is important. we don't want to be locked out by the share-acl
3661 * before copying files - gd */
3663 ret
= run_rpc_command(c
, NULL
, &ndr_table_srvsvc
.syntax_id
, 0,
3664 rpc_share_migrate_shares_internals
, argc
, argv
);
3668 ret
= run_rpc_command(c
, NULL
, &ndr_table_srvsvc
.syntax_id
, 0,
3669 rpc_share_migrate_files_internals
, argc
, argv
);
3673 return run_rpc_command(c
, NULL
, &ndr_table_srvsvc
.syntax_id
, 0,
3674 rpc_share_migrate_security_internals
, argc
,
3680 * 'net rpc share migrate' entrypoint.
3681 * @param argc Standard main() style argc.
3682 * @param argv Standard main() style argv. Initial components are already
3685 static int rpc_share_migrate(struct net_context
*c
, int argc
, const char **argv
)
3688 struct functable func
[] = {
3691 rpc_share_migrate_all
,
3693 "Migrate shares from remote to local server",
3694 "net rpc share migrate all\n"
3695 " Migrate shares from remote to local server"
3699 rpc_share_migrate_files
,
3701 "Migrate files from remote to local server",
3702 "net rpc share migrate files\n"
3703 " Migrate files from remote to local server"
3707 rpc_share_migrate_security
,
3709 "Migrate share-ACLs from remote to local server",
3710 "net rpc share migrate security\n"
3711 " Migrate share-ACLs from remote to local server"
3715 rpc_share_migrate_shares
,
3717 "Migrate shares from remote to local server",
3718 "net rpc share migrate shares\n"
3719 " Migrate shares from remote to local server"
3721 {NULL
, NULL
, 0, NULL
, NULL
}
3724 net_mode_share
= NET_MODE_SHARE_MIGRATE
;
3726 return net_run_function(c
, argc
, argv
, "net rpc share migrate", func
);
3735 static int num_server_aliases
;
3736 static struct full_alias
*server_aliases
;
3739 * Add an alias to the static list.
3741 static void push_alias(TALLOC_CTX
*mem_ctx
, struct full_alias
*alias
)
3743 if (server_aliases
== NULL
)
3744 server_aliases
= SMB_MALLOC_ARRAY(struct full_alias
, 100);
3746 server_aliases
[num_server_aliases
] = *alias
;
3747 num_server_aliases
+= 1;
3751 * For a specific domain on the server, fetch all the aliases
3752 * and their members. Add all of them to the server_aliases.
3755 static NTSTATUS
rpc_fetch_domain_aliases(struct rpc_pipe_client
*pipe_hnd
,
3756 TALLOC_CTX
*mem_ctx
,
3757 POLICY_HND
*connect_pol
,
3758 const DOM_SID
*domain_sid
)
3760 uint32 start_idx
, max_entries
, num_entries
, i
;
3761 struct samr_SamArray
*groups
= NULL
;
3763 POLICY_HND domain_pol
;
3765 /* Get domain policy handle */
3767 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
3769 MAXIMUM_ALLOWED_ACCESS
,
3770 CONST_DISCARD(struct dom_sid2
*, domain_sid
),
3772 if (!NT_STATUS_IS_OK(result
))
3779 result
= rpccli_samr_EnumDomainAliases(pipe_hnd
, mem_ctx
,
3785 for (i
= 0; i
< num_entries
; i
++) {
3787 POLICY_HND alias_pol
;
3788 struct full_alias alias
;
3789 struct lsa_SidArray sid_array
;
3792 result
= rpccli_samr_OpenAlias(pipe_hnd
, mem_ctx
,
3794 MAXIMUM_ALLOWED_ACCESS
,
3795 groups
->entries
[i
].idx
,
3797 if (!NT_STATUS_IS_OK(result
))
3800 result
= rpccli_samr_GetMembersInAlias(pipe_hnd
, mem_ctx
,
3803 if (!NT_STATUS_IS_OK(result
))
3806 alias
.num_members
= sid_array
.num_sids
;
3808 result
= rpccli_samr_Close(pipe_hnd
, mem_ctx
, &alias_pol
);
3809 if (!NT_STATUS_IS_OK(result
))
3812 alias
.members
= NULL
;
3814 if (alias
.num_members
> 0) {
3815 alias
.members
= SMB_MALLOC_ARRAY(DOM_SID
, alias
.num_members
);
3817 for (j
= 0; j
< alias
.num_members
; j
++)
3818 sid_copy(&alias
.members
[j
],
3819 sid_array
.sids
[j
].sid
);
3822 sid_copy(&alias
.sid
, domain_sid
);
3823 sid_append_rid(&alias
.sid
, groups
->entries
[i
].idx
);
3825 push_alias(mem_ctx
, &alias
);
3827 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
3829 result
= NT_STATUS_OK
;
3832 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &domain_pol
);
3838 * Dump server_aliases as names for debugging purposes.
3841 static NTSTATUS
rpc_aliaslist_dump(struct net_context
*c
,
3842 const DOM_SID
*domain_sid
,
3843 const char *domain_name
,
3844 struct cli_state
*cli
,
3845 struct rpc_pipe_client
*pipe_hnd
,
3846 TALLOC_CTX
*mem_ctx
,
3854 result
= rpccli_lsa_open_policy(pipe_hnd
, mem_ctx
, true,
3855 SEC_RIGHTS_MAXIMUM_ALLOWED
,
3857 if (!NT_STATUS_IS_OK(result
))
3860 for (i
=0; i
<num_server_aliases
; i
++) {
3863 enum lsa_SidType
*types
;
3866 struct full_alias
*alias
= &server_aliases
[i
];
3868 result
= rpccli_lsa_lookup_sids(pipe_hnd
, mem_ctx
, &lsa_pol
, 1,
3870 &domains
, &names
, &types
);
3871 if (!NT_STATUS_IS_OK(result
))
3874 DEBUG(1, ("%s\\%s %d: ", domains
[0], names
[0], types
[0]));
3876 if (alias
->num_members
== 0) {
3881 result
= rpccli_lsa_lookup_sids(pipe_hnd
, mem_ctx
, &lsa_pol
,
3884 &domains
, &names
, &types
);
3886 if (!NT_STATUS_IS_OK(result
) &&
3887 !NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
))
3890 for (j
=0; j
<alias
->num_members
; j
++)
3891 DEBUG(1, ("%s\\%s (%d); ",
3892 domains
[j
] ? domains
[j
] : "*unknown*",
3893 names
[j
] ? names
[j
] : "*unknown*",types
[j
]));
3897 rpccli_lsa_Close(pipe_hnd
, mem_ctx
, &lsa_pol
);
3899 return NT_STATUS_OK
;
3903 * Fetch a list of all server aliases and their members into
3907 static NTSTATUS
rpc_aliaslist_internals(struct net_context
*c
,
3908 const DOM_SID
*domain_sid
,
3909 const char *domain_name
,
3910 struct cli_state
*cli
,
3911 struct rpc_pipe_client
*pipe_hnd
,
3912 TALLOC_CTX
*mem_ctx
,
3917 POLICY_HND connect_pol
;
3919 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
3921 MAXIMUM_ALLOWED_ACCESS
,
3924 if (!NT_STATUS_IS_OK(result
))
3927 result
= rpc_fetch_domain_aliases(pipe_hnd
, mem_ctx
, &connect_pol
,
3928 &global_sid_Builtin
);
3930 if (!NT_STATUS_IS_OK(result
))
3933 result
= rpc_fetch_domain_aliases(pipe_hnd
, mem_ctx
, &connect_pol
,
3936 rpccli_samr_Close(pipe_hnd
, mem_ctx
, &connect_pol
);
3941 static void init_user_token(NT_USER_TOKEN
*token
, DOM_SID
*user_sid
)
3943 token
->num_sids
= 4;
3945 if (!(token
->user_sids
= SMB_MALLOC_ARRAY(DOM_SID
, 4))) {
3946 d_fprintf(stderr
, "malloc failed\n");
3947 token
->num_sids
= 0;
3951 token
->user_sids
[0] = *user_sid
;
3952 sid_copy(&token
->user_sids
[1], &global_sid_World
);
3953 sid_copy(&token
->user_sids
[2], &global_sid_Network
);
3954 sid_copy(&token
->user_sids
[3], &global_sid_Authenticated_Users
);
3957 static void free_user_token(NT_USER_TOKEN
*token
)
3959 SAFE_FREE(token
->user_sids
);
3962 static void add_sid_to_token(NT_USER_TOKEN
*token
, DOM_SID
*sid
)
3964 if (is_sid_in_token(token
, sid
))
3967 token
->user_sids
= SMB_REALLOC_ARRAY(token
->user_sids
, DOM_SID
, token
->num_sids
+1);
3968 if (!token
->user_sids
) {
3972 sid_copy(&token
->user_sids
[token
->num_sids
], sid
);
3974 token
->num_sids
+= 1;
3979 NT_USER_TOKEN token
;
3982 static void dump_user_token(struct user_token
*token
)
3986 d_printf("%s\n", token
->name
);
3988 for (i
=0; i
<token
->token
.num_sids
; i
++) {
3989 d_printf(" %s\n", sid_string_tos(&token
->token
.user_sids
[i
]));
3993 static bool is_alias_member(DOM_SID
*sid
, struct full_alias
*alias
)
3997 for (i
=0; i
<alias
->num_members
; i
++) {
3998 if (sid_compare(sid
, &alias
->members
[i
]) == 0)
4005 static void collect_sid_memberships(NT_USER_TOKEN
*token
, DOM_SID sid
)
4009 for (i
=0; i
<num_server_aliases
; i
++) {
4010 if (is_alias_member(&sid
, &server_aliases
[i
]))
4011 add_sid_to_token(token
, &server_aliases
[i
].sid
);
4016 * We got a user token with all the SIDs we can know about without asking the
4017 * server directly. These are the user and domain group sids. All of these can
4018 * be members of aliases. So scan the list of aliases for each of the SIDs and
4019 * add them to the token.
4022 static void collect_alias_memberships(NT_USER_TOKEN
*token
)
4024 int num_global_sids
= token
->num_sids
;
4027 for (i
=0; i
<num_global_sids
; i
++) {
4028 collect_sid_memberships(token
, token
->user_sids
[i
]);
4032 static bool get_user_sids(const char *domain
, const char *user
, NT_USER_TOKEN
*token
)
4034 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
4035 enum wbcSidType type
;
4037 struct wbcDomainSid wsid
;
4038 char *sid_str
= NULL
;
4040 uint32_t num_groups
;
4041 gid_t
*groups
= NULL
;
4044 fstr_sprintf(full_name
, "%s%c%s",
4045 domain
, *lp_winbind_separator(), user
);
4047 /* First let's find out the user sid */
4049 wbc_status
= wbcLookupName(domain
, user
, &wsid
, &type
);
4051 if (!WBC_ERROR_IS_OK(wbc_status
)) {
4052 DEBUG(1, ("winbind could not find %s: %s\n",
4053 full_name
, wbcErrorString(wbc_status
)));
4057 wbc_status
= wbcSidToString(&wsid
, &sid_str
);
4058 if (!WBC_ERROR_IS_OK(wbc_status
)) {
4062 if (type
!= SID_NAME_USER
) {
4063 wbcFreeMemory(sid_str
);
4064 DEBUG(1, ("%s is not a user\n", full_name
));
4068 if (!string_to_sid(&user_sid
, sid_str
)) {
4069 DEBUG(1,("Could not convert sid %s from string\n", sid_str
));
4073 wbcFreeMemory(sid_str
);
4076 init_user_token(token
, &user_sid
);
4078 /* And now the groups winbind knows about */
4080 wbc_status
= wbcGetGroups(full_name
, &num_groups
, &groups
);
4081 if (!WBC_ERROR_IS_OK(wbc_status
)) {
4082 DEBUG(1, ("winbind could not get groups of %s: %s\n",
4083 full_name
, wbcErrorString(wbc_status
)));
4087 for (i
= 0; i
< num_groups
; i
++) {
4088 gid_t gid
= groups
[i
];
4091 wbc_status
= wbcGidToSid(gid
, &wsid
);
4092 if (!WBC_ERROR_IS_OK(wbc_status
)) {
4093 DEBUG(1, ("winbind could not find SID of gid %d: %s\n",
4094 gid
, wbcErrorString(wbc_status
)));
4095 wbcFreeMemory(groups
);
4099 wbc_status
= wbcSidToString(&wsid
, &sid_str
);
4100 if (!WBC_ERROR_IS_OK(wbc_status
)) {
4101 wbcFreeMemory(groups
);
4105 DEBUG(3, (" %s\n", sid_str
));
4107 string_to_sid(&sid
, sid_str
);
4108 wbcFreeMemory(sid_str
);
4111 add_sid_to_token(token
, &sid
);
4113 wbcFreeMemory(groups
);
4119 * Get a list of all user tokens we want to look at
4122 static bool get_user_tokens(struct net_context
*c
, int *num_tokens
,
4123 struct user_token
**user_tokens
)
4125 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
4126 uint32_t i
, num_users
;
4128 struct user_token
*result
;
4129 TALLOC_CTX
*frame
= NULL
;
4131 if (lp_winbind_use_default_domain() &&
4132 (c
->opt_target_workgroup
== NULL
)) {
4133 d_fprintf(stderr
, "winbind use default domain = yes set, "
4134 "please specify a workgroup\n");
4138 /* Send request to winbind daemon */
4140 wbc_status
= wbcListUsers(NULL
, &num_users
, &users
);
4141 if (!WBC_ERROR_IS_OK(wbc_status
)) {
4142 DEBUG(1, ("winbind could not list users: %s\n",
4143 wbcErrorString(wbc_status
)));
4147 result
= SMB_MALLOC_ARRAY(struct user_token
, num_users
);
4149 if (result
== NULL
) {
4150 DEBUG(1, ("Could not malloc sid array\n"));
4151 wbcFreeMemory(users
);
4155 frame
= talloc_stackframe();
4156 for (i
=0; i
< num_users
; i
++) {
4157 fstring domain
, user
;
4160 fstrcpy(result
[i
].name
, users
[i
]);
4162 p
= strchr(users
[i
], *lp_winbind_separator());
4164 DEBUG(3, ("%s\n", users
[i
]));
4167 fstrcpy(domain
, c
->opt_target_workgroup
);
4168 fstrcpy(user
, users
[i
]);
4171 fstrcpy(domain
, users
[i
]);
4176 get_user_sids(domain
, user
, &(result
[i
].token
));
4180 wbcFreeMemory(users
);
4182 *num_tokens
= num_users
;
4183 *user_tokens
= result
;
4188 static bool get_user_tokens_from_file(FILE *f
,
4190 struct user_token
**tokens
)
4192 struct user_token
*token
= NULL
;
4197 if (fgets(line
, sizeof(line
)-1, f
) == NULL
) {
4201 if (line
[strlen(line
)-1] == '\n')
4202 line
[strlen(line
)-1] = '\0';
4204 if (line
[0] == ' ') {
4208 if(!string_to_sid(&sid
, &line
[1])) {
4209 DEBUG(1,("get_user_tokens_from_file: Could "
4210 "not convert sid %s \n",&line
[1]));
4214 if (token
== NULL
) {
4215 DEBUG(0, ("File does not begin with username"));
4219 add_sid_to_token(&token
->token
, &sid
);
4223 /* And a new user... */
4226 *tokens
= SMB_REALLOC_ARRAY(*tokens
, struct user_token
, *num_tokens
);
4227 if (*tokens
== NULL
) {
4228 DEBUG(0, ("Could not realloc tokens\n"));
4232 token
= &((*tokens
)[*num_tokens
-1]);
4234 fstrcpy(token
->name
, line
);
4235 token
->token
.num_sids
= 0;
4236 token
->token
.user_sids
= NULL
;
4245 * Show the list of all users that have access to a share
4248 static void show_userlist(struct rpc_pipe_client
*pipe_hnd
,
4249 TALLOC_CTX
*mem_ctx
,
4250 const char *netname
,
4252 struct user_token
*tokens
)
4255 SEC_DESC
*share_sd
= NULL
;
4256 SEC_DESC
*root_sd
= NULL
;
4257 struct cli_state
*cli
= rpc_pipe_np_smb_conn(pipe_hnd
);
4259 union srvsvc_NetShareInfo info
;
4264 status
= rpccli_srvsvc_NetShareGetInfo(pipe_hnd
, mem_ctx
,
4271 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
)) {
4272 DEBUG(1, ("Coult not query secdesc for share %s\n",
4277 share_sd
= info
.info502
->sd_buf
.sd
;
4278 if (share_sd
== NULL
) {
4279 DEBUG(1, ("Got no secdesc for share %s\n",
4285 if (!cli_send_tconX(cli
, netname
, "A:", "", 0)) {
4289 fnum
= cli_nt_create(cli
, "\\", READ_CONTROL_ACCESS
);
4292 root_sd
= cli_query_secdesc(cli
, fnum
, mem_ctx
);
4295 for (i
=0; i
<num_tokens
; i
++) {
4298 if (share_sd
!= NULL
) {
4299 status
= se_access_check(share_sd
, &tokens
[i
].token
,
4302 if (!NT_STATUS_IS_OK(status
)) {
4303 DEBUG(1, ("Could not check share_sd for "
4310 if (root_sd
== NULL
) {
4311 d_printf(" %s\n", tokens
[i
].name
);
4315 status
= se_access_check(root_sd
, &tokens
[i
].token
,
4317 if (!NT_STATUS_IS_OK(status
)) {
4318 DEBUG(1, ("Could not check root_sd for user %s\n",
4322 d_printf(" %s\n", tokens
[i
].name
);
4326 cli_close(cli
, fnum
);
4338 static void collect_share(const char *name
, uint32 m
,
4339 const char *comment
, void *state
)
4341 struct share_list
*share_list
= (struct share_list
*)state
;
4343 if (m
!= STYPE_DISKTREE
)
4346 share_list
->num_shares
+= 1;
4347 share_list
->shares
= SMB_REALLOC_ARRAY(share_list
->shares
, char *, share_list
->num_shares
);
4348 if (!share_list
->shares
) {
4349 share_list
->num_shares
= 0;
4352 share_list
->shares
[share_list
->num_shares
-1] = SMB_STRDUP(name
);
4356 * List shares on a remote RPC server, including the security descriptors.
4358 * All parameters are provided by the run_rpc_command function, except for
4359 * argc, argv which are passed through.
4361 * @param domain_sid The domain sid acquired from the remote server.
4362 * @param cli A cli_state connected to the server.
4363 * @param mem_ctx Talloc context, destroyed on completion of the function.
4364 * @param argc Standard main() style argc.
4365 * @param argv Standard main() style argv. Initial components are already
4368 * @return Normal NTSTATUS return.
4371 static NTSTATUS
rpc_share_allowedusers_internals(struct net_context
*c
,
4372 const DOM_SID
*domain_sid
,
4373 const char *domain_name
,
4374 struct cli_state
*cli
,
4375 struct rpc_pipe_client
*pipe_hnd
,
4376 TALLOC_CTX
*mem_ctx
,
4385 struct user_token
*tokens
= NULL
;
4388 struct share_list share_list
;
4393 f
= fopen(argv
[0], "r");
4397 DEBUG(0, ("Could not open userlist: %s\n", strerror(errno
)));
4398 return NT_STATUS_UNSUCCESSFUL
;
4401 r
= get_user_tokens_from_file(f
, &num_tokens
, &tokens
);
4407 DEBUG(0, ("Could not read users from file\n"));
4408 return NT_STATUS_UNSUCCESSFUL
;
4411 for (i
=0; i
<num_tokens
; i
++)
4412 collect_alias_memberships(&tokens
[i
].token
);
4414 share_list
.num_shares
= 0;
4415 share_list
.shares
= NULL
;
4417 ret
= cli_RNetShareEnum(cli
, collect_share
, &share_list
);
4420 DEBUG(0, ("Error returning browse list: %s\n",
4425 for (i
= 0; i
< share_list
.num_shares
; i
++) {
4426 char *netname
= share_list
.shares
[i
];
4428 if (netname
[strlen(netname
)-1] == '$')
4431 d_printf("%s\n", netname
);
4433 show_userlist(pipe_hnd
, mem_ctx
, netname
,
4434 num_tokens
, tokens
);
4437 for (i
=0; i
<num_tokens
; i
++) {
4438 free_user_token(&tokens
[i
].token
);
4441 SAFE_FREE(share_list
.shares
);
4443 return NT_STATUS_OK
;
4446 static int rpc_share_allowedusers(struct net_context
*c
, int argc
,
4451 if (c
->display_usage
) {
4453 "net rpc share allowedusers\n"
4454 " List allowed users\n");
4458 result
= run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
, 0,
4459 rpc_aliaslist_internals
,
4464 result
= run_rpc_command(c
, NULL
, &ndr_table_lsarpc
.syntax_id
, 0,
4470 return run_rpc_command(c
, NULL
, &ndr_table_srvsvc
.syntax_id
, 0,
4471 rpc_share_allowedusers_internals
,
4475 int net_usersidlist(struct net_context
*c
, int argc
, const char **argv
)
4478 struct user_token
*tokens
= NULL
;
4482 net_usersidlist_usage(c
, argc
, argv
);
4486 if (!get_user_tokens(c
, &num_tokens
, &tokens
)) {
4487 DEBUG(0, ("Could not get the user/sid list\n"));
4491 for (i
=0; i
<num_tokens
; i
++) {
4492 dump_user_token(&tokens
[i
]);
4493 free_user_token(&tokens
[i
].token
);
4500 int net_usersidlist_usage(struct net_context
*c
, int argc
, const char **argv
)
4502 d_printf("net usersidlist\n"
4503 "\tprints out a list of all users the running winbind knows\n"
4504 "\tabout, together with all their SIDs. This is used as\n"
4505 "\tinput to the 'net rpc share allowedusers' command.\n\n");
4507 net_common_flags_usage(c
, argc
, argv
);
4512 * 'net rpc share' entrypoint.
4513 * @param argc Standard main() style argc.
4514 * @param argv Standard main() style argv. Initial components are already
4518 int net_rpc_share(struct net_context
*c
, int argc
, const char **argv
)
4520 NET_API_STATUS status
;
4522 struct functable func
[] = {
4528 "net rpc share add\n"
4536 "net rpc share delete\n"
4541 rpc_share_allowedusers
,
4543 "Modify allowed users",
4544 "net rpc share allowedusers\n"
4545 " Modify allowed users"
4551 "Migrate share to local server",
4552 "net rpc share migrate\n"
4553 " Migrate share to local server"
4560 "net rpc share list\n"
4563 {NULL
, NULL
, 0, NULL
, NULL
}
4566 status
= libnetapi_init(&c
->netapi_ctx
);
4570 libnetapi_set_username(c
->netapi_ctx
, c
->opt_user_name
);
4571 libnetapi_set_password(c
->netapi_ctx
, c
->opt_password
);
4572 if (c
->opt_kerberos
) {
4573 libnetapi_set_use_kerberos(c
->netapi_ctx
);
4577 if (c
->display_usage
) {
4581 " Alias for net rpc share list\n");
4582 net_display_usage_from_functable(func
);
4586 return rpc_share_list(c
, argc
, argv
);
4589 return net_run_function(c
, argc
, argv
, "net rpc share", func
);
4592 static NTSTATUS
rpc_sh_share_list(struct net_context
*c
,
4593 TALLOC_CTX
*mem_ctx
,
4594 struct rpc_sh_ctx
*ctx
,
4595 struct rpc_pipe_client
*pipe_hnd
,
4596 int argc
, const char **argv
)
4599 return werror_to_ntstatus(W_ERROR(rpc_share_list(c
, argc
, argv
)));
4602 static NTSTATUS
rpc_sh_share_add(struct net_context
*c
,
4603 TALLOC_CTX
*mem_ctx
,
4604 struct rpc_sh_ctx
*ctx
,
4605 struct rpc_pipe_client
*pipe_hnd
,
4606 int argc
, const char **argv
)
4608 NET_API_STATUS status
;
4609 uint32_t parm_err
= 0;
4610 struct SHARE_INFO_2 i2
;
4612 if ((argc
< 2) || (argc
> 3)) {
4613 d_fprintf(stderr
, "usage: %s <share> <path> [comment]\n",
4615 return NT_STATUS_INVALID_PARAMETER
;
4618 i2
.shi2_netname
= argv
[0];
4619 i2
.shi2_type
= STYPE_DISKTREE
;
4620 i2
.shi2_remark
= (argc
== 3) ? argv
[2] : "";
4621 i2
.shi2_permissions
= 0;
4622 i2
.shi2_max_uses
= 0;
4623 i2
.shi2_current_uses
= 0;
4624 i2
.shi2_path
= argv
[1];
4625 i2
.shi2_passwd
= NULL
;
4627 status
= NetShareAdd(pipe_hnd
->desthost
,
4632 return werror_to_ntstatus(W_ERROR(status
));
4635 static NTSTATUS
rpc_sh_share_delete(struct net_context
*c
,
4636 TALLOC_CTX
*mem_ctx
,
4637 struct rpc_sh_ctx
*ctx
,
4638 struct rpc_pipe_client
*pipe_hnd
,
4639 int argc
, const char **argv
)
4642 d_fprintf(stderr
, "usage: %s <share>\n", ctx
->whoami
);
4643 return NT_STATUS_INVALID_PARAMETER
;
4646 return werror_to_ntstatus(W_ERROR(NetShareDel(pipe_hnd
->desthost
, argv
[0], 0)));
4649 static NTSTATUS
rpc_sh_share_info(struct net_context
*c
,
4650 TALLOC_CTX
*mem_ctx
,
4651 struct rpc_sh_ctx
*ctx
,
4652 struct rpc_pipe_client
*pipe_hnd
,
4653 int argc
, const char **argv
)
4655 union srvsvc_NetShareInfo info
;
4660 d_fprintf(stderr
, "usage: %s <share>\n", ctx
->whoami
);
4661 return NT_STATUS_INVALID_PARAMETER
;
4664 status
= rpccli_srvsvc_NetShareGetInfo(pipe_hnd
, mem_ctx
,
4670 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
)) {
4674 d_printf("Name: %s\n", info
.info2
->name
);
4675 d_printf("Comment: %s\n", info
.info2
->comment
);
4676 d_printf("Path: %s\n", info
.info2
->path
);
4677 d_printf("Password: %s\n", info
.info2
->password
);
4680 return werror_to_ntstatus(result
);
4683 struct rpc_sh_cmd
*net_rpc_share_cmds(struct net_context
*c
, TALLOC_CTX
*mem_ctx
,
4684 struct rpc_sh_ctx
*ctx
)
4686 static struct rpc_sh_cmd cmds
[] = {
4688 { "list", NULL
, &ndr_table_srvsvc
.syntax_id
, rpc_sh_share_list
,
4689 "List available shares" },
4691 { "add", NULL
, &ndr_table_srvsvc
.syntax_id
, rpc_sh_share_add
,
4694 { "delete", NULL
, &ndr_table_srvsvc
.syntax_id
, rpc_sh_share_delete
,
4697 { "info", NULL
, &ndr_table_srvsvc
.syntax_id
, rpc_sh_share_info
,
4698 "Get information about a share" },
4700 { NULL
, NULL
, 0, NULL
, NULL
}
4706 /****************************************************************************/
4708 static int rpc_file_usage(struct net_context
*c
, int argc
, const char **argv
)
4710 return net_file_usage(c
, argc
, argv
);
4714 * Close a file on a remote RPC server.
4716 * @param argc Standard main() style argc.
4717 * @param argv Standard main() style argv. Initial components are already
4720 * @return A shell status integer (0 for success).
4722 static int rpc_file_close(struct net_context
*c
, int argc
, const char **argv
)
4724 if (argc
< 1 || c
->display_usage
) {
4725 return rpc_file_usage(c
, argc
, argv
);
4728 return NetFileClose(c
->opt_host
, atoi(argv
[0]));
4732 * Formatted print of open file info
4734 * @param r struct FILE_INFO_3 contents
4737 static void display_file_info_3(struct FILE_INFO_3
*r
)
4739 d_printf("%-7.1d %-20.20s 0x%-4.2x %-6.1d %s\n",
4740 r
->fi3_id
, r
->fi3_username
, r
->fi3_permissions
,
4741 r
->fi3_num_locks
, r
->fi3_pathname
);
4745 * List files for a user on a remote RPC server.
4747 * @param argc Standard main() style argc.
4748 * @param argv Standard main() style argv. Initial components are already
4751 * @return A shell status integer (0 for success)..
4754 static int rpc_file_user(struct net_context
*c
, int argc
, const char **argv
)
4756 NET_API_STATUS status
;
4757 uint32 preferred_len
= 0xffffffff, i
;
4758 const char *username
=NULL
;
4759 uint32_t total_entries
= 0;
4760 uint32_t entries_read
= 0;
4761 uint32_t resume_handle
= 0;
4762 struct FILE_INFO_3
*i3
= NULL
;
4764 if (c
->display_usage
) {
4765 return rpc_file_usage(c
, argc
, argv
);
4768 /* if argc > 0, must be user command */
4770 username
= smb_xstrdup(argv
[0]);
4773 status
= NetFileEnum(c
->opt_host
,
4777 (uint8_t **)(void *)&i3
,
4787 /* Display results */
4790 "\nEnumerating open files on remote server:\n\n"
4791 "\nFileId Opened by Perms Locks Path"
4792 "\n------ --------- ----- ----- ---- \n");
4793 for (i
= 0; i
< entries_read
; i
++) {
4794 display_file_info_3(&i3
[i
]);
4801 * 'net rpc file' entrypoint.
4802 * @param argc Standard main() style argc.
4803 * @param argv Standard main() style argv. Initial components are already
4807 int net_rpc_file(struct net_context
*c
, int argc
, const char **argv
)
4809 NET_API_STATUS status
;
4811 struct functable func
[] = {
4816 "Close opened file",
4817 "net rpc file close\n"
4818 " Close opened file"
4824 "List files opened by user",
4825 "net rpc file user\n"
4826 " List files opened by user"
4833 "Display information about opened file",
4834 "net rpc file info\n"
4835 " Display information about opened file"
4838 {NULL
, NULL
, 0, NULL
, NULL
}
4841 status
= libnetapi_init(&c
->netapi_ctx
);
4845 libnetapi_set_username(c
->netapi_ctx
, c
->opt_user_name
);
4846 libnetapi_set_password(c
->netapi_ctx
, c
->opt_password
);
4847 if (c
->opt_kerberos
) {
4848 libnetapi_set_use_kerberos(c
->netapi_ctx
);
4852 if (c
->display_usage
) {
4853 d_printf("Usage:\n");
4854 d_printf("net rpc file\n"
4855 " List opened files\n");
4856 net_display_usage_from_functable(func
);
4860 return rpc_file_user(c
, argc
, argv
);
4863 return net_run_function(c
, argc
, argv
, "net rpc file", func
);
4867 * ABORT the shutdown of a remote RPC Server, over initshutdown pipe.
4869 * All parameters are provided by the run_rpc_command function, except for
4870 * argc, argv which are passed through.
4872 * @param c A net_context structure.
4873 * @param domain_sid The domain sid acquired from the remote server.
4874 * @param cli A cli_state connected to the server.
4875 * @param mem_ctx Talloc context, destroyed on completion of the function.
4876 * @param argc Standard main() style argc.
4877 * @param argv Standard main() style argv. Initial components are already
4880 * @return Normal NTSTATUS return.
4883 static NTSTATUS
rpc_shutdown_abort_internals(struct net_context
*c
,
4884 const DOM_SID
*domain_sid
,
4885 const char *domain_name
,
4886 struct cli_state
*cli
,
4887 struct rpc_pipe_client
*pipe_hnd
,
4888 TALLOC_CTX
*mem_ctx
,
4892 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
4894 result
= rpccli_initshutdown_Abort(pipe_hnd
, mem_ctx
, NULL
, NULL
);
4896 if (NT_STATUS_IS_OK(result
)) {
4897 d_printf("\nShutdown successfully aborted\n");
4898 DEBUG(5,("cmd_shutdown_abort: query succeeded\n"));
4900 DEBUG(5,("cmd_shutdown_abort: query failed\n"));
4906 * ABORT the shutdown of a remote RPC Server, over winreg pipe.
4908 * All parameters are provided by the run_rpc_command function, except for
4909 * argc, argv which are passed through.
4911 * @param c A net_context structure.
4912 * @param domain_sid The domain sid acquired from the remote server.
4913 * @param cli A cli_state connected to the server.
4914 * @param mem_ctx Talloc context, destroyed on completion of the function.
4915 * @param argc Standard main() style argc.
4916 * @param argv Standard main() style argv. Initial components are already
4919 * @return Normal NTSTATUS return.
4922 static NTSTATUS
rpc_reg_shutdown_abort_internals(struct net_context
*c
,
4923 const DOM_SID
*domain_sid
,
4924 const char *domain_name
,
4925 struct cli_state
*cli
,
4926 struct rpc_pipe_client
*pipe_hnd
,
4927 TALLOC_CTX
*mem_ctx
,
4931 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
4933 result
= rpccli_winreg_AbortSystemShutdown(pipe_hnd
, mem_ctx
, NULL
, NULL
);
4935 if (NT_STATUS_IS_OK(result
)) {
4936 d_printf("\nShutdown successfully aborted\n");
4937 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
4939 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
4945 * ABORT the shutdown of a remote RPC server.
4947 * @param argc Standard main() style argc.
4948 * @param argv Standard main() style argv. Initial components are already
4951 * @return A shell status integer (0 for success).
4954 static int rpc_shutdown_abort(struct net_context
*c
, int argc
,
4959 if (c
->display_usage
) {
4961 "net rpc abortshutdown\n"
4962 " Abort a scheduled shutdown\n");
4966 rc
= run_rpc_command(c
, NULL
, &ndr_table_initshutdown
.syntax_id
, 0,
4967 rpc_shutdown_abort_internals
, argc
, argv
);
4972 DEBUG(1, ("initshutdown pipe didn't work, trying winreg pipe\n"));
4974 return run_rpc_command(c
, NULL
, &ndr_table_winreg
.syntax_id
, 0,
4975 rpc_reg_shutdown_abort_internals
,
4980 * Shut down a remote RPC Server via initshutdown pipe.
4982 * All parameters are provided by the run_rpc_command function, except for
4983 * argc, argv which are passed through.
4985 * @param c A net_context structure.
4986 * @param domain_sid The domain sid acquired from the remote server.
4987 * @param cli A cli_state connected to the server.
4988 * @param mem_ctx Talloc context, destroyed on completion of the function.
4989 * @param argc Standard main() style argc.
4990 * @param argv Standard main() style argv. Initial components are already
4993 * @return Normal NTSTATUS return.
4996 NTSTATUS
rpc_init_shutdown_internals(struct net_context
*c
,
4997 const DOM_SID
*domain_sid
,
4998 const char *domain_name
,
4999 struct cli_state
*cli
,
5000 struct rpc_pipe_client
*pipe_hnd
,
5001 TALLOC_CTX
*mem_ctx
,
5005 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
5006 const char *msg
= "This machine will be shutdown shortly";
5007 uint32 timeout
= 20;
5008 struct initshutdown_String msg_string
;
5009 struct initshutdown_String_sub s
;
5011 if (c
->opt_comment
) {
5012 msg
= c
->opt_comment
;
5014 if (c
->opt_timeout
) {
5015 timeout
= c
->opt_timeout
;
5019 msg_string
.name
= &s
;
5021 /* create an entry */
5022 result
= rpccli_initshutdown_Init(pipe_hnd
, mem_ctx
, NULL
,
5023 &msg_string
, timeout
, c
->opt_force
, c
->opt_reboot
,
5026 if (NT_STATUS_IS_OK(result
)) {
5027 d_printf("\nShutdown of remote machine succeeded\n");
5028 DEBUG(5,("Shutdown of remote machine succeeded\n"));
5030 DEBUG(1,("Shutdown of remote machine failed!\n"));
5036 * Shut down a remote RPC Server via winreg pipe.
5038 * All parameters are provided by the run_rpc_command function, except for
5039 * argc, argv which are passed through.
5041 * @param c A net_context structure.
5042 * @param domain_sid The domain sid acquired from the remote server.
5043 * @param cli A cli_state connected to the server.
5044 * @param mem_ctx Talloc context, destroyed on completion of the function.
5045 * @param argc Standard main() style argc.
5046 * @param argv Standard main() style argv. Initial components are already
5049 * @return Normal NTSTATUS return.
5052 NTSTATUS
rpc_reg_shutdown_internals(struct net_context
*c
,
5053 const DOM_SID
*domain_sid
,
5054 const char *domain_name
,
5055 struct cli_state
*cli
,
5056 struct rpc_pipe_client
*pipe_hnd
,
5057 TALLOC_CTX
*mem_ctx
,
5061 const char *msg
= "This machine will be shutdown shortly";
5062 uint32 timeout
= 20;
5063 struct initshutdown_String msg_string
;
5064 struct initshutdown_String_sub s
;
5068 if (c
->opt_comment
) {
5069 msg
= c
->opt_comment
;
5072 msg_string
.name
= &s
;
5074 if (c
->opt_timeout
) {
5075 timeout
= c
->opt_timeout
;
5078 /* create an entry */
5079 result
= rpccli_winreg_InitiateSystemShutdown(pipe_hnd
, mem_ctx
, NULL
,
5080 &msg_string
, timeout
, c
->opt_force
, c
->opt_reboot
,
5083 if (NT_STATUS_IS_OK(result
)) {
5084 d_printf("\nShutdown of remote machine succeeded\n");
5086 d_fprintf(stderr
, "\nShutdown of remote machine failed\n");
5087 if ( W_ERROR_EQUAL(werr
, WERR_MACHINE_LOCKED
) )
5088 d_fprintf(stderr
, "\nMachine locked, use -f switch to force\n");
5090 d_fprintf(stderr
, "\nresult was: %s\n", dos_errstr(werr
));
5097 * Shut down a remote RPC server.
5099 * @param argc Standard main() style argc.
5100 * @param argv Standard main() style argv. Initial components are already
5103 * @return A shell status integer (0 for success).
5106 static int rpc_shutdown(struct net_context
*c
, int argc
, const char **argv
)
5110 if (c
->display_usage
) {
5112 "net rpc shutdown\n"
5113 " Shut down a remote RPC server\n");
5117 rc
= run_rpc_command(c
, NULL
, &ndr_table_initshutdown
.syntax_id
, 0,
5118 rpc_init_shutdown_internals
, argc
, argv
);
5121 DEBUG(1, ("initshutdown pipe failed, trying winreg pipe\n"));
5122 rc
= run_rpc_command(c
, NULL
, &ndr_table_winreg
.syntax_id
, 0,
5123 rpc_reg_shutdown_internals
, argc
, argv
);
5129 /***************************************************************************
5130 NT Domain trusts code (i.e. 'net rpc trustdom' functionality)
5131 ***************************************************************************/
5134 * Add interdomain trust account to the RPC server.
5135 * All parameters (except for argc and argv) are passed by run_rpc_command
5138 * @param c A net_context structure.
5139 * @param domain_sid The domain sid acquired from the server.
5140 * @param cli A cli_state connected to the server.
5141 * @param mem_ctx Talloc context, destroyed on completion of the function.
5142 * @param argc Standard main() style argc.
5143 * @param argv Standard main() style argv. Initial components are already
5146 * @return normal NTSTATUS return code.
5149 static NTSTATUS
rpc_trustdom_add_internals(struct net_context
*c
,
5150 const DOM_SID
*domain_sid
,
5151 const char *domain_name
,
5152 struct cli_state
*cli
,
5153 struct rpc_pipe_client
*pipe_hnd
,
5154 TALLOC_CTX
*mem_ctx
,
5158 POLICY_HND connect_pol
, domain_pol
, user_pol
;
5159 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
5161 struct lsa_String lsa_acct_name
;
5163 uint32 acct_flags
=0;
5165 uint32_t access_granted
= 0;
5166 union samr_UserInfo info
;
5167 unsigned int orig_timeout
;
5170 d_printf("Usage: net rpc trustdom add <domain_name> "
5171 "<trust password>\n");
5172 return NT_STATUS_INVALID_PARAMETER
;
5176 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5179 if (asprintf(&acct_name
, "%s$", argv
[0]) < 0) {
5180 return NT_STATUS_NO_MEMORY
;
5183 strupper_m(acct_name
);
5185 init_lsa_String(&lsa_acct_name
, acct_name
);
5187 /* Get samr policy handle */
5188 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
5190 MAXIMUM_ALLOWED_ACCESS
,
5192 if (!NT_STATUS_IS_OK(result
)) {
5196 /* Get domain policy handle */
5197 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
5199 MAXIMUM_ALLOWED_ACCESS
,
5200 CONST_DISCARD(struct dom_sid2
*, domain_sid
),
5202 if (!NT_STATUS_IS_OK(result
)) {
5206 /* This call can take a long time - allow the server to time out.
5207 * 35 seconds should do it. */
5209 orig_timeout
= rpccli_set_timeout(pipe_hnd
, 35000);
5211 /* Create trusting domain's account */
5212 acb_info
= ACB_NORMAL
;
5213 acct_flags
= SEC_GENERIC_READ
| SEC_GENERIC_WRITE
| SEC_GENERIC_EXECUTE
|
5214 SEC_STD_WRITE_DAC
| SEC_STD_DELETE
|
5215 SAMR_USER_ACCESS_SET_PASSWORD
|
5216 SAMR_USER_ACCESS_GET_ATTRIBUTES
|
5217 SAMR_USER_ACCESS_SET_ATTRIBUTES
;
5219 result
= rpccli_samr_CreateUser2(pipe_hnd
, mem_ctx
,
5228 /* And restore our original timeout. */
5229 rpccli_set_timeout(pipe_hnd
, orig_timeout
);
5231 if (!NT_STATUS_IS_OK(result
)) {
5232 d_printf("net rpc trustdom add: create user %s failed %s\n",
5233 acct_name
, nt_errstr(result
));
5239 struct samr_LogonHours hours
;
5240 struct lsa_BinaryString parameters
;
5241 const int units_per_week
= 168;
5242 struct samr_CryptPassword crypt_pwd
;
5244 ZERO_STRUCT(notime
);
5246 ZERO_STRUCT(parameters
);
5248 hours
.bits
= talloc_array(mem_ctx
, uint8_t, units_per_week
);
5250 result
= NT_STATUS_NO_MEMORY
;
5253 hours
.units_per_week
= units_per_week
;
5254 memset(hours
.bits
, 0xFF, units_per_week
);
5256 init_samr_CryptPassword(argv
[1],
5257 &cli
->user_session_key
,
5260 init_samr_user_info23(&info
.info23
,
5261 notime
, notime
, notime
,
5262 notime
, notime
, notime
,
5263 NULL
, NULL
, NULL
, NULL
, NULL
,
5264 NULL
, NULL
, NULL
, NULL
, ¶meters
,
5266 SAMR_FIELD_ACCT_FLAGS
| SAMR_FIELD_NT_PASSWORD_PRESENT
,
5268 0, 0, 0, 0, 0, 0, 0,
5271 result
= rpccli_samr_SetUserInfo2(pipe_hnd
, mem_ctx
,
5276 if (!NT_STATUS_IS_OK(result
)) {
5277 DEBUG(0,("Could not set trust account password: %s\n",
5278 nt_errstr(result
)));
5284 SAFE_FREE(acct_name
);
5289 * Create interdomain trust account for a remote domain.
5291 * @param argc Standard argc.
5292 * @param argv Standard argv without initial components.
5294 * @return Integer status (0 means success).
5297 static int rpc_trustdom_add(struct net_context
*c
, int argc
, const char **argv
)
5299 if (argc
> 0 && !c
->display_usage
) {
5300 return run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
, 0,
5301 rpc_trustdom_add_internals
, argc
, argv
);
5304 "net rpc trustdom add <domain_name> <trust password>\n");
5311 * Remove interdomain trust account from the RPC server.
5312 * All parameters (except for argc and argv) are passed by run_rpc_command
5315 * @param c A net_context structure.
5316 * @param domain_sid The domain sid acquired from the server.
5317 * @param cli A cli_state connected to the server.
5318 * @param mem_ctx Talloc context, destroyed on completion of the function.
5319 * @param argc Standard main() style argc.
5320 * @param argv Standard main() style argv. Initial components are already
5323 * @return normal NTSTATUS return code.
5326 static NTSTATUS
rpc_trustdom_del_internals(struct net_context
*c
,
5327 const DOM_SID
*domain_sid
,
5328 const char *domain_name
,
5329 struct cli_state
*cli
,
5330 struct rpc_pipe_client
*pipe_hnd
,
5331 TALLOC_CTX
*mem_ctx
,
5335 POLICY_HND connect_pol
, domain_pol
, user_pol
;
5336 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
5338 DOM_SID trust_acct_sid
;
5339 struct samr_Ids user_rids
, name_types
;
5340 struct lsa_String lsa_acct_name
;
5343 d_printf("Usage: net rpc trustdom del <domain_name>\n");
5344 return NT_STATUS_INVALID_PARAMETER
;
5348 * Make valid trusting domain account (ie. uppercased and with '$' appended)
5350 acct_name
= talloc_asprintf(mem_ctx
, "%s$", argv
[0]);
5352 if (acct_name
== NULL
)
5353 return NT_STATUS_NO_MEMORY
;
5355 strupper_m(acct_name
);
5357 /* Get samr policy handle */
5358 result
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
5360 MAXIMUM_ALLOWED_ACCESS
,
5362 if (!NT_STATUS_IS_OK(result
)) {
5366 /* Get domain policy handle */
5367 result
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
5369 MAXIMUM_ALLOWED_ACCESS
,
5370 CONST_DISCARD(struct dom_sid2
*, domain_sid
),
5372 if (!NT_STATUS_IS_OK(result
)) {
5376 init_lsa_String(&lsa_acct_name
, acct_name
);
5378 result
= rpccli_samr_LookupNames(pipe_hnd
, mem_ctx
,
5385 if (!NT_STATUS_IS_OK(result
)) {
5386 d_printf("net rpc trustdom del: LookupNames on user %s failed %s\n",
5387 acct_name
, nt_errstr(result
) );
5391 result
= rpccli_samr_OpenUser(pipe_hnd
, mem_ctx
,
5393 MAXIMUM_ALLOWED_ACCESS
,
5397 if (!NT_STATUS_IS_OK(result
)) {
5398 d_printf("net rpc trustdom del: OpenUser on user %s failed %s\n",
5399 acct_name
, nt_errstr(result
) );
5403 /* append the rid to the domain sid */
5404 sid_copy(&trust_acct_sid
, domain_sid
);
5405 if (!sid_append_rid(&trust_acct_sid
, user_rids
.ids
[0])) {
5409 /* remove the sid */
5411 result
= rpccli_samr_RemoveMemberFromForeignDomain(pipe_hnd
, mem_ctx
,
5414 if (!NT_STATUS_IS_OK(result
)) {
5415 d_printf("net rpc trustdom del: RemoveMemberFromForeignDomain on user %s failed %s\n",
5416 acct_name
, nt_errstr(result
) );
5422 result
= rpccli_samr_DeleteUser(pipe_hnd
, mem_ctx
,
5425 if (!NT_STATUS_IS_OK(result
)) {
5426 d_printf("net rpc trustdom del: DeleteUser on user %s failed %s\n",
5427 acct_name
, nt_errstr(result
) );
5431 if (!NT_STATUS_IS_OK(result
)) {
5432 d_printf("Could not set trust account password: %s\n",
5442 * Delete interdomain trust account for a remote domain.
5444 * @param argc Standard argc.
5445 * @param argv Standard argv without initial components.
5447 * @return Integer status (0 means success).
5450 static int rpc_trustdom_del(struct net_context
*c
, int argc
, const char **argv
)
5452 if (argc
> 0 && !c
->display_usage
) {
5453 return run_rpc_command(c
, NULL
, &ndr_table_samr
.syntax_id
, 0,
5454 rpc_trustdom_del_internals
, argc
, argv
);
5457 "net rpc trustdom del <domain>\n");
5462 static NTSTATUS
rpc_trustdom_get_pdc(struct net_context
*c
,
5463 struct cli_state
*cli
,
5464 TALLOC_CTX
*mem_ctx
,
5465 const char *domain_name
)
5467 char *dc_name
= NULL
;
5468 const char *buffer
= NULL
;
5469 struct rpc_pipe_client
*netr
;
5472 /* Use NetServerEnum2 */
5474 if (cli_get_pdc_name(cli
, domain_name
, &dc_name
)) {
5476 return NT_STATUS_OK
;
5479 DEBUG(1,("NetServerEnum2 error: Couldn't find primary domain controller\
5480 for domain %s\n", domain_name
));
5482 /* Try netr_GetDcName */
5484 status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_netlogon
.syntax_id
,
5486 if (!NT_STATUS_IS_OK(status
)) {
5490 status
= rpccli_netr_GetDcName(netr
, mem_ctx
,
5497 if (NT_STATUS_IS_OK(status
)) {
5501 DEBUG(1,("netr_GetDcName error: Couldn't find primary domain controller\
5502 for domain %s\n", domain_name
));
5508 * Establish trust relationship to a trusting domain.
5509 * Interdomain account must already be created on remote PDC.
5511 * @param c A net_context structure.
5512 * @param argc Standard argc.
5513 * @param argv Standard argv without initial components.
5515 * @return Integer status (0 means success).
5518 static int rpc_trustdom_establish(struct net_context
*c
, int argc
,
5521 struct cli_state
*cli
= NULL
;
5522 struct sockaddr_storage server_ss
;
5523 struct rpc_pipe_client
*pipe_hnd
= NULL
;
5524 POLICY_HND connect_hnd
;
5525 TALLOC_CTX
*mem_ctx
;
5527 DOM_SID
*domain_sid
;
5532 union lsa_PolicyInformation
*info
= NULL
;
5535 * Connect to \\server\ipc$ as 'our domain' account with password
5538 if (argc
!= 1 || c
->display_usage
) {
5540 "net rpc trustdom establish <domain_name>\n");
5544 domain_name
= smb_xstrdup(argv
[0]);
5545 strupper_m(domain_name
);
5547 /* account name used at first is our domain's name with '$' */
5548 if (asprintf(&acct_name
, "%s$", lp_workgroup()) == -1) {
5551 strupper_m(acct_name
);
5554 * opt_workgroup will be used by connection functions further,
5555 * hence it should be set to remote domain name instead of ours
5557 if (c
->opt_workgroup
) {
5558 c
->opt_workgroup
= smb_xstrdup(domain_name
);
5561 c
->opt_user_name
= acct_name
;
5563 /* find the domain controller */
5564 if (!net_find_pdc(&server_ss
, pdc_name
, domain_name
)) {
5565 DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name
));
5569 /* connect to ipc$ as username/password */
5570 nt_status
= connect_to_ipc(c
, &cli
, &server_ss
, pdc_name
);
5571 if (!NT_STATUS_EQUAL(nt_status
, NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT
)) {
5573 /* Is it trusting domain account for sure ? */
5574 DEBUG(0, ("Couldn't verify trusting domain account. Error was %s\n",
5575 nt_errstr(nt_status
)));
5579 /* store who we connected to */
5581 saf_store( domain_name
, pdc_name
);
5584 * Connect to \\server\ipc$ again (this time anonymously)
5587 nt_status
= connect_to_ipc_anonymous(c
, &cli
, &server_ss
,
5590 if (NT_STATUS_IS_ERR(nt_status
)) {
5591 DEBUG(0, ("Couldn't connect to domain %s controller. Error was %s.\n",
5592 domain_name
, nt_errstr(nt_status
)));
5596 if (!(mem_ctx
= talloc_init("establishing trust relationship to "
5597 "domain %s", domain_name
))) {
5598 DEBUG(0, ("talloc_init() failed\n"));
5603 /* Make sure we're talking to a proper server */
5605 nt_status
= rpc_trustdom_get_pdc(c
, cli
, mem_ctx
, domain_name
);
5606 if (!NT_STATUS_IS_OK(nt_status
)) {
5608 talloc_destroy(mem_ctx
);
5613 * Call LsaOpenPolicy and LsaQueryInfo
5616 nt_status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_lsarpc
.syntax_id
,
5618 if (!NT_STATUS_IS_OK(nt_status
)) {
5619 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status
) ));
5621 talloc_destroy(mem_ctx
);
5625 nt_status
= rpccli_lsa_open_policy2(pipe_hnd
, mem_ctx
, true, SEC_RIGHTS_QUERY_VALUE
,
5627 if (NT_STATUS_IS_ERR(nt_status
)) {
5628 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5629 nt_errstr(nt_status
)));
5631 talloc_destroy(mem_ctx
);
5635 /* Querying info level 5 */
5637 nt_status
= rpccli_lsa_QueryInfoPolicy(pipe_hnd
, mem_ctx
,
5639 LSA_POLICY_INFO_ACCOUNT_DOMAIN
,
5641 if (NT_STATUS_IS_ERR(nt_status
)) {
5642 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5643 nt_errstr(nt_status
)));
5645 talloc_destroy(mem_ctx
);
5649 domain_sid
= info
->account_domain
.sid
;
5651 /* There should be actually query info level 3 (following nt serv behaviour),
5652 but I still don't know if it's _really_ necessary */
5655 * Store the password in secrets db
5658 if (!pdb_set_trusteddom_pw(domain_name
, c
->opt_password
, domain_sid
)) {
5659 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5661 talloc_destroy(mem_ctx
);
5666 * Close the pipes and clean up
5669 nt_status
= rpccli_lsa_Close(pipe_hnd
, mem_ctx
, &connect_hnd
);
5670 if (NT_STATUS_IS_ERR(nt_status
)) {
5671 DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
5672 nt_errstr(nt_status
)));
5674 talloc_destroy(mem_ctx
);
5680 talloc_destroy(mem_ctx
);
5682 d_printf("Trust to domain %s established\n", domain_name
);
5687 * Revoke trust relationship to the remote domain.
5689 * @param c A net_context structure.
5690 * @param argc Standard argc.
5691 * @param argv Standard argv without initial components.
5693 * @return Integer status (0 means success).
5696 static int rpc_trustdom_revoke(struct net_context
*c
, int argc
,
5702 if (argc
< 1 || c
->display_usage
) {
5704 "net rpc trustdom revoke <domain_name>\n"
5705 " Revoke trust relationship\n"
5706 " domain_name\tName of domain to revoke trust\n");
5710 /* generate upper cased domain name */
5711 domain_name
= smb_xstrdup(argv
[0]);
5712 strupper_m(domain_name
);
5714 /* delete password of the trust */
5715 if (!pdb_del_trusteddom_pw(domain_name
)) {
5716 DEBUG(0, ("Failed to revoke relationship to the trusted domain %s\n",
5723 SAFE_FREE(domain_name
);
5727 static NTSTATUS
rpc_query_domain_sid(struct net_context
*c
,
5728 const DOM_SID
*domain_sid
,
5729 const char *domain_name
,
5730 struct cli_state
*cli
,
5731 struct rpc_pipe_client
*pipe_hnd
,
5732 TALLOC_CTX
*mem_ctx
,
5737 sid_to_fstring(str_sid
, domain_sid
);
5738 d_printf("%s\n", str_sid
);
5739 return NT_STATUS_OK
;
5742 static void print_trusted_domain(DOM_SID
*dom_sid
, const char *trusted_dom_name
)
5744 fstring ascii_sid
, padding
;
5745 int pad_len
, col_len
= 20;
5747 /* convert sid into ascii string */
5748 sid_to_fstring(ascii_sid
, dom_sid
);
5750 /* calculate padding space for d_printf to look nicer */
5751 pad_len
= col_len
- strlen(trusted_dom_name
);
5752 padding
[pad_len
] = 0;
5753 do padding
[--pad_len
] = ' '; while (pad_len
);
5755 d_printf("%s%s%s\n", trusted_dom_name
, padding
, ascii_sid
);
5758 static NTSTATUS
vampire_trusted_domain(struct rpc_pipe_client
*pipe_hnd
,
5759 TALLOC_CTX
*mem_ctx
,
5762 const char *trusted_dom_name
)
5765 union lsa_TrustedDomainInfo
*info
= NULL
;
5766 char *cleartextpwd
= NULL
;
5767 uint8_t nt_hash
[16];
5768 DATA_BLOB data
= data_blob_null
;
5770 nt_status
= rpccli_lsa_QueryTrustedDomainInfoBySid(pipe_hnd
, mem_ctx
,
5773 LSA_TRUSTED_DOMAIN_INFO_PASSWORD
,
5775 if (NT_STATUS_IS_ERR(nt_status
)) {
5776 DEBUG(0,("Could not query trusted domain info. Error was %s\n",
5777 nt_errstr(nt_status
)));
5781 data
= data_blob(info
->password
.password
->data
,
5782 info
->password
.password
->length
);
5784 if (!rpccli_get_pwd_hash(pipe_hnd
, nt_hash
)) {
5785 DEBUG(0, ("Could not retrieve password hash\n"));
5789 cleartextpwd
= decrypt_trustdom_secret(nt_hash
, &data
);
5791 if (cleartextpwd
== NULL
) {
5792 DEBUG(0,("retrieved NULL password\n"));
5793 nt_status
= NT_STATUS_UNSUCCESSFUL
;
5797 if (!pdb_set_trusteddom_pw(trusted_dom_name
, cleartextpwd
, &dom_sid
)) {
5798 DEBUG(0, ("Storing password for trusted domain failed.\n"));
5799 nt_status
= NT_STATUS_UNSUCCESSFUL
;
5803 #ifdef DEBUG_PASSWORD
5804 DEBUG(100,("successfully vampired trusted domain [%s], sid: [%s], "
5805 "password: [%s]\n", trusted_dom_name
,
5806 sid_string_dbg(&dom_sid
), cleartextpwd
));
5810 SAFE_FREE(cleartextpwd
);
5811 data_blob_free(&data
);
5816 static int rpc_trustdom_vampire(struct net_context
*c
, int argc
,
5819 /* common variables */
5820 TALLOC_CTX
* mem_ctx
;
5821 struct cli_state
*cli
= NULL
;
5822 struct rpc_pipe_client
*pipe_hnd
= NULL
;
5824 const char *domain_name
= NULL
;
5825 DOM_SID
*queried_dom_sid
;
5826 POLICY_HND connect_hnd
;
5827 union lsa_PolicyInformation
*info
= NULL
;
5829 /* trusted domains listing variables */
5830 unsigned int enum_ctx
= 0;
5832 struct lsa_DomainList dom_list
;
5835 if (c
->display_usage
) {
5837 "net rpc trustdom vampire\n"
5838 " Vampire trust relationship from remote server\n");
5843 * Listing trusted domains (stored in secrets.tdb, if local)
5846 mem_ctx
= talloc_init("trust relationships vampire");
5849 * set domain and pdc name to local samba server (default)
5850 * or to remote one given in command line
5853 if (StrCaseCmp(c
->opt_workgroup
, lp_workgroup())) {
5854 domain_name
= c
->opt_workgroup
;
5855 c
->opt_target_workgroup
= c
->opt_workgroup
;
5857 fstrcpy(pdc_name
, global_myname());
5858 domain_name
= talloc_strdup(mem_ctx
, lp_workgroup());
5859 c
->opt_target_workgroup
= domain_name
;
5862 /* open \PIPE\lsarpc and open policy handle */
5863 nt_status
= net_make_ipc_connection(c
, NET_FLAGS_PDC
, &cli
);
5864 if (!NT_STATUS_IS_OK(nt_status
)) {
5865 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
5866 nt_errstr(nt_status
)));
5867 talloc_destroy(mem_ctx
);
5871 nt_status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_lsarpc
.syntax_id
,
5873 if (!NT_STATUS_IS_OK(nt_status
)) {
5874 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
5875 nt_errstr(nt_status
) ));
5877 talloc_destroy(mem_ctx
);
5881 nt_status
= rpccli_lsa_open_policy2(pipe_hnd
, mem_ctx
, false, SEC_RIGHTS_QUERY_VALUE
,
5883 if (NT_STATUS_IS_ERR(nt_status
)) {
5884 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
5885 nt_errstr(nt_status
)));
5887 talloc_destroy(mem_ctx
);
5891 /* query info level 5 to obtain sid of a domain being queried */
5892 nt_status
= rpccli_lsa_QueryInfoPolicy(pipe_hnd
, mem_ctx
,
5894 LSA_POLICY_INFO_ACCOUNT_DOMAIN
,
5897 if (NT_STATUS_IS_ERR(nt_status
)) {
5898 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
5899 nt_errstr(nt_status
)));
5901 talloc_destroy(mem_ctx
);
5905 queried_dom_sid
= info
->account_domain
.sid
;
5908 * Keep calling LsaEnumTrustdom over opened pipe until
5909 * the end of enumeration is reached
5912 d_printf("Vampire trusted domains:\n\n");
5915 nt_status
= rpccli_lsa_EnumTrustDom(pipe_hnd
, mem_ctx
,
5920 if (NT_STATUS_IS_ERR(nt_status
)) {
5921 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
5922 nt_errstr(nt_status
)));
5924 talloc_destroy(mem_ctx
);
5928 for (i
= 0; i
< dom_list
.count
; i
++) {
5930 print_trusted_domain(dom_list
.domains
[i
].sid
,
5931 dom_list
.domains
[i
].name
.string
);
5933 nt_status
= vampire_trusted_domain(pipe_hnd
, mem_ctx
, &connect_hnd
,
5934 *dom_list
.domains
[i
].sid
,
5935 dom_list
.domains
[i
].name
.string
);
5936 if (!NT_STATUS_IS_OK(nt_status
)) {
5938 talloc_destroy(mem_ctx
);
5944 * in case of no trusted domains say something rather
5945 * than just display blank line
5947 if (!dom_list
.count
) d_printf("none\n");
5949 } while (NT_STATUS_EQUAL(nt_status
, STATUS_MORE_ENTRIES
));
5951 /* close this connection before doing next one */
5952 nt_status
= rpccli_lsa_Close(pipe_hnd
, mem_ctx
, &connect_hnd
);
5953 if (NT_STATUS_IS_ERR(nt_status
)) {
5954 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
5955 nt_errstr(nt_status
)));
5957 talloc_destroy(mem_ctx
);
5961 /* close lsarpc pipe and connection to IPC$ */
5964 talloc_destroy(mem_ctx
);
5968 static int rpc_trustdom_list(struct net_context
*c
, int argc
, const char **argv
)
5970 /* common variables */
5971 TALLOC_CTX
* mem_ctx
;
5972 struct cli_state
*cli
= NULL
, *remote_cli
= NULL
;
5973 struct rpc_pipe_client
*pipe_hnd
= NULL
;
5975 const char *domain_name
= NULL
;
5976 DOM_SID
*queried_dom_sid
;
5978 int ascii_dom_name_len
;
5979 POLICY_HND connect_hnd
;
5980 union lsa_PolicyInformation
*info
= NULL
;
5982 /* trusted domains listing variables */
5983 unsigned int num_domains
, enum_ctx
= 0;
5984 int i
, pad_len
, col_len
= 20;
5985 struct lsa_DomainList dom_list
;
5989 /* trusting domains listing variables */
5990 POLICY_HND domain_hnd
;
5991 struct samr_SamArray
*trusts
= NULL
;
5993 if (c
->display_usage
) {
5995 "net rpc trustdom list\n"
5996 " List trust relationships\n");
6001 * Listing trusted domains (stored in secrets.tdb, if local)
6004 mem_ctx
= talloc_init("trust relationships listing");
6007 * set domain and pdc name to local samba server (default)
6008 * or to remote one given in command line
6011 if (StrCaseCmp(c
->opt_workgroup
, lp_workgroup())) {
6012 domain_name
= c
->opt_workgroup
;
6013 c
->opt_target_workgroup
= c
->opt_workgroup
;
6015 fstrcpy(pdc_name
, global_myname());
6016 domain_name
= talloc_strdup(mem_ctx
, lp_workgroup());
6017 c
->opt_target_workgroup
= domain_name
;
6020 /* open \PIPE\lsarpc and open policy handle */
6021 nt_status
= net_make_ipc_connection(c
, NET_FLAGS_PDC
, &cli
);
6022 if (!NT_STATUS_IS_OK(nt_status
)) {
6023 DEBUG(0, ("Couldn't connect to domain controller: %s\n",
6024 nt_errstr(nt_status
)));
6025 talloc_destroy(mem_ctx
);
6029 nt_status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_lsarpc
.syntax_id
,
6031 if (!NT_STATUS_IS_OK(nt_status
)) {
6032 DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
6033 nt_errstr(nt_status
) ));
6035 talloc_destroy(mem_ctx
);
6039 nt_status
= rpccli_lsa_open_policy2(pipe_hnd
, mem_ctx
, false, SEC_RIGHTS_QUERY_VALUE
,
6041 if (NT_STATUS_IS_ERR(nt_status
)) {
6042 DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
6043 nt_errstr(nt_status
)));
6045 talloc_destroy(mem_ctx
);
6049 /* query info level 5 to obtain sid of a domain being queried */
6050 nt_status
= rpccli_lsa_QueryInfoPolicy(pipe_hnd
, mem_ctx
,
6052 LSA_POLICY_INFO_ACCOUNT_DOMAIN
,
6055 if (NT_STATUS_IS_ERR(nt_status
)) {
6056 DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
6057 nt_errstr(nt_status
)));
6059 talloc_destroy(mem_ctx
);
6063 queried_dom_sid
= info
->account_domain
.sid
;
6066 * Keep calling LsaEnumTrustdom over opened pipe until
6067 * the end of enumeration is reached
6070 d_printf("Trusted domains list:\n\n");
6072 found_domain
= false;
6075 nt_status
= rpccli_lsa_EnumTrustDom(pipe_hnd
, mem_ctx
,
6080 if (NT_STATUS_IS_ERR(nt_status
)) {
6081 DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
6082 nt_errstr(nt_status
)));
6084 talloc_destroy(mem_ctx
);
6088 for (i
= 0; i
< dom_list
.count
; i
++) {
6089 print_trusted_domain(dom_list
.domains
[i
].sid
,
6090 dom_list
.domains
[i
].name
.string
);
6091 found_domain
= true;
6094 } while (NT_STATUS_EQUAL(nt_status
, STATUS_MORE_ENTRIES
));
6097 * in case of no trusted domains say something rather
6098 * than just display blank line
6100 if (!found_domain
) {
6104 /* close this connection before doing next one */
6105 nt_status
= rpccli_lsa_Close(pipe_hnd
, mem_ctx
, &connect_hnd
);
6106 if (NT_STATUS_IS_ERR(nt_status
)) {
6107 DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
6108 nt_errstr(nt_status
)));
6110 talloc_destroy(mem_ctx
);
6114 TALLOC_FREE(pipe_hnd
);
6117 * Listing trusting domains (stored in passdb backend, if local)
6120 d_printf("\nTrusting domains list:\n\n");
6123 * Open \PIPE\samr and get needed policy handles
6125 nt_status
= cli_rpc_pipe_open_noauth(cli
, &ndr_table_samr
.syntax_id
,
6127 if (!NT_STATUS_IS_OK(nt_status
)) {
6128 DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status
)));
6130 talloc_destroy(mem_ctx
);
6135 nt_status
= rpccli_samr_Connect2(pipe_hnd
, mem_ctx
,
6137 SAMR_ACCESS_LOOKUP_DOMAIN
,
6139 if (!NT_STATUS_IS_OK(nt_status
)) {
6140 DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
6141 nt_errstr(nt_status
)));
6143 talloc_destroy(mem_ctx
);
6147 /* SamrOpenDomain - we have to open domain policy handle in order to be
6148 able to enumerate accounts*/
6149 nt_status
= rpccli_samr_OpenDomain(pipe_hnd
, mem_ctx
,
6151 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
6154 if (!NT_STATUS_IS_OK(nt_status
)) {
6155 DEBUG(0, ("Couldn't open domain object. Error was %s\n",
6156 nt_errstr(nt_status
)));
6158 talloc_destroy(mem_ctx
);
6163 * perform actual enumeration
6166 found_domain
= false;
6168 enum_ctx
= 0; /* reset enumeration context from last enumeration */
6171 nt_status
= rpccli_samr_EnumDomainUsers(pipe_hnd
, mem_ctx
,
6178 if (NT_STATUS_IS_ERR(nt_status
)) {
6179 DEBUG(0, ("Couldn't enumerate accounts. Error was: %s\n",
6180 nt_errstr(nt_status
)));
6182 talloc_destroy(mem_ctx
);
6186 for (i
= 0; i
< num_domains
; i
++) {
6188 char *str
= CONST_DISCARD(char *, trusts
->entries
[i
].name
.string
);
6190 found_domain
= true;
6193 * get each single domain's sid (do we _really_ need this ?):
6194 * 1) connect to domain's pdc
6195 * 2) query the pdc for domain's sid
6198 /* get rid of '$' tail */
6199 ascii_dom_name_len
= strlen(str
);
6200 if (ascii_dom_name_len
&& ascii_dom_name_len
< FSTRING_LEN
)
6201 str
[ascii_dom_name_len
- 1] = '\0';
6203 /* calculate padding space for d_printf to look nicer */
6204 pad_len
= col_len
- strlen(str
);
6205 padding
[pad_len
] = 0;
6206 do padding
[--pad_len
] = ' '; while (pad_len
);
6208 /* set opt_* variables to remote domain */
6210 c
->opt_workgroup
= talloc_strdup(mem_ctx
, str
);
6211 c
->opt_target_workgroup
= c
->opt_workgroup
;
6213 d_printf("%s%s", str
, padding
);
6215 /* connect to remote domain controller */
6216 nt_status
= net_make_ipc_connection(c
,
6217 NET_FLAGS_PDC
| NET_FLAGS_ANONYMOUS
,
6219 if (NT_STATUS_IS_OK(nt_status
)) {
6220 /* query for domain's sid */
6221 if (run_rpc_command(
6223 &ndr_table_lsarpc
.syntax_id
, 0,
6224 rpc_query_domain_sid
, argc
,
6226 d_fprintf(stderr
, "couldn't get domain's sid\n");
6228 cli_shutdown(remote_cli
);
6231 d_fprintf(stderr
, "domain controller is not "
6233 nt_errstr(nt_status
));
6237 } while (NT_STATUS_EQUAL(nt_status
, STATUS_MORE_ENTRIES
));
6239 if (!found_domain
) {
6243 /* close opened samr and domain policy handles */
6244 nt_status
= rpccli_samr_Close(pipe_hnd
, mem_ctx
, &domain_hnd
);
6245 if (!NT_STATUS_IS_OK(nt_status
)) {
6246 DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name
));
6249 nt_status
= rpccli_samr_Close(pipe_hnd
, mem_ctx
, &connect_hnd
);
6250 if (!NT_STATUS_IS_OK(nt_status
)) {
6251 DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name
));
6254 /* close samr pipe and connection to IPC$ */
6257 talloc_destroy(mem_ctx
);
6262 * Entrypoint for 'net rpc trustdom' code.
6264 * @param argc Standard argc.
6265 * @param argv Standard argv without initial components.
6267 * @return Integer status (0 means success).
6270 static int rpc_trustdom(struct net_context
*c
, int argc
, const char **argv
)
6272 struct functable func
[] = {
6277 "Add trusted domain's account",
6278 "net rpc trustdom add\n"
6279 " Add trusted domain's account"
6285 "Remove trusted domain's account",
6286 "net rpc trustdom del\n"
6287 " Remove trusted domain's account"
6291 rpc_trustdom_establish
,
6293 "Establish trust relationship",
6294 "net rpc trustdom establish\n"
6295 " Establish trust relationship"
6299 rpc_trustdom_revoke
,
6301 "Revoke trust relationship",
6302 "net rpc trustdom revoke\n"
6303 " Revoke trust relationship"
6309 "List domain trusts",
6310 "net rpc trustdom list\n"
6311 " List domain trusts"
6315 rpc_trustdom_vampire
,
6317 "Vampire trusts from remote server",
6318 "net rpc trustdom vampire\n"
6319 " Vampire trusts from remote server"
6321 {NULL
, NULL
, 0, NULL
, NULL
}
6324 return net_run_function(c
, argc
, argv
, "net rpc trustdom", func
);
6328 * Check if a server will take rpc commands
6329 * @param flags Type of server to connect to (PDC, DMB, localhost)
6330 * if the host is not explicitly specified
6331 * @return bool (true means rpc supported)
6333 bool net_rpc_check(struct net_context
*c
, unsigned flags
)
6335 struct cli_state
*cli
;
6337 struct sockaddr_storage server_ss
;
6338 char *server_name
= NULL
;
6341 /* flags (i.e. server type) may depend on command */
6342 if (!net_find_server(c
, NULL
, flags
, &server_ss
, &server_name
))
6345 if ((cli
= cli_initialise()) == NULL
) {
6349 status
= cli_connect(cli
, server_name
, &server_ss
);
6350 if (!NT_STATUS_IS_OK(status
))
6352 if (!attempt_netbios_session_request(&cli
, global_myname(),
6353 server_name
, &server_ss
))
6355 if (!cli_negprot(cli
))
6357 if (cli
->protocol
< PROTOCOL_NT1
)
6366 /* dump sam database via samsync rpc calls */
6367 static int rpc_samdump(struct net_context
*c
, int argc
, const char **argv
) {
6368 if (c
->display_usage
) {
6371 " Dump remote SAM database\n");
6375 return run_rpc_command(c
, NULL
, &ndr_table_netlogon
.syntax_id
,
6376 NET_FLAGS_ANONYMOUS
,
6377 rpc_samdump_internals
, argc
, argv
);
6380 /* syncronise sam database via samsync rpc calls */
6381 static int rpc_vampire(struct net_context
*c
, int argc
, const char **argv
)
6383 struct functable func
[] = {
6388 "Dump remote SAM database to ldif",
6389 "net rpc vampire ldif\n"
6390 " Dump remote SAM database to LDIF file or stdout"
6396 "Dump remote SAM database to Kerberos Keytab",
6397 "net rpc vampire keytab\n"
6398 " Dump remote SAM database to Kerberos keytab file"
6404 "Dump remote SAM database to passdb",
6405 "net rpc vampire passdb\n"
6406 " Dump remote SAM database to passdb"
6409 {NULL
, NULL
, 0, NULL
, NULL
}
6413 if (c
->display_usage
) {
6416 " Vampire remote SAM database\n");
6420 return run_rpc_command(c
, NULL
, &ndr_table_netlogon
.syntax_id
,
6421 NET_FLAGS_ANONYMOUS
,
6422 rpc_vampire_internals
,
6426 return net_run_function(c
, argc
, argv
, "net rpc vampire", func
);
6430 * Migrate everything from a print server.
6432 * @param c A net_context structure.
6433 * @param argc Standard main() style argc.
6434 * @param argv Standard main() style argv. Initial components are already
6437 * @return A shell status integer (0 for success).
6439 * The order is important !
6440 * To successfully add drivers the print queues have to exist !
6441 * Applying ACLs should be the last step, because you're easily locked out.
6444 static int rpc_printer_migrate_all(struct net_context
*c
, int argc
,
6449 if (c
->display_usage
) {
6451 "net rpc printer migrate all\n"
6452 " Migrate everything from a print server\n");
6457 d_printf("no server to migrate\n");
6461 ret
= run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6462 rpc_printer_migrate_printers_internals
, argc
,
6467 ret
= run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6468 rpc_printer_migrate_drivers_internals
, argc
,
6473 ret
= run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6474 rpc_printer_migrate_forms_internals
, argc
, argv
);
6478 ret
= run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6479 rpc_printer_migrate_settings_internals
, argc
,
6484 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6485 rpc_printer_migrate_security_internals
, argc
,
6491 * Migrate print drivers from a print server.
6493 * @param c A net_context structure.
6494 * @param argc Standard main() style argc.
6495 * @param argv Standard main() style argv. Initial components are already
6498 * @return A shell status integer (0 for success).
6500 static int rpc_printer_migrate_drivers(struct net_context
*c
, int argc
,
6503 if (c
->display_usage
) {
6505 "net rpc printer migrate drivers\n"
6506 " Migrate print-drivers from a print-server\n");
6511 d_printf("no server to migrate\n");
6515 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6516 rpc_printer_migrate_drivers_internals
,
6521 * Migrate print-forms from a print-server.
6523 * @param c A net_context structure.
6524 * @param argc Standard main() style argc.
6525 * @param argv Standard main() style argv. Initial components are already
6528 * @return A shell status integer (0 for success).
6530 static int rpc_printer_migrate_forms(struct net_context
*c
, int argc
,
6533 if (c
->display_usage
) {
6535 "net rpc printer migrate forms\n"
6536 " Migrate print-forms from a print-server\n");
6541 d_printf("no server to migrate\n");
6545 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6546 rpc_printer_migrate_forms_internals
,
6551 * Migrate printers from a print-server.
6553 * @param c A net_context structure.
6554 * @param argc Standard main() style argc.
6555 * @param argv Standard main() style argv. Initial components are already
6558 * @return A shell status integer (0 for success).
6560 static int rpc_printer_migrate_printers(struct net_context
*c
, int argc
,
6563 if (c
->display_usage
) {
6565 "net rpc printer migrate printers\n"
6566 " Migrate printers from a print-server\n");
6571 d_printf("no server to migrate\n");
6575 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6576 rpc_printer_migrate_printers_internals
,
6581 * Migrate printer-ACLs from a print-server
6583 * @param c A net_context structure.
6584 * @param argc Standard main() style argc.
6585 * @param argv Standard main() style argv. Initial components are already
6588 * @return A shell status integer (0 for success).
6590 static int rpc_printer_migrate_security(struct net_context
*c
, int argc
,
6593 if (c
->display_usage
) {
6595 "net rpc printer migrate security\n"
6596 " Migrate printer-ACLs from a print-server\n");
6601 d_printf("no server to migrate\n");
6605 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6606 rpc_printer_migrate_security_internals
,
6611 * Migrate printer-settings from a print-server.
6613 * @param c A net_context structure.
6614 * @param argc Standard main() style argc.
6615 * @param argv Standard main() style argv. Initial components are already
6618 * @return A shell status integer (0 for success).
6620 static int rpc_printer_migrate_settings(struct net_context
*c
, int argc
,
6623 if (c
->display_usage
) {
6625 "net rpc printer migrate settings\n"
6626 " Migrate printer-settings from a print-server\n");
6631 d_printf("no server to migrate\n");
6635 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6636 rpc_printer_migrate_settings_internals
,
6641 * 'net rpc printer' entrypoint.
6643 * @param c A net_context structure.
6644 * @param argc Standard main() style argc.
6645 * @param argv Standard main() style argv. Initial components are already
6649 int rpc_printer_migrate(struct net_context
*c
, int argc
, const char **argv
)
6652 /* ouch: when addriver and setdriver are called from within
6653 rpc_printer_migrate_drivers_internals, the printer-queue already
6656 struct functable func
[] = {
6659 rpc_printer_migrate_all
,
6661 "Migrate all from remote to local print server",
6662 "net rpc printer migrate all\n"
6663 " Migrate all from remote to local print server"
6667 rpc_printer_migrate_drivers
,
6669 "Migrate drivers to local server",
6670 "net rpc printer migrate drivers\n"
6671 " Migrate drivers to local server"
6675 rpc_printer_migrate_forms
,
6677 "Migrate froms to local server",
6678 "net rpc printer migrate forms\n"
6679 " Migrate froms to local server"
6683 rpc_printer_migrate_printers
,
6685 "Migrate printers to local server",
6686 "net rpc printer migrate printers\n"
6687 " Migrate printers to local server"
6691 rpc_printer_migrate_security
,
6693 "Mirgate printer ACLs to local server",
6694 "net rpc printer migrate security\n"
6695 " Mirgate printer ACLs to local server"
6699 rpc_printer_migrate_settings
,
6701 "Migrate printer settings to local server",
6702 "net rpc printer migrate settings\n"
6703 " Migrate printer settings to local server"
6705 {NULL
, NULL
, 0, NULL
, NULL
}
6708 return net_run_function(c
, argc
, argv
, "net rpc printer migrate",func
);
6713 * List printers on a remote RPC server.
6715 * @param c A net_context structure.
6716 * @param argc Standard main() style argc.
6717 * @param argv Standard main() style argv. Initial components are already
6720 * @return A shell status integer (0 for success).
6722 static int rpc_printer_list(struct net_context
*c
, int argc
, const char **argv
)
6724 if (c
->display_usage
) {
6726 "net rpc printer list\n"
6727 " List printers on a remote RPC server\n");
6731 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6732 rpc_printer_list_internals
,
6737 * List printer-drivers on a remote RPC server.
6739 * @param c A net_context structure.
6740 * @param argc Standard main() style argc.
6741 * @param argv Standard main() style argv. Initial components are already
6744 * @return A shell status integer (0 for success).
6746 static int rpc_printer_driver_list(struct net_context
*c
, int argc
,
6749 if (c
->display_usage
) {
6751 "net rpc printer driver\n"
6752 " List printer-drivers on a remote RPC server\n");
6756 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6757 rpc_printer_driver_list_internals
,
6762 * Publish printer in ADS via MSRPC.
6764 * @param c A net_context structure.
6765 * @param argc Standard main() style argc.
6766 * @param argv Standard main() style argv. Initial components are already
6769 * @return A shell status integer (0 for success).
6771 static int rpc_printer_publish_publish(struct net_context
*c
, int argc
,
6774 if (c
->display_usage
) {
6776 "net rpc printer publish publish\n"
6777 " Publish printer in ADS via MSRPC\n");
6781 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6782 rpc_printer_publish_publish_internals
,
6787 * Update printer in ADS via MSRPC.
6789 * @param c A net_context structure.
6790 * @param argc Standard main() style argc.
6791 * @param argv Standard main() style argv. Initial components are already
6794 * @return A shell status integer (0 for success).
6796 static int rpc_printer_publish_update(struct net_context
*c
, int argc
, const char **argv
)
6798 if (c
->display_usage
) {
6800 "net rpc printer publish update\n"
6801 " Update printer in ADS via MSRPC\n");
6805 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6806 rpc_printer_publish_update_internals
,
6811 * UnPublish printer in ADS via MSRPC.
6813 * @param c A net_context structure.
6814 * @param argc Standard main() style argc.
6815 * @param argv Standard main() style argv. Initial components are already
6818 * @return A shell status integer (0 for success).
6820 static int rpc_printer_publish_unpublish(struct net_context
*c
, int argc
,
6823 if (c
->display_usage
) {
6825 "net rpc printer publish unpublish\n"
6826 " UnPublish printer in ADS via MSRPC\n");
6830 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6831 rpc_printer_publish_unpublish_internals
,
6836 * List published printers via MSRPC.
6838 * @param c A net_context structure.
6839 * @param argc Standard main() style argc.
6840 * @param argv Standard main() style argv. Initial components are already
6843 * @return A shell status integer (0 for success).
6845 static int rpc_printer_publish_list(struct net_context
*c
, int argc
,
6848 if (c
->display_usage
) {
6850 "net rpc printer publish list\n"
6851 " List published printers via MSRPC\n");
6855 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6856 rpc_printer_publish_list_internals
,
6862 * Publish printer in ADS.
6864 * @param c A net_context structure.
6865 * @param argc Standard main() style argc.
6866 * @param argv Standard main() style argv. Initial components are already
6869 * @return A shell status integer (0 for success).
6871 static int rpc_printer_publish(struct net_context
*c
, int argc
,
6875 struct functable func
[] = {
6878 rpc_printer_publish_publish
,
6880 "Publish printer in AD",
6881 "net rpc printer publish publish\n"
6882 " Publish printer in AD"
6886 rpc_printer_publish_update
,
6888 "Update printer in AD",
6889 "net rpc printer publish update\n"
6890 " Update printer in AD"
6894 rpc_printer_publish_unpublish
,
6896 "Unpublish printer",
6897 "net rpc printer publish unpublish\n"
6898 " Unpublish printer"
6902 rpc_printer_publish_list
,
6904 "List published printers",
6905 "net rpc printer publish list\n"
6906 " List published printers"
6908 {NULL
, NULL
, 0, NULL
, NULL
}
6912 if (c
->display_usage
) {
6913 d_printf("Usage:\n");
6914 d_printf("net rpc printer publish\n"
6915 " List published printers\n"
6916 " Alias of net rpc printer publish list\n");
6917 net_display_usage_from_functable(func
);
6920 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
6921 rpc_printer_publish_list_internals
,
6925 return net_run_function(c
, argc
, argv
, "net rpc printer publish",func
);
6931 * Display rpc printer help page.
6933 * @param c A net_context structure.
6934 * @param argc Standard main() style argc.
6935 * @param argv Standard main() style argv. Initial components are already
6938 int rpc_printer_usage(struct net_context
*c
, int argc
, const char **argv
)
6940 d_printf("net rpc printer LIST [printer] [misc. options] [targets]\n"
6941 "\tlists all printers on print-server\n\n");
6942 d_printf("net rpc printer DRIVER [printer] [misc. options] [targets]\n"
6943 "\tlists all printer-drivers on print-server\n\n");
6944 d_printf("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"
6945 "\tpublishes printer settings in Active Directory\n"
6946 "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n");
6947 d_printf("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"
6948 "\n\tmigrates printers from remote to local server\n\n");
6949 d_printf("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"
6950 "\n\tmigrates printer-settings from remote to local server\n\n");
6951 d_printf("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"
6952 "\n\tmigrates printer-drivers from remote to local server\n\n");
6953 d_printf("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"
6954 "\n\tmigrates printer-forms from remote to local server\n\n");
6955 d_printf("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"
6956 "\n\tmigrates printer-ACLs from remote to local server\n\n");
6957 d_printf("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"
6958 "\n\tmigrates drivers, forms, queues, settings and acls from\n"
6959 "\tremote to local print-server\n\n");
6960 net_common_methods_usage(c
, argc
, argv
);
6961 net_common_flags_usage(c
, argc
, argv
);
6963 "\t-v or --verbose\t\t\tgive verbose output\n"
6964 "\t --destination\t\tmigration target server (default: localhost)\n");
6970 * 'net rpc printer' entrypoint.
6972 * @param c A net_context structure.
6973 * @param argc Standard main() style argc.
6974 * @param argv Standard main() style argv. Initial components are already
6977 int net_rpc_printer(struct net_context
*c
, int argc
, const char **argv
)
6979 struct functable func
[] = {
6984 "List all printers on print server",
6985 "net rpc printer list\n"
6986 " List all printers on print server"
6990 rpc_printer_migrate
,
6992 "Migrate printer to local server",
6993 "net rpc printer migrate\n"
6994 " Migrate printer to local server"
6998 rpc_printer_driver_list
,
7000 "List printer drivers",
7001 "net rpc printer driver\n"
7002 " List printer drivers"
7006 rpc_printer_publish
,
7008 "Publish printer in AD",
7009 "net rpc printer publish\n"
7010 " Publish printer in AD"
7012 {NULL
, NULL
, 0, NULL
, NULL
}
7016 if (c
->display_usage
) {
7017 d_printf("Usage:\n");
7018 d_printf("net rpc printer\n"
7019 " List printers\n");
7020 net_display_usage_from_functable(func
);
7023 return run_rpc_command(c
, NULL
, &syntax_spoolss
, 0,
7024 rpc_printer_list_internals
,
7028 return net_run_function(c
, argc
, argv
, "net rpc printer", func
);
7032 * 'net rpc' entrypoint.
7034 * @param c A net_context structure.
7035 * @param argc Standard main() style argc.
7036 * @param argv Standard main() style argv. Initial components are already
7040 int net_rpc(struct net_context
*c
, int argc
, const char **argv
)
7042 struct functable func
[] = {
7047 "Modify global audit settings",
7049 " Modify global audit settings"
7055 "Show basic info about a domain",
7057 " Show basic info about a domain"
7071 "Join a domain created in server manager",
7073 " Join a domain created in server manager"
7079 "Test that a join is valid",
7080 "net rpc testjoin\n"
7081 " Test that a join is valid"
7087 "List/modify users",
7089 " List/modify users"
7095 "Change a user password",
7096 "net rpc password\n"
7097 " Change a user password\n"
7098 " Alias for net rpc user password"
7104 "List/modify groups",
7106 " List/modify groups"
7112 "List/modify shares",
7114 " List/modify shares"
7128 "List/modify printers",
7130 " List/modify printers"
7134 net_rpc_changetrustpw
,
7136 "Change trust account password",
7137 "net rpc changetrustpw\n"
7138 " Change trust account password"
7144 "Modify domain trusts",
7145 "net rpc trustdom\n"
7146 " Modify domain trusts"
7152 "Abort a remote shutdown",
7153 "net rpc abortshutdown\n"
7154 " Abort a remote shutdown"
7160 "Shutdown a remote server",
7161 "net rpc shutdown\n"
7162 " Shutdown a remote server"
7168 "Dump SAM data of remote NT PDC",
7170 " Dump SAM data of remote NT PDC"
7176 "Sync a remote NT PDC's data into local passdb",
7178 " Sync a remote NT PDC's data into local passdb"
7184 "Fetch the domain sid into local secrets.tdb",
7186 " Fetch the domain sid into local secrets.tdb"
7192 "Manage privileges assigned to SID",
7194 " Manage privileges assigned to SID"
7200 "Start/stop/query remote services",
7202 " Start/stop/query remote services"
7208 "Manage registry hives",
7209 "net rpc registry\n"
7210 " Manage registry hives"
7216 "Open interactive shell on remote server",
7218 " Open interactive shell on remote server"
7220 {NULL
, NULL
, 0, NULL
, NULL
}
7222 return net_run_function(c
, argc
, argv
, "net rpc", func
);