2 Samba Unix/Linux SMB client library
4 Distributed SMB/CIFS Server Management Utility
5 Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 #include "../utils/net.h"
27 * @brief RPC based subcommands for the 'net' utility.
29 * This file should contain much of the functionality that used to
30 * be found in rpcclient, execpt that the commands should change
31 * less often, and the fucntionality should be sane (the user is not
32 * expected to know a rid/sid before they conduct an operation etc.)
34 * @todo Perhaps eventually these should be split out into a number
35 * of files, as this could get quite big.
39 /* A function of this type is passed to the 'run_rpc_command' wrapper */
40 typedef NTSTATUS (*rpc_command_fn
)(const DOM_SID
*, struct cli_state
*, TALLOC_CTX
*, int, const char **);
43 * Many of the RPC functions need the domain sid. This function gets
44 * it at the start of every run
46 * @param cli A cli_state already connected to the remote machine
48 * @return The Domain SID of the remote machine.
51 static DOM_SID
*net_get_remote_domain_sid(struct cli_state
*cli
)
55 NTSTATUS result
= NT_STATUS_OK
;
56 uint32 info_class
= 5;
60 if (!(domain_sid
= malloc(sizeof(DOM_SID
)))){
61 DEBUG(0,("fetch_domain_sid: malloc returned NULL!\n"));
65 if (!(mem_ctx
=talloc_init()))
67 DEBUG(0,("fetch_domain_sid: talloc_init returned NULL!\n"));
72 if (!cli_nt_session_open (cli
, PIPE_LSARPC
)) {
73 fprintf(stderr
, "could not initialise lsa pipe\n");
77 result
= cli_lsa_open_policy(cli
, mem_ctx
, True
,
78 SEC_RIGHTS_MAXIMUM_ALLOWED
,
80 if (!NT_STATUS_IS_OK(result
)) {
84 result
= cli_lsa_query_info_policy(cli
, mem_ctx
, &pol
, info_class
,
85 domain_name
, domain_sid
);
86 if (!NT_STATUS_IS_OK(result
)) {
90 cli_lsa_close(cli
, mem_ctx
, &pol
);
91 cli_nt_session_close(cli
);
92 talloc_destroy(mem_ctx
);
97 fprintf(stderr
, "could not obtain sid for domain %s\n", cli
->domain
);
99 if (!NT_STATUS_IS_OK(result
)) {
100 fprintf(stderr
, "error: %s\n", get_nt_error_msg(result
));
107 * Run a single RPC command, from start to finish.
109 * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
110 * @param conn_flag a NET_FLAG_ combination. Passed to
111 * net_make_ipc_connection.
112 * @param argc Standard main() style argc
113 * @param argc Standard main() style argv. Initial components are already
115 * @return A shell status integer (0 for success)
118 static int run_rpc_command(const char *pipe_name
, int conn_flags
,
120 int argc
, const char **argv
)
122 struct cli_state
*cli
= net_make_ipc_connection(conn_flags
);
131 domain_sid
= net_get_remote_domain_sid(cli
);
135 if (!(mem_ctx
= talloc_init())) {
136 DEBUG(0, ("talloc_init() failed\n"));
141 if (!cli_nt_session_open(cli
, pipe_name
)) {
142 DEBUG(0, ("Could not initialise samr pipe\n"));
145 nt_status
= fn(domain_sid
, cli
, mem_ctx
, argc
, argv
);
147 if (!NT_STATUS_IS_OK(nt_status
)) {
148 DEBUG(0, ("rpc command function failed! (%s)\n", get_nt_error_msg(nt_status
)));
150 DEBUG(5, ("rpc command function succedded\n"));
154 if (cli
->nt_pipe_fnum
)
155 cli_nt_session_close(cli
);
157 talloc_destroy(mem_ctx
);
159 return (!NT_STATUS_IS_OK(nt_status
));
163 /****************************************************************************/
167 * Force a change of the trust acccount password.
169 * All paramaters are provided by the run_rpc_command funcion, except for
170 * argc, argv which are passes through.
172 * @param domain_sid The domain sid aquired from the remote server
173 * @param cli A cli_state connected to the server.
174 * @param mem_ctx Talloc context, destoyed on compleation of the function.
175 * @param argc Standard main() style argc
176 * @param argc Standard main() style argv. Initial components are already
179 * @return Normal NTSTATUS return.
182 static NTSTATUS
rpc_changetrustpw_internals(const DOM_SID
*domain_sid
, struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
183 int argc
, const char **argv
) {
185 return trust_pw_find_change_and_store_it(cli
, mem_ctx
, opt_target_workgroup
);
189 * Force a change of the trust acccount password.
191 * @param argc Standard main() style argc
192 * @param argc Standard main() style argv. Initial components are already
195 * @return A shell status integer (0 for success)
198 static int rpc_changetrustpw(int argc
, const char **argv
)
200 return run_rpc_command(PIPE_NETLOGON
, NET_FLAGS_ANONYMOUS
| NET_FLAGS_PDC
, rpc_changetrustpw_internals
,
205 /****************************************************************************/
209 * Join a domain, the old way.
211 * This uses 'machinename' as the inital password, and changes it.
213 * The password should be created with 'server manager' or eqiv first.
215 * All paramaters are provided by the run_rpc_command funcion, except for
216 * argc, argv which are passes through.
218 * @param domain_sid The domain sid aquired from the remote server
219 * @param cli A cli_state connected to the server.
220 * @param mem_ctx Talloc context, destoyed on compleation of the function.
221 * @param argc Standard main() style argc
222 * @param argc Standard main() style argv. Initial components are already
225 * @return Normal NTSTATUS return.
228 static NTSTATUS
rpc_join_oldstyle_internals(const DOM_SID
*domain_sid
, struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
229 int argc
, const char **argv
) {
231 extern pstring global_myname
;
232 fstring trust_passwd
;
233 unsigned char orig_trust_passwd_hash
[16];
235 fstrcpy(trust_passwd
, global_myname
);
236 strlower(trust_passwd
);
237 E_md4hash( (uchar
*)trust_passwd
, orig_trust_passwd_hash
);
239 return trust_pw_change_and_store_it(cli
, mem_ctx
, orig_trust_passwd_hash
);
243 * Join a domain, the old way.
245 * @param argc Standard main() style argc
246 * @param argc Standard main() style argv. Initial components are already
249 * @return A shell status integer (0 for success)
252 static int rpc_join_oldstyle(int argc
, const char **argv
)
254 return run_rpc_command(PIPE_NETLOGON
, NET_FLAGS_ANONYMOUS
| NET_FLAGS_PDC
, rpc_join_oldstyle_internals
,
259 * Basic usage function for 'net rpc join'
260 * @param argc Standard main() style argc
261 * @param argc Standard main() style argv. Initial components are already
265 static int rpc_join_usage(int argc
, const char **argv
)
267 d_printf(" net rpc join \t to join a domain with admin username & password\n");
268 d_printf(" net rpc join oldstyle \t to join a domain created in server manager\n");
273 * 'net rpc join' entrypoint.
274 * @param argc Standard main() style argc
275 * @param argc Standard main() style argv. Initial components are already
278 * Main 'net_rpc_join()' (where the admain username/password is used) is
282 static int rpc_join(int argc
, const char **argv
)
284 struct functable func
[] = {
285 {"oldstyle", rpc_join_oldstyle
},
290 return net_rpc_join(argc
, argv
);
293 return net_run_function(argc
, argv
, func
, rpc_join_usage
);
297 /****************************************************************************/
301 * Add a new user to a remote RPC server
303 * All paramaters are provided by the run_rpc_command funcion, except for
304 * argc, argv which are passes through.
306 * @param domain_sid The domain sid aquired from the remote server
307 * @param cli A cli_state connected to the server.
308 * @param mem_ctx Talloc context, destoyed on compleation of the function.
309 * @param argc Standard main() style argc
310 * @param argc Standard main() style argv. Initial components are already
313 * @return Normal NTSTATUS return.
316 static NTSTATUS
rpc_user_add_internals(const DOM_SID
*domain_sid
, struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
317 int argc
, const char **argv
) {
319 POLICY_HND connect_pol
, domain_pol
, user_pol
;
320 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
321 const char *acct_name
;
323 uint32 unknown
, user_rid
;
326 d_printf("Usage: net rpc user add username\n");
332 /* Get sam policy handle */
334 result
= cli_samr_connect(cli
, mem_ctx
, MAXIMUM_ALLOWED_ACCESS
,
336 if (!NT_STATUS_IS_OK(result
)) {
340 /* Get domain policy handle */
342 result
= cli_samr_open_domain(cli
, mem_ctx
, &connect_pol
,
343 MAXIMUM_ALLOWED_ACCESS
,
344 domain_sid
, &domain_pol
);
345 if (!NT_STATUS_IS_OK(result
)) {
349 /* Create domain user */
351 acb_info
= ACB_NORMAL
;
352 unknown
= 0xe005000b; /* No idea what this is - a permission mask? */
354 result
= cli_samr_create_dom_user(cli
, mem_ctx
, &domain_pol
,
355 acct_name
, acb_info
, unknown
,
356 &user_pol
, &user_rid
);
357 if (!NT_STATUS_IS_OK(result
)) {
366 * Add a new user to a remote RPC server
368 * @param argc Standard main() style argc
369 * @param argc Standard main() style argv. Initial components are already
372 * @return A shell status integer (0 for success)
375 static int rpc_user_add(int argc
, const char **argv
)
377 return run_rpc_command(PIPE_SAMR
, 0, rpc_user_add_internals
,
382 * Basic usage function for 'net rpc user'
383 * @param argc Standard main() style argc
384 * @param argc Standard main() style argv. Initial components are already
388 static int rpc_user_usage(int argc
, const char **argv
)
390 d_printf(" net rpc user add \t to add a user\n");
395 * 'net rpc user' entrypoint.
396 * @param argc Standard main() style argc
397 * @param argc Standard main() style argv. Initial components are already
401 static int rpc_user(int argc
, const char **argv
)
403 struct functable func
[] = {
404 {"add", rpc_user_add
},
409 return rpc_user_usage(argc
, argv
);
412 return net_run_function(argc
, argv
, func
, rpc_user_usage
);
416 /****************************************************************************/
421 * ABORT the shutdown of a remote RPC Server
423 * All paramaters are provided by the run_rpc_command funcion, except for
424 * argc, argv which are passed through.
426 * @param domain_sid The domain sid aquired from the remote server
427 * @param cli A cli_state connected to the server.
428 * @param mem_ctx Talloc context, destoyed on compleation of the function.
429 * @param argc Standard main() style argc
430 * @param argc Standard main() style argv. Initial components are already
433 * @return Normal NTSTATUS return.
436 static NTSTATUS
rpc_shutdown_abort_internals(const DOM_SID
*domain_sid
, struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
437 int argc
, const char **argv
)
439 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
441 result
= cli_reg_abort_shutdown(cli
, mem_ctx
);
443 if (NT_STATUS_IS_OK(result
))
444 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
446 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
453 * ABORT the Shut down of a remote RPC server
455 * @param argc Standard main() style argc
456 * @param argc Standard main() style argv. Initial components are already
459 * @return A shell status integer (0 for success)
462 static int rpc_shutdown_abort(int argc
, const char **argv
)
464 return run_rpc_command(PIPE_WINREG
, 0, rpc_shutdown_abort_internals
,
469 * Shut down a remote RPC Server
471 * All paramaters are provided by the run_rpc_command funcion, except for
472 * argc, argv which are passes through.
474 * @param domain_sid The domain sid aquired from the remote server
475 * @param cli A cli_state connected to the server.
476 * @param mem_ctx Talloc context, destoyed on compleation of the function.
477 * @param argc Standard main() style argc
478 * @param argc Standard main() style argv. Initial components are already
481 * @return Normal NTSTATUS return.
484 static NTSTATUS
rpc_shutdown_internals(const DOM_SID
*domain_sid
, struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
485 int argc
, const char **argv
)
487 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
488 char *msg
= "This machine will be shutdown shortly";
491 BOOL reboot
= opt_reboot
;
492 BOOL force
= opt_force
;
497 struct poptOption long_options
[] = {
498 {"message", 'm', POPT_ARG_STRING
, &msg
},
499 {"timeout", 't', POPT_ARG_INT
, &timeout
},
500 {"reboot", 'r', POPT_ARG_NONE
, &reboot
},
501 {"force", 'f', POPT_ARG_NONE
, &force
},
505 pc
= poptGetContext(NULL
, argc
, (const char **) argv
, long_options
,
506 POPT_CONTEXT_KEEP_FIRST
);
508 rc
= poptGetNextOpt(pc
);
511 /* an error occurred during option processing */
512 DEBUG(0, ("%s: %s\n",
513 poptBadOption(pc
, POPT_BADOPTION_NOALIAS
),
515 return NT_STATUS_INVALID_PARAMETER
;
519 flgs
|= REG_REBOOT_ON_SHUTDOWN
;
522 flgs
|= REG_FORCE_SHUTDOWN
;
528 timeout
= opt_timeout
;
531 /* create an entry */
532 result
= cli_reg_shutdown(cli
, mem_ctx
, msg
, timeout
, flgs
);
534 if (NT_STATUS_IS_OK(result
))
535 DEBUG(5,("Shutdown of remote machine succeeded\n"));
537 DEBUG(0,("Shutdown of remote machine failed!\n"));
543 * Shut down a remote RPC server
545 * @param argc Standard main() style argc
546 * @param argc Standard main() style argv. Initial components are already
549 * @return A shell status integer (0 for success)
552 static int rpc_shutdown(int argc
, const char **argv
)
554 return run_rpc_command(PIPE_WINREG
, 0, rpc_shutdown_internals
,
558 /****************************************************************************/
562 * Basic usage function for 'net rpc'
563 * @param argc Standard main() style argc
564 * @param argc Standard main() style argv. Initial components are already
568 int net_rpc_usage(int argc
, const char **argv
)
570 d_printf(" net rpc join \tto join a domain \n");
571 d_printf(" net rpc user \tto add, delete and list users\n");
572 d_printf(" net rpc changetrustpw \tto change the trust account password\n");
573 d_printf(" net rpc abortshutdown \tto to abort the shutdown of a remote server\n");
574 d_printf(" net rpc shutdown \tto to shutdown a remote server\n");
576 d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
577 d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
578 d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
579 d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
580 d_printf("\t-c or --comment=<message>\ttext message to display on impending shutdown\n");
585 * 'net rpc' entrypoint.
586 * @param argc Standard main() style argc
587 * @param argc Standard main() style argv. Initial components are already
591 int net_rpc(int argc
, const char **argv
)
593 struct functable func
[] = {
596 {"changetrustpw", rpc_changetrustpw
},
597 {"abortshutdown", rpc_shutdown_abort
},
598 {"shutdown", rpc_shutdown
},
601 return net_run_function(argc
, argv
, func
, net_rpc_usage
);