sync getopt() args with 2.2
[Samba.git] / source / utils / net_rpc.c
blob68a14197b4dd6cc53e870833a8cc7bd33e674e6f
1 /*
2 Samba Unix/Linux SMB client library
3 Version 3.0
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. */
21 #include "includes.h"
22 #include "../utils/net.h"
24 /**
25 * @file net_rpc.c
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.
36 **/
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 **);
42 /**
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.
49 **/
51 static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
53 DOM_SID *domain_sid;
54 POLICY_HND pol;
55 NTSTATUS result = NT_STATUS_OK;
56 uint32 info_class = 5;
57 fstring domain_name;
58 TALLOC_CTX *mem_ctx;
60 if (!(domain_sid = malloc(sizeof(DOM_SID)))){
61 DEBUG(0,("fetch_domain_sid: malloc returned NULL!\n"));
62 goto error;
65 if (!(mem_ctx=talloc_init()))
67 DEBUG(0,("fetch_domain_sid: talloc_init returned NULL!\n"));
68 goto error;
72 if (!cli_nt_session_open (cli, PIPE_LSARPC)) {
73 fprintf(stderr, "could not initialise lsa pipe\n");
74 goto error;
77 result = cli_lsa_open_policy(cli, mem_ctx, True,
78 SEC_RIGHTS_MAXIMUM_ALLOWED,
79 &pol);
80 if (!NT_STATUS_IS_OK(result)) {
81 goto error;
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)) {
87 goto error;
90 cli_lsa_close(cli, mem_ctx, &pol);
91 cli_nt_session_close(cli);
92 talloc_destroy(mem_ctx);
94 return domain_sid;
96 error:
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));
103 exit(1);
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
114 * stripped
115 * @return A shell status integer (0 for success)
118 static int run_rpc_command(const char *pipe_name, int conn_flags,
119 rpc_command_fn fn,
120 int argc, const char **argv)
122 struct cli_state *cli = net_make_ipc_connection(conn_flags);
123 TALLOC_CTX *mem_ctx;
124 NTSTATUS nt_status;
125 DOM_SID *domain_sid;
127 if (!cli) {
128 return -1;
131 domain_sid = net_get_remote_domain_sid(cli);
133 /* Create mem_ctx */
135 if (!(mem_ctx = talloc_init())) {
136 DEBUG(0, ("talloc_init() failed\n"));
137 cli_shutdown(cli);
138 return -1;
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)));
149 } else {
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 /****************************************************************************/
166 /**
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
177 * stripped
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);
188 /**
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
193 * stripped
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,
201 argc, argv);
205 /****************************************************************************/
208 /**
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
223 * stripped
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);
242 /**
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
247 * stripped
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,
255 argc, argv);
258 /**
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
262 * stripped
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");
269 return -1;
272 /**
273 * 'net rpc join' entrypoint.
274 * @param argc Standard main() style argc
275 * @param argc Standard main() style argv. Initial components are already
276 * stripped
278 * Main 'net_rpc_join()' (where the admain username/password is used) is
279 * in net_rpc_join.c
282 static int rpc_join(int argc, const char **argv)
284 struct functable func[] = {
285 {"oldstyle", rpc_join_oldstyle},
286 {NULL, NULL}
289 if (argc == 0) {
290 return net_rpc_join(argc, argv);
293 return net_run_function(argc, argv, func, rpc_join_usage);
297 /****************************************************************************/
300 /**
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
311 * stripped
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;
322 uint16 acb_info;
323 uint32 unknown, user_rid;
325 if (argc != 1) {
326 d_printf("Usage: net rpc user add username\n");
327 return NT_STATUS_OK;
330 acct_name = argv[0];
332 /* Get sam policy handle */
334 result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
335 &connect_pol);
336 if (!NT_STATUS_IS_OK(result)) {
337 goto done;
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)) {
346 goto done;
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)) {
358 goto done;
361 done:
362 return result;
365 /**
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
370 * stripped
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,
378 argc, argv);
381 /**
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
385 * stripped
388 static int rpc_user_usage(int argc, const char **argv)
390 d_printf(" net rpc user add \t to add a user\n");
391 return -1;
394 /**
395 * 'net rpc user' entrypoint.
396 * @param argc Standard main() style argc
397 * @param argc Standard main() style argv. Initial components are already
398 * stripped
401 static int rpc_user(int argc, const char **argv)
403 struct functable func[] = {
404 {"add", rpc_user_add},
405 {NULL, NULL}
408 if (argc == 0) {
409 return rpc_user_usage(argc, argv);
412 return net_run_function(argc, argv, func, rpc_user_usage);
416 /****************************************************************************/
420 /**
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
431 * stripped
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"));
445 else
446 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
448 return result;
452 /**
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
457 * stripped
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,
465 argc, argv);
468 /**
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
479 * stripped
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";
489 uint32 timeout = 20;
490 uint16 flgs = 0;
491 BOOL reboot = opt_reboot;
492 BOOL force = opt_force;
493 #if 0
494 poptContext pc;
495 int rc;
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},
502 { 0, 0, 0, 0}
505 pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
506 POPT_CONTEXT_KEEP_FIRST);
508 rc = poptGetNextOpt(pc);
510 if (rc < -1) {
511 /* an error occurred during option processing */
512 DEBUG(0, ("%s: %s\n",
513 poptBadOption(pc, POPT_BADOPTION_NOALIAS),
514 poptStrerror(rc)));
515 return NT_STATUS_INVALID_PARAMETER;
517 #endif
518 if (reboot) {
519 flgs |= REG_REBOOT_ON_SHUTDOWN;
521 if (force) {
522 flgs |= REG_FORCE_SHUTDOWN;
524 if (opt_comment) {
525 msg = opt_comment;
527 if (opt_timeout) {
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"));
536 else
537 DEBUG(0,("Shutdown of remote machine failed!\n"));
539 return result;
542 /**
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
547 * stripped
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,
555 argc, argv);
558 /****************************************************************************/
561 /**
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
565 * stripped
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");
575 d_printf("\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");
581 return -1;
584 /**
585 * 'net rpc' entrypoint.
586 * @param argc Standard main() style argc
587 * @param argc Standard main() style argv. Initial components are already
588 * stripped
591 int net_rpc(int argc, const char **argv)
593 struct functable func[] = {
594 {"join", rpc_join},
595 {"user", rpc_user},
596 {"changetrustpw", rpc_changetrustpw},
597 {"abortshutdown", rpc_shutdown_abort},
598 {"shutdown", rpc_shutdown},
599 {NULL, NULL}
601 return net_run_function(argc, argv, func, net_rpc_usage);