Removed version number from file header.
[ira/wip.git] / source3 / utils / net_rpc.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19  
20 #include "includes.h"
21 #include "../utils/net.h"
22
23 /**
24  * @file net_rpc.c
25  *
26  * @brief RPC based subcommands for the 'net' utility.
27  *
28  * This file should contain much of the functionality that used to
29  * be found in rpcclient, execpt that the commands should change 
30  * less often, and the fucntionality should be sane (the user is not 
31  * expected to know a rid/sid before they conduct an operation etc.)
32  *
33  * @todo Perhaps eventually these should be split out into a number
34  * of files, as this could get quite big.
35  **/
36
37
38 /* A function of this type is passed to the 'run_rpc_command' wrapper */
39 typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, struct cli_state *, TALLOC_CTX *, int, const char **);
40
41 /**
42  * Many of the RPC functions need the domain sid.  This function gets
43  *  it at the start of every run 
44  *
45  * @param cli A cli_state already connected to the remote machine
46  *
47  * @return The Domain SID of the remote machine.
48  **/
49
50 static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
51 {
52         DOM_SID *domain_sid;
53         POLICY_HND pol;
54         NTSTATUS result = NT_STATUS_OK;
55         uint32 info_class = 5;
56         fstring domain_name;
57         TALLOC_CTX *mem_ctx;
58         
59         if (!(domain_sid = malloc(sizeof(DOM_SID)))){
60                 DEBUG(0,("fetch_domain_sid: malloc returned NULL!\n"));
61                 goto error;
62         }
63             
64         if (!(mem_ctx=talloc_init()))
65         {
66                 DEBUG(0,("fetch_domain_sid: talloc_init returned NULL!\n"));
67                 goto error;
68         }
69
70
71         if (!cli_nt_session_open (cli, PIPE_LSARPC)) {
72                 fprintf(stderr, "could not initialise lsa pipe\n");
73                 goto error;
74         }
75         
76         result = cli_lsa_open_policy(cli, mem_ctx, True, 
77                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
78                                      &pol);
79         if (!NT_STATUS_IS_OK(result)) {
80                 goto error;
81         }
82
83         result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, 
84                                            domain_name, domain_sid);
85         if (!NT_STATUS_IS_OK(result)) {
86                 goto error;
87         }
88
89         cli_lsa_close(cli, mem_ctx, &pol);
90         cli_nt_session_close(cli);
91         talloc_destroy(mem_ctx);
92
93         return domain_sid;
94
95  error:
96         fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
97
98         if (!NT_STATUS_IS_OK(result)) {
99                 fprintf(stderr, "error: %s\n", get_nt_error_msg(result));
100         }
101
102         exit(1);
103 }
104
105 /**
106  * Run a single RPC command, from start to finish.
107  *
108  * @param pipe_name the pipe to connect to (usually a PIPE_ constant)
109  * @param conn_flag a NET_FLAG_ combination.  Passed to 
110  *                   net_make_ipc_connection.
111  * @param argc  Standard main() style argc
112  * @param argc  Standard main() style argv.  Initial components are already
113  *              stripped
114  * @return A shell status integer (0 for success)
115  */
116
117 static int run_rpc_command(const char *pipe_name, int conn_flags,
118                            rpc_command_fn fn,
119                            int argc, const char **argv) 
120 {
121         struct cli_state *cli = net_make_ipc_connection(conn_flags);
122         TALLOC_CTX *mem_ctx;
123         NTSTATUS nt_status;
124         DOM_SID *domain_sid;
125
126         if (!cli) {
127                 return -1;
128         }
129
130         domain_sid = net_get_remote_domain_sid(cli);
131
132         /* Create mem_ctx */
133         
134         if (!(mem_ctx = talloc_init())) {
135                 DEBUG(0, ("talloc_init() failed\n"));
136                 cli_shutdown(cli);
137                 return -1;
138         }
139         
140         if (!cli_nt_session_open(cli, pipe_name)) {
141                 DEBUG(0, ("Could not initialise samr pipe\n"));
142         }
143         
144         nt_status = fn(domain_sid, cli, mem_ctx, argc, argv);
145         
146         if (!NT_STATUS_IS_OK(nt_status)) {
147                 DEBUG(0, ("rpc command function failed! (%s)\n", get_nt_error_msg(nt_status)));
148         } else {
149                 DEBUG(5, ("rpc command function succedded\n"));
150         }
151                 
152             
153         if (cli->nt_pipe_fnum)
154                 cli_nt_session_close(cli);
155         
156         talloc_destroy(mem_ctx);
157
158         return (!NT_STATUS_IS_OK(nt_status));
159 }
160
161
162 /****************************************************************************/
163
164
165 /** 
166  * Force a change of the trust acccount password.
167  *
168  * All paramaters are provided by the run_rpc_command funcion, except for
169  * argc, argv which are passes through. 
170  *
171  * @param domain_sid The domain sid aquired from the remote server
172  * @param cli A cli_state connected to the server.
173  * @param mem_ctx Talloc context, destoyed on compleation of the function.
174  * @param argc  Standard main() style argc
175  * @param argc  Standard main() style argv.  Initial components are already
176  *              stripped
177  *
178  * @return Normal NTSTATUS return.
179  **/
180
181 static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
182                                        int argc, const char **argv) {
183         
184         return trust_pw_find_change_and_store_it(cli, mem_ctx, opt_target_workgroup);
185 }
186
187 /** 
188  * Force a change of the trust acccount password.
189  *
190  * @param argc  Standard main() style argc
191  * @param argc  Standard main() style argv.  Initial components are already
192  *              stripped
193  *
194  * @return A shell status integer (0 for success)
195  **/
196
197 static int rpc_changetrustpw(int argc, const char **argv) 
198 {
199         return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_changetrustpw_internals,
200                                argc, argv);
201 }
202
203
204 /****************************************************************************/
205
206
207 /** 
208  * Join a domain, the old way.
209  *
210  * This uses 'machinename' as the inital password, and changes it. 
211  *
212  * The password should be created with 'server manager' or eqiv first.
213  *
214  * All paramaters are provided by the run_rpc_command funcion, except for
215  * argc, argv which are passes through. 
216  *
217  * @param domain_sid The domain sid aquired from the remote server
218  * @param cli A cli_state connected to the server.
219  * @param mem_ctx Talloc context, destoyed on compleation of the function.
220  * @param argc  Standard main() style argc
221  * @param argc  Standard main() style argv.  Initial components are already
222  *              stripped
223  *
224  * @return Normal NTSTATUS return.
225  **/
226
227 static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
228                                        int argc, const char **argv) {
229         
230         extern pstring global_myname;
231         fstring trust_passwd;
232         unsigned char orig_trust_passwd_hash[16];
233
234         fstrcpy(trust_passwd, global_myname);
235         strlower(trust_passwd);
236         E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash);
237
238         return trust_pw_change_and_store_it(cli, mem_ctx, orig_trust_passwd_hash);
239 }
240
241 /** 
242  * Join a domain, the old way.
243  *
244  * @param argc  Standard main() style argc
245  * @param argc  Standard main() style argv.  Initial components are already
246  *              stripped
247  *
248  * @return A shell status integer (0 for success)
249  **/
250
251 static int rpc_join_oldstyle(int argc, const char **argv) 
252 {
253         return run_rpc_command(PIPE_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_join_oldstyle_internals,
254                                argc, argv);
255 }
256
257 /** 
258  * Basic usage function for 'net rpc join'
259  * @param argc  Standard main() style argc
260  * @param argc  Standard main() style argv.  Initial components are already
261  *              stripped
262  **/
263
264 static int rpc_join_usage(int argc, const char **argv) 
265 {       
266         d_printf("  net rpc join \t to join a domain with admin username & password\n");
267         d_printf("  net rpc join oldstyle \t to join a domain created in server manager\n");
268         return -1;
269 }
270
271 /** 
272  * 'net rpc join' entrypoint.
273  * @param argc  Standard main() style argc
274  * @param argc  Standard main() style argv.  Initial components are already
275  *              stripped
276  *
277  * Main 'net_rpc_join()' (where the admain username/password is used) is 
278  * in net_rpc_join.c
279  **/
280
281 static int rpc_join(int argc, const char **argv) 
282 {
283         struct functable func[] = {
284                 {"oldstyle", rpc_join_oldstyle},
285                 {NULL, NULL}
286         };
287         
288         if (argc == 0) {
289                 return net_rpc_join(argc, argv);
290         }
291
292         return net_run_function(argc, argv, func, rpc_join_usage);
293 }
294
295
296 /****************************************************************************/
297
298
299 /** 
300  * Add a new user to a remote RPC server
301  *
302  * All paramaters are provided by the run_rpc_command funcion, except for
303  * argc, argv which are passes through. 
304  *
305  * @param domain_sid The domain sid aquired from the remote server
306  * @param cli A cli_state connected to the server.
307  * @param mem_ctx Talloc context, destoyed on compleation of the function.
308  * @param argc  Standard main() style argc
309  * @param argc  Standard main() style argv.  Initial components are already
310  *              stripped
311  *
312  * @return Normal NTSTATUS return.
313  **/
314
315 static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
316                                        int argc, const char **argv) {
317         
318         POLICY_HND connect_pol, domain_pol, user_pol;
319         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
320         const char *acct_name;
321         uint16 acb_info;
322         uint32 unknown, user_rid;
323
324         if (argc != 1) {
325                 d_printf("Usage: net rpc user add username\n");
326                 return NT_STATUS_OK;
327         }
328
329         acct_name = argv[0];
330
331         /* Get sam policy handle */
332         
333         result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
334                                   &connect_pol);
335         if (!NT_STATUS_IS_OK(result)) {
336                 goto done;
337         }
338         
339         /* Get domain policy handle */
340         
341         result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
342                                       MAXIMUM_ALLOWED_ACCESS,
343                                       domain_sid, &domain_pol);
344         if (!NT_STATUS_IS_OK(result)) {
345                 goto done;
346         }
347
348         /* Create domain user */
349
350         acb_info = ACB_NORMAL;
351         unknown = 0xe005000b; /* No idea what this is - a permission mask? */
352
353         result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
354                                           acct_name, acb_info, unknown,
355                                           &user_pol, &user_rid);
356         if (!NT_STATUS_IS_OK(result)) {
357                 goto done;
358         }
359
360  done:
361         return result;
362 }
363
364 /** 
365  * Add a new user to a remote RPC server
366  *
367  * @param argc  Standard main() style argc
368  * @param argc  Standard main() style argv.  Initial components are already
369  *              stripped
370  *
371  * @return A shell status integer (0 for success)
372  **/
373
374 static int rpc_user_add(int argc, const char **argv) 
375 {
376         return run_rpc_command(PIPE_SAMR, 0, rpc_user_add_internals,
377                                argc, argv);
378 }
379
380 /** 
381  * Basic usage function for 'net rpc user'
382  * @param argc  Standard main() style argc
383  * @param argc  Standard main() style argv.  Initial components are already
384  *              stripped
385  **/
386
387 static int rpc_user_usage(int argc, const char **argv) 
388 {
389         d_printf("  net rpc user add \t to add a user\n");
390         return -1;
391 }
392
393 /** 
394  * 'net rpc user' entrypoint.
395  * @param argc  Standard main() style argc
396  * @param argc  Standard main() style argv.  Initial components are already
397  *              stripped
398  **/
399
400 static int rpc_user(int argc, const char **argv) 
401 {
402         struct functable func[] = {
403                 {"add", rpc_user_add},
404                 {NULL, NULL}
405         };
406         
407         if (argc == 0) {
408                 return rpc_user_usage(argc, argv);
409         }
410
411         return net_run_function(argc, argv, func, rpc_user_usage);
412 }
413
414
415 /****************************************************************************/
416
417
418
419 /** 
420  * ABORT the shutdown of a remote RPC Server
421  *
422  * All paramaters are provided by the run_rpc_command funcion, except for
423  * argc, argv which are passed through. 
424  *
425  * @param domain_sid The domain sid aquired from the remote server
426  * @param cli A cli_state connected to the server.
427  * @param mem_ctx Talloc context, destoyed on compleation of the function.
428  * @param argc  Standard main() style argc
429  * @param argc  Standard main() style argv.  Initial components are already
430  *              stripped
431  *
432  * @return Normal NTSTATUS return.
433  **/
434
435 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
436                                              int argc, const char **argv) 
437 {
438         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
439         
440         result = cli_reg_abort_shutdown(cli, mem_ctx);
441         
442         if (NT_STATUS_IS_OK(result))
443                 DEBUG(5,("cmd_reg_abort_shutdown: query succeeded\n"));
444         else
445                 DEBUG(5,("cmd_reg_abort_shutdown: query failed\n"));
446         
447         return result;
448 }
449
450
451 /** 
452  * ABORT the Shut down of a remote RPC server
453  *
454  * @param argc  Standard main() style argc
455  * @param argc  Standard main() style argv.  Initial components are already
456  *              stripped
457  *
458  * @return A shell status integer (0 for success)
459  **/
460
461 static int rpc_shutdown_abort(int argc, const char **argv) 
462 {
463         return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_abort_internals,
464                                argc, argv);
465 }
466
467 /** 
468  * Shut down a remote RPC Server
469  *
470  * All paramaters are provided by the run_rpc_command funcion, except for
471  * argc, argv which are passes through. 
472  *
473  * @param domain_sid The domain sid aquired from the remote server
474  * @param cli A cli_state connected to the server.
475  * @param mem_ctx Talloc context, destoyed on compleation of the function.
476  * @param argc  Standard main() style argc
477  * @param argc  Standard main() style argv.  Initial components are already
478  *              stripped
479  *
480  * @return Normal NTSTATUS return.
481  **/
482
483 static NTSTATUS rpc_shutdown_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, 
484                                        int argc, const char **argv) 
485 {
486         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
487         char *msg = "This machine will be shutdown shortly";
488         uint32 timeout = 20;
489         uint16 flgs = 0;
490         BOOL reboot = opt_reboot;
491         BOOL force = opt_force;
492 #if 0
493         poptContext pc;
494         int rc;
495
496         struct poptOption long_options[] = {
497                 {"message",    'm', POPT_ARG_STRING, &msg},
498                 {"timeout",    't', POPT_ARG_INT,    &timeout},
499                 {"reboot",     'r', POPT_ARG_NONE,   &reboot},
500                 {"force",      'f', POPT_ARG_NONE,   &force},
501                 { 0, 0, 0, 0}
502         };
503
504         pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
505                             POPT_CONTEXT_KEEP_FIRST);
506
507         rc = poptGetNextOpt(pc);
508         
509         if (rc < -1) {
510                 /* an error occurred during option processing */
511                 DEBUG(0, ("%s: %s\n",
512                           poptBadOption(pc, POPT_BADOPTION_NOALIAS),
513                           poptStrerror(rc)));
514                 return NT_STATUS_INVALID_PARAMETER;
515         }
516 #endif
517         if (reboot) {
518                 flgs |= REG_REBOOT_ON_SHUTDOWN;
519         }
520         if (force) {
521                 flgs |= REG_FORCE_SHUTDOWN;
522         }
523         if (opt_comment) {
524                 msg = opt_comment;
525         }
526         if (opt_timeout) {
527                 timeout = opt_timeout;
528         }
529
530         /* create an entry */
531         result = cli_reg_shutdown(cli, mem_ctx, msg, timeout, flgs);
532
533         if (NT_STATUS_IS_OK(result))
534                 DEBUG(5,("Shutdown of remote machine succeeded\n"));
535         else
536                 DEBUG(0,("Shutdown of remote machine failed!\n"));
537
538         return result;
539 }
540
541 /** 
542  * Shut down a remote RPC server
543  *
544  * @param argc  Standard main() style argc
545  * @param argc  Standard main() style argv.  Initial components are already
546  *              stripped
547  *
548  * @return A shell status integer (0 for success)
549  **/
550
551 static int rpc_shutdown(int argc, const char **argv) 
552 {
553         return run_rpc_command(PIPE_WINREG, 0, rpc_shutdown_internals,
554                                        argc, argv);
555 }
556
557 /****************************************************************************/
558
559
560 /** 
561  * Basic usage function for 'net rpc'
562  * @param argc  Standard main() style argc
563  * @param argc  Standard main() style argv.  Initial components are already
564  *              stripped
565  **/
566
567 int net_rpc_usage(int argc, const char **argv) 
568 {
569         d_printf("  net rpc join \tto join a domain \n");
570         d_printf("  net rpc user \tto add, delete and list users\n");
571         d_printf("  net rpc changetrustpw \tto change the trust account password\n");
572         d_printf("  net rpc abortshutdown \tto to abort the shutdown of a remote server\n");
573         d_printf("  net rpc shutdown \tto to shutdown a remote server\n");
574         d_printf("\n");
575         d_printf("'net rpc shutdown' also accepts the following miscellaneous options:\n"); /* misc options */
576         d_printf("\t-r or --reboot\trequest remote server reboot on shutdown\n");
577         d_printf("\t-f or --force\trequest the remote server force its shutdown\n");
578         d_printf("\t-t or --timeout=<timeout>\tnumber of seconds before shutdown\n");
579         d_printf("\t-c or --comment=<message>\ttext message to display on impending shutdown\n");
580         return -1;
581 }
582
583 /** 
584  * 'net rpc' entrypoint.
585  * @param argc  Standard main() style argc
586  * @param argc  Standard main() style argv.  Initial components are already
587  *              stripped
588  **/
589
590 int net_rpc(int argc, const char **argv)
591 {
592         struct functable func[] = {
593                 {"join", rpc_join},
594                 {"user", rpc_user},
595                 {"changetrustpw", rpc_changetrustpw},
596                 {"abortshutdown", rpc_shutdown_abort},
597                 {"shutdown", rpc_shutdown},
598                 {NULL, NULL}
599         };
600         return net_run_function(argc, argv, func, net_rpc_usage);
601 }