samba: share readline wrappers among all buildsystems.
[metze/samba/wip.git] / source3 / rpcclient / rpcclient.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Tim Potter 2000-2001
6    Copyright (C) Martin Pool 2003
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "popt_common.h"
24 #include "rpcclient.h"
25 #include "../libcli/auth/libcli_auth.h"
26 #include "../librpc/gen_ndr/cli_lsa.h"
27 #include "rpc_client/cli_lsarpc.h"
28 #include "../librpc/gen_ndr/ndr_netlogon.h"
29 #include "rpc_client/cli_netlogon.h"
30 #include "../libcli/smbreadline/smbreadline.h"
31
32 enum pipe_auth_type_spnego {
33         PIPE_AUTH_TYPE_SPNEGO_NONE = 0,
34         PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
35         PIPE_AUTH_TYPE_SPNEGO_KRB5
36 };
37
38 struct dom_sid domain_sid;
39
40 static enum dcerpc_AuthType pipe_default_auth_type = DCERPC_AUTH_TYPE_NONE;
41 static enum pipe_auth_type_spnego pipe_default_auth_spnego_type = 0;
42 static enum dcerpc_AuthLevel pipe_default_auth_level = DCERPC_AUTH_LEVEL_NONE;
43 static unsigned int timeout = 0;
44 static enum dcerpc_transport_t default_transport = NCACN_NP;
45
46 struct user_auth_info *rpcclient_auth_info;
47
48 /* List to hold groups of commands.
49  *
50  * Commands are defined in a list of arrays: arrays are easy to
51  * statically declare, and lists are easier to dynamically extend.
52  */
53
54 static struct cmd_list {
55         struct cmd_list *prev, *next;
56         struct cmd_set *cmd_set;
57 } *cmd_list;
58
59 /****************************************************************************
60 handle completion of commands for readline
61 ****************************************************************************/
62 static char **completion_fn(const char *text, int start, int end)
63 {
64 #define MAX_COMPLETIONS 1000
65         char **matches;
66         int i, count=0;
67         struct cmd_list *commands = cmd_list;
68
69 #if 0   /* JERRY */
70         /* FIXME!!!  -- what to do when completing argument? */
71         /* for words not at the start of the line fallback 
72            to filename completion */
73         if (start) 
74                 return NULL;
75 #endif
76
77         /* make sure we have a list of valid commands */
78         if (!commands) {
79                 return NULL;
80         }
81
82         matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
83         if (!matches) {
84                 return NULL;
85         }
86
87         matches[count++] = SMB_STRDUP(text);
88         if (!matches[0]) {
89                 SAFE_FREE(matches);
90                 return NULL;
91         }
92
93         while (commands && count < MAX_COMPLETIONS-1) {
94                 if (!commands->cmd_set) {
95                         break;
96                 }
97
98                 for (i=0; commands->cmd_set[i].name; i++) {
99                         if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
100                                 (( commands->cmd_set[i].returntype == RPC_RTYPE_NTSTATUS &&
101                         commands->cmd_set[i].ntfn ) || 
102                       ( commands->cmd_set[i].returntype == RPC_RTYPE_WERROR &&
103                         commands->cmd_set[i].wfn))) {
104                                 matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
105                                 if (!matches[count]) {
106                                         for (i = 0; i < count; i++) {
107                                                 SAFE_FREE(matches[count]);
108                                         }
109                                         SAFE_FREE(matches);
110                                         return NULL;
111                                 }
112                                 count++;
113                         }
114                 }
115                 commands = commands->next;
116         }
117
118         if (count == 2) {
119                 SAFE_FREE(matches[0]);
120                 matches[0] = SMB_STRDUP(matches[1]);
121         }
122         matches[count] = NULL;
123         return matches;
124 }
125
126 static char *next_command (char **cmdstr)
127 {
128         char *command;
129         char                    *p;
130
131         if (!cmdstr || !(*cmdstr))
132                 return NULL;
133
134         p = strchr_m(*cmdstr, ';');
135         if (p)
136                 *p = '\0';
137         command = SMB_STRDUP(*cmdstr);
138         if (p)
139                 *cmdstr = p + 1;
140         else
141                 *cmdstr = NULL;
142
143         return command;
144 }
145
146 /* Fetch the SID for this computer */
147
148 static void fetch_machine_sid(struct cli_state *cli)
149 {
150         struct policy_handle pol;
151         NTSTATUS result = NT_STATUS_OK;
152         static bool got_domain_sid;
153         TALLOC_CTX *mem_ctx;
154         struct rpc_pipe_client *lsapipe = NULL;
155         union lsa_PolicyInformation *info = NULL;
156
157         if (got_domain_sid) return;
158
159         if (!(mem_ctx=talloc_init("fetch_machine_sid"))) {
160                 DEBUG(0,("fetch_machine_sid: talloc_init returned NULL!\n"));
161                 goto error;
162         }
163
164         result = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
165                                           &lsapipe);
166         if (!NT_STATUS_IS_OK(result)) {
167                 fprintf(stderr, "could not initialise lsa pipe. Error was %s\n", nt_errstr(result) );
168                 goto error;
169         }
170
171         result = rpccli_lsa_open_policy(lsapipe, mem_ctx, True, 
172                                      SEC_FLAG_MAXIMUM_ALLOWED,
173                                      &pol);
174         if (!NT_STATUS_IS_OK(result)) {
175                 goto error;
176         }
177
178         result = rpccli_lsa_QueryInfoPolicy(lsapipe, mem_ctx,
179                                             &pol,
180                                             LSA_POLICY_INFO_ACCOUNT_DOMAIN,
181                                             &info);
182         if (!NT_STATUS_IS_OK(result)) {
183                 goto error;
184         }
185
186         got_domain_sid = True;
187         sid_copy(&domain_sid, info->account_domain.sid);
188
189         rpccli_lsa_Close(lsapipe, mem_ctx, &pol);
190         TALLOC_FREE(lsapipe);
191         talloc_destroy(mem_ctx);
192
193         return;
194
195  error:
196
197         if (lsapipe) {
198                 TALLOC_FREE(lsapipe);
199         }
200
201         fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
202
203         if (!NT_STATUS_IS_OK(result)) {
204                 fprintf(stderr, "error: %s\n", nt_errstr(result));
205         }
206
207         exit(1);
208 }
209
210 /* List the available commands on a given pipe */
211
212 static NTSTATUS cmd_listcommands(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
213                                  int argc, const char **argv)
214 {
215         struct cmd_list *tmp;
216         struct cmd_set *tmp_set;
217         int i;
218
219         /* Usage */
220
221         if (argc != 2) {
222                 printf("Usage: %s <pipe>\n", argv[0]);
223                 return NT_STATUS_OK;
224         }
225
226         /* Help on one command */
227
228         for (tmp = cmd_list; tmp; tmp = tmp->next) 
229         {
230                 tmp_set = tmp->cmd_set;
231
232                 if (!StrCaseCmp(argv[1], tmp_set->name))
233                 {
234                         printf("Available commands on the %s pipe:\n\n", tmp_set->name);
235
236                         i = 0;
237                         tmp_set++;
238                         while(tmp_set->name) {
239                                 printf("%30s", tmp_set->name);
240                                 tmp_set++;
241                                 i++;
242                                 if (i%3 == 0)
243                                         printf("\n");
244                         }
245
246                         /* drop out of the loop */
247                         break;
248                 }
249         }
250         printf("\n\n");
251
252         return NT_STATUS_OK;
253 }
254
255 /* Display help on commands */
256
257 static NTSTATUS cmd_help(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
258                          int argc, const char **argv)
259 {
260         struct cmd_list *tmp;
261         struct cmd_set *tmp_set;
262
263         /* Usage */
264
265         if (argc > 2) {
266                 printf("Usage: %s [command]\n", argv[0]);
267                 return NT_STATUS_OK;
268         }
269
270         /* Help on one command */
271
272         if (argc == 2) {
273                 for (tmp = cmd_list; tmp; tmp = tmp->next) {
274
275                         tmp_set = tmp->cmd_set;
276
277                         while(tmp_set->name) {
278                                 if (strequal(argv[1], tmp_set->name)) {
279                                         if (tmp_set->usage &&
280                                             tmp_set->usage[0])
281                                                 printf("%s\n", tmp_set->usage);
282                                         else
283                                                 printf("No help for %s\n", tmp_set->name);
284
285                                         return NT_STATUS_OK;
286                                 }
287
288                                 tmp_set++;
289                         }
290                 }
291
292                 printf("No such command: %s\n", argv[1]);
293                 return NT_STATUS_OK;
294         }
295
296         /* List all commands */
297
298         for (tmp = cmd_list; tmp; tmp = tmp->next) {
299
300                 tmp_set = tmp->cmd_set;
301
302                 while(tmp_set->name) {
303
304                         printf("%15s\t\t%s\n", tmp_set->name,
305                                tmp_set->description ? tmp_set->description:
306                                "");
307
308                         tmp_set++;
309                 }
310         }
311
312         return NT_STATUS_OK;
313 }
314
315 /* Change the debug level */
316
317 static NTSTATUS cmd_debuglevel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
318                                int argc, const char **argv)
319 {
320         if (argc > 2) {
321                 printf("Usage: %s [debuglevel]\n", argv[0]);
322                 return NT_STATUS_OK;
323         }
324
325         if (argc == 2) {
326                 DEBUGLEVEL = atoi(argv[1]);
327         }
328
329         printf("debuglevel is %d\n", DEBUGLEVEL);
330
331         return NT_STATUS_OK;
332 }
333
334 static NTSTATUS cmd_quit(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
335                          int argc, const char **argv)
336 {
337         exit(0);
338         return NT_STATUS_OK; /* NOTREACHED */
339 }
340
341 static NTSTATUS cmd_set_ss_level(void)
342 {
343         struct cmd_list *tmp;
344
345         /* Close any existing connections not at this level. */
346
347         for (tmp = cmd_list; tmp; tmp = tmp->next) {
348                 struct cmd_set *tmp_set;
349
350                 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
351                         if (tmp_set->rpc_pipe == NULL) {
352                                 continue;
353                         }
354
355                         if ((tmp_set->rpc_pipe->auth->auth_type
356                              != pipe_default_auth_type)
357                             || (tmp_set->rpc_pipe->auth->auth_level
358                                 != pipe_default_auth_level)) {
359                                 TALLOC_FREE(tmp_set->rpc_pipe);
360                                 tmp_set->rpc_pipe = NULL;
361                         }
362                 }
363         }
364         return NT_STATUS_OK;
365 }
366
367 static NTSTATUS cmd_set_transport(void)
368 {
369         struct cmd_list *tmp;
370
371         /* Close any existing connections not at this level. */
372
373         for (tmp = cmd_list; tmp; tmp = tmp->next) {
374                 struct cmd_set *tmp_set;
375
376                 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
377                         if (tmp_set->rpc_pipe == NULL) {
378                                 continue;
379                         }
380
381                         if (tmp_set->rpc_pipe->transport->transport != default_transport) {
382                                 TALLOC_FREE(tmp_set->rpc_pipe);
383                                 tmp_set->rpc_pipe = NULL;
384                         }
385                 }
386         }
387         return NT_STATUS_OK;
388 }
389
390 static NTSTATUS cmd_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
391                          int argc, const char **argv)
392 {
393         const char *p = "[KRB5|KRB5_SPNEGO|NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]";
394         const char *type = "NTLMSSP";
395
396         pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
397         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
398
399         if (argc > 2) {
400                 printf("Usage: %s %s\n", argv[0], p);
401                 return NT_STATUS_OK;
402         }
403
404         if (argc == 2) {
405                 type = argv[1];
406                 if (strequal(type, "KRB5")) {
407                         pipe_default_auth_type = DCERPC_AUTH_TYPE_KRB5;
408                 } else if (strequal(type, "KRB5_SPNEGO")) {
409                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
410                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
411                 } else if (strequal(type, "NTLMSSP")) {
412                         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
413                 } else if (strequal(type, "NTLMSSP_SPNEGO")) {
414                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
415                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
416                 } else if (strequal(type, "SCHANNEL")) {
417                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
418                 } else {
419                         printf("unknown type %s\n", type);
420                         printf("Usage: %s %s\n", argv[0], p);
421                         return NT_STATUS_INVALID_LEVEL;
422                 }
423         }
424
425         d_printf("Setting %s - sign\n", type);
426
427         return cmd_set_ss_level();
428 }
429
430 static NTSTATUS cmd_seal(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
431                          int argc, const char **argv)
432 {
433         const char *p = "[KRB5|KRB5_SPNEGO|NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]";
434         const char *type = "NTLMSSP";
435
436         pipe_default_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
437         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
438
439         if (argc > 2) {
440                 printf("Usage: %s %s\n", argv[0], p);
441                 return NT_STATUS_OK;
442         }
443
444         if (argc == 2) {
445                 type = argv[1];
446                 if (strequal(type, "KRB5")) {
447                         pipe_default_auth_type = DCERPC_AUTH_TYPE_KRB5;
448                 } else if (strequal(type, "KRB5_SPNEGO")) {
449                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
450                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
451                 } else if (strequal(type, "NTLMSSP")) {
452                         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
453                 } else if (strequal(type, "NTLMSSP_SPNEGO")) {
454                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
455                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
456                 } else if (strequal(type, "SCHANNEL")) {
457                         pipe_default_auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
458                 } else {
459                         printf("unknown type %s\n", type);
460                         printf("Usage: %s %s\n", argv[0], p);
461                         return NT_STATUS_INVALID_LEVEL;
462                 }
463         }
464
465         d_printf("Setting %s - sign and seal\n", type);
466
467         return cmd_set_ss_level();
468 }
469
470 static NTSTATUS cmd_timeout(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
471                             int argc, const char **argv)
472 {
473         struct cmd_list *tmp;
474
475         if (argc > 2) {
476                 printf("Usage: %s timeout\n", argv[0]);
477                 return NT_STATUS_OK;
478         }
479
480         if (argc == 2) {
481                 timeout = atoi(argv[1]);
482
483                 for (tmp = cmd_list; tmp; tmp = tmp->next) {
484
485                         struct cmd_set *tmp_set;
486
487                         for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
488                                 if (tmp_set->rpc_pipe == NULL) {
489                                         continue;
490                                 }
491
492                                 rpccli_set_timeout(tmp_set->rpc_pipe, timeout);
493                         }
494                 }
495         }
496
497         printf("timeout is %d\n", timeout);
498
499         return NT_STATUS_OK;
500 }
501
502
503 static NTSTATUS cmd_none(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
504                          int argc, const char **argv)
505 {
506         pipe_default_auth_level = DCERPC_AUTH_LEVEL_NONE;
507         pipe_default_auth_type = DCERPC_AUTH_TYPE_NONE;
508         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NONE;
509
510         return cmd_set_ss_level();
511 }
512
513 static NTSTATUS cmd_schannel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
514                              int argc, const char **argv)
515 {
516         d_printf("Setting schannel - sign and seal\n");
517         pipe_default_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
518         pipe_default_auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
519
520         return cmd_set_ss_level();
521 }
522
523 static NTSTATUS cmd_schannel_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
524                              int argc, const char **argv)
525 {
526         d_printf("Setting schannel - sign only\n");
527         pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
528         pipe_default_auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
529
530         return cmd_set_ss_level();
531 }
532
533 static NTSTATUS cmd_choose_transport(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
534                                      int argc, const char **argv)
535 {
536         NTSTATUS status;
537
538         if (argc != 2) {
539                 printf("Usage: %s [NCACN_NP|NCACN_IP_TCP]\n", argv[0]);
540                 return NT_STATUS_OK;
541         }
542
543         if (strequal(argv[1], "NCACN_NP")) {
544                 default_transport = NCACN_NP;
545         } else if (strequal(argv[1], "NCACN_IP_TCP")) {
546                 default_transport = NCACN_IP_TCP;
547         } else {
548                 printf("transport type: %s unknown or not supported\n", argv[1]);
549                 return NT_STATUS_NOT_SUPPORTED;
550         }
551
552         status = cmd_set_transport();
553         if (!NT_STATUS_IS_OK(status)) {
554                 return status;
555         }
556
557         printf("default transport is now: %s\n", argv[1]);
558
559         return NT_STATUS_OK;
560 }
561
562 /* Built in rpcclient commands */
563
564 static struct cmd_set rpcclient_commands[] = {
565
566         { "GENERAL OPTIONS" },
567
568         { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL,     NULL, NULL,   "Get help on commands", "[command]" },
569         { "?",  RPC_RTYPE_NTSTATUS, cmd_help, NULL,       NULL, NULL,   "Get help on commands", "[command]" },
570         { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   NULL,       NULL, "Set debug level", "level" },
571         { "debug", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   NULL,    NULL, "Set debug level", "level" },
572         { "list",       RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, NULL,       NULL, "List available commands on <pipe>", "pipe" },
573         { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,   NULL,   NULL,   "Exit program", "" },
574         { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,     NULL, NULL, "Exit program", "" },
575         { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL,     NULL, NULL, "Force RPC pipe connections to be signed", "" },
576         { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL,     NULL, NULL, "Force RPC pipe connections to be sealed", "" },
577         { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL,     NULL, NULL,   "Force RPC pipe connections to be sealed with 'schannel'.  Assumes valid machine account to this domain controller.", "" },
578         { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL,    NULL, NULL, "Force RPC pipe connections to be signed (not sealed) with 'schannel'.  Assumes valid machine account to this domain controller.", "" },
579         { "timeout", RPC_RTYPE_NTSTATUS, cmd_timeout, NULL,       NULL, NULL, "Set timeout (in milliseonds) for RPC operations", "" },
580         { "transport", RPC_RTYPE_NTSTATUS, cmd_choose_transport, NULL,    NULL, NULL, "Choose ncacn transport for RPC operations", "" },
581         { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL,     NULL, NULL, "Force RPC pipe connections to have no special properties", "" },
582
583         { NULL }
584 };
585
586 static struct cmd_set separator_command[] = {
587         { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL,   NULL, NULL, "----------------------" },
588         { NULL }
589 };
590
591
592 /* Various pipe commands */
593
594 extern struct cmd_set lsarpc_commands[];
595 extern struct cmd_set samr_commands[];
596 extern struct cmd_set spoolss_commands[];
597 extern struct cmd_set netlogon_commands[];
598 extern struct cmd_set srvsvc_commands[];
599 extern struct cmd_set dfs_commands[];
600 extern struct cmd_set ds_commands[];
601 extern struct cmd_set echo_commands[];
602 extern struct cmd_set epmapper_commands[];
603 extern struct cmd_set shutdown_commands[];
604 extern struct cmd_set test_commands[];
605 extern struct cmd_set wkssvc_commands[];
606 extern struct cmd_set ntsvcs_commands[];
607 extern struct cmd_set drsuapi_commands[];
608 extern struct cmd_set eventlog_commands[];
609 extern struct cmd_set winreg_commands[];
610
611 static struct cmd_set *rpcclient_command_list[] = {
612         rpcclient_commands,
613         lsarpc_commands,
614         ds_commands,
615         samr_commands,
616         spoolss_commands,
617         netlogon_commands,
618         srvsvc_commands,
619         dfs_commands,
620         echo_commands,
621         epmapper_commands,
622         shutdown_commands,
623         test_commands,
624         wkssvc_commands,
625         ntsvcs_commands,
626         drsuapi_commands,
627         eventlog_commands,
628         winreg_commands,
629         NULL
630 };
631
632 static void add_command_set(struct cmd_set *cmd_set)
633 {
634         struct cmd_list *entry;
635
636         if (!(entry = SMB_MALLOC_P(struct cmd_list))) {
637                 DEBUG(0, ("out of memory\n"));
638                 return;
639         }
640
641         ZERO_STRUCTP(entry);
642
643         entry->cmd_set = cmd_set;
644         DLIST_ADD(cmd_list, entry);
645 }
646
647
648 /**
649  * Call an rpcclient function, passing an argv array.
650  *
651  * @param cmd Command to run, as a single string.
652  **/
653 static NTSTATUS do_cmd(struct cli_state *cli,
654                        struct user_auth_info *auth_info,
655                        struct cmd_set *cmd_entry,
656                        struct dcerpc_binding *binding,
657                        int argc, char **argv)
658 {
659         NTSTATUS ntresult;
660         WERROR wresult;
661
662         TALLOC_CTX *mem_ctx;
663
664         /* Create mem_ctx */
665
666         if (!(mem_ctx = talloc_init("do_cmd"))) {
667                 DEBUG(0, ("talloc_init() failed\n"));
668                 return NT_STATUS_NO_MEMORY;
669         }
670
671         /* Open pipe */
672
673         if ((cmd_entry->interface != NULL) && (cmd_entry->rpc_pipe == NULL)) {
674                 switch (pipe_default_auth_type) {
675                 case DCERPC_AUTH_TYPE_NONE:
676                         ntresult = cli_rpc_pipe_open_noauth_transport(
677                                 cli, default_transport,
678                                 cmd_entry->interface,
679                                 &cmd_entry->rpc_pipe);
680                         break;
681                 case DCERPC_AUTH_TYPE_SPNEGO:
682                         switch (pipe_default_auth_spnego_type) {
683                         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
684                                 ntresult = cli_rpc_pipe_open_spnego_ntlmssp(
685                                                 cli, cmd_entry->interface,
686                                                 default_transport,
687                                                 pipe_default_auth_level,
688                                                 get_cmdline_auth_info_domain(auth_info),
689                                                 get_cmdline_auth_info_username(auth_info),
690                                                 get_cmdline_auth_info_password(auth_info),
691                                                 &cmd_entry->rpc_pipe);
692                                 break;
693                         case PIPE_AUTH_TYPE_SPNEGO_KRB5:
694                                 ntresult = cli_rpc_pipe_open_spnego_krb5(
695                                                 cli, cmd_entry->interface,
696                                                 default_transport,
697                                                 pipe_default_auth_level,
698                                                 cli->desthost,
699                                                 NULL, NULL,
700                                                 &cmd_entry->rpc_pipe);
701                                 break;
702                         default:
703                                 ntresult = NT_STATUS_INTERNAL_ERROR;
704                         }
705                         break;
706                 case DCERPC_AUTH_TYPE_NTLMSSP:
707                         ntresult = cli_rpc_pipe_open_ntlmssp(
708                                 cli, cmd_entry->interface,
709                                 default_transport,
710                                 pipe_default_auth_level,
711                                 get_cmdline_auth_info_domain(auth_info),
712                                 get_cmdline_auth_info_username(auth_info),
713                                 get_cmdline_auth_info_password(auth_info),
714                                 &cmd_entry->rpc_pipe);
715                         break;
716                 case DCERPC_AUTH_TYPE_SCHANNEL:
717                         ntresult = cli_rpc_pipe_open_schannel(
718                                 cli, cmd_entry->interface,
719                                 default_transport,
720                                 pipe_default_auth_level,
721                                 get_cmdline_auth_info_domain(auth_info),
722                                 &cmd_entry->rpc_pipe);
723                         break;
724                 case DCERPC_AUTH_TYPE_KRB5:
725                         ntresult = cli_rpc_pipe_open_krb5(
726                                 cli, cmd_entry->interface,
727                                 default_transport,
728                                 pipe_default_auth_level,
729                                 cli->desthost,
730                                 NULL, NULL,
731                                 &cmd_entry->rpc_pipe);
732                         break;
733                 default:
734                         DEBUG(0, ("Could not initialise %s. Invalid "
735                                   "auth type %u\n",
736                                   get_pipe_name_from_syntax(
737                                           talloc_tos(),
738                                           cmd_entry->interface),
739                                   pipe_default_auth_type ));
740                         return NT_STATUS_UNSUCCESSFUL;
741                 }
742                 if (!NT_STATUS_IS_OK(ntresult)) {
743                         DEBUG(0, ("Could not initialise %s. Error was %s\n",
744                                   get_pipe_name_from_syntax(
745                                           talloc_tos(), cmd_entry->interface),
746                                   nt_errstr(ntresult) ));
747                         return ntresult;
748                 }
749
750                 if (ndr_syntax_id_equal(cmd_entry->interface,
751                                         &ndr_table_netlogon.syntax_id)) {
752                         uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
753                         enum netr_SchannelType sec_channel_type;
754                         uchar trust_password[16];
755                         const char *machine_account;
756
757                         if (!get_trust_pw_hash(get_cmdline_auth_info_domain(auth_info),
758                                                trust_password, &machine_account,
759                                                &sec_channel_type))
760                         {
761                                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
762                         }
763
764                         ntresult = rpccli_netlogon_setup_creds(cmd_entry->rpc_pipe,
765                                                 cli->desthost,   /* server name */
766                                                 get_cmdline_auth_info_domain(auth_info),  /* domain */
767                                                 global_myname(), /* client name */
768                                                 machine_account, /* machine account name */
769                                                 trust_password,
770                                                 sec_channel_type,
771                                                 &neg_flags);
772
773                         if (!NT_STATUS_IS_OK(ntresult)) {
774                                 DEBUG(0, ("Could not initialise credentials for %s.\n",
775                                           get_pipe_name_from_syntax(
776                                                   talloc_tos(),
777                                                   cmd_entry->interface)));
778                                 return ntresult;
779                         }
780                 }
781         }
782
783         /* Run command */
784
785         if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) {
786                 ntresult = cmd_entry->ntfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv);
787                 if (!NT_STATUS_IS_OK(ntresult)) {
788                         printf("result was %s\n", nt_errstr(ntresult));
789                 }
790         } else {
791                 wresult = cmd_entry->wfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv);
792                 /* print out the DOS error */
793                 if (!W_ERROR_IS_OK(wresult)) {
794                         printf( "result was %s\n", win_errstr(wresult));
795                 }
796                 ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
797         }
798
799         /* Cleanup */
800
801         talloc_destroy(mem_ctx);
802
803         return ntresult;
804 }
805
806
807 /**
808  * Process a command entered at the prompt or as part of -c
809  *
810  * @returns The NTSTATUS from running the command.
811  **/
812 static NTSTATUS process_cmd(struct user_auth_info *auth_info,
813                             struct cli_state *cli,
814                             struct dcerpc_binding *binding,
815                             char *cmd)
816 {
817         struct cmd_list *temp_list;
818         NTSTATUS result = NT_STATUS_OK;
819         int ret;
820         int argc;
821         char **argv = NULL;
822
823         if ((ret = poptParseArgvString(cmd, &argc, (const char ***) &argv)) != 0) {
824                 fprintf(stderr, "rpcclient: %s\n", poptStrerror(ret));
825                 return NT_STATUS_UNSUCCESSFUL;
826         }
827
828
829         /* Walk through a dlist of arrays of commands. */
830         for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
831                 struct cmd_set *temp_set = temp_list->cmd_set;
832
833                 while (temp_set->name) {
834                         if (strequal(argv[0], temp_set->name)) {
835                                 if (!(temp_set->returntype == RPC_RTYPE_NTSTATUS && temp_set->ntfn ) &&
836                          !(temp_set->returntype == RPC_RTYPE_WERROR && temp_set->wfn )) {
837                                         fprintf (stderr, "Invalid command\n");
838                                         goto out_free;
839                                 }
840
841                                 result = do_cmd(cli, auth_info, temp_set,
842                                                 binding, argc, argv);
843
844                                 goto out_free;
845                         }
846                         temp_set++;
847                 }
848         }
849
850         if (argv[0]) {
851                 printf("command not found: %s\n", argv[0]);
852         }
853
854 out_free:
855 /* moved to do_cmd()
856         if (!NT_STATUS_IS_OK(result)) {
857                 printf("result was %s\n", nt_errstr(result));
858         }
859 */
860
861         /* NOTE: popt allocates the whole argv, including the
862          * strings, as a single block.  So a single free is
863          * enough to release it -- we don't free the
864          * individual strings.  rtfm. */
865         free(argv);
866
867         return result;
868 }
869
870
871 /* Main function */
872
873  int main(int argc, char *argv[])
874 {
875         int                     opt;
876         static char             *cmdstr = NULL;
877         const char *server;
878         struct cli_state        *cli = NULL;
879         static char             *opt_ipaddr=NULL;
880         struct cmd_set          **cmd_set;
881         struct sockaddr_storage server_ss;
882         NTSTATUS                nt_status;
883         static int              opt_port = 0;
884         fstring new_workgroup;
885         int result = 0;
886         TALLOC_CTX *frame = talloc_stackframe();
887         uint32_t flags = 0;
888         struct dcerpc_binding *binding = NULL;
889         const char *binding_string = NULL;
890         char *user, *domain, *q;
891
892         /* make sure the vars that get altered (4th field) are in
893            a fixed location or certain compilers complain */
894         poptContext pc;
895         struct poptOption long_options[] = {
896                 POPT_AUTOHELP
897                 {"command",     'c', POPT_ARG_STRING,   &cmdstr, 'c', "Execute semicolon separated cmds", "COMMANDS"},
898                 {"dest-ip", 'I', POPT_ARG_STRING,   &opt_ipaddr, 'I', "Specify destination IP address", "IP"},
899                 {"port", 'p', POPT_ARG_INT,   &opt_port, 'p', "Specify port number", "PORT"},
900                 POPT_COMMON_SAMBA
901                 POPT_COMMON_CONNECTION
902                 POPT_COMMON_CREDENTIALS
903                 POPT_TABLEEND
904         };
905
906         load_case_tables();
907
908         zero_sockaddr(&server_ss);
909
910         setlinebuf(stdout);
911
912         /* the following functions are part of the Samba debugging
913            facilities.  See lib/debug.c */
914         setup_logging("rpcclient", True);
915
916         rpcclient_auth_info = user_auth_info_init(frame);
917         if (rpcclient_auth_info == NULL) {
918                 exit(1);
919         }
920         popt_common_set_auth_info(rpcclient_auth_info);
921
922         /* Parse options */
923
924         pc = poptGetContext("rpcclient", argc, (const char **) argv,
925                             long_options, 0);
926
927         if (argc == 1) {
928                 poptPrintHelp(pc, stderr, 0);
929                 goto done;
930         }
931
932         while((opt = poptGetNextOpt(pc)) != -1) {
933                 switch (opt) {
934
935                 case 'I':
936                         if (!interpret_string_addr(&server_ss,
937                                                 opt_ipaddr,
938                                                 AI_NUMERICHOST)) {
939                                 fprintf(stderr, "%s not a valid IP address\n",
940                                         opt_ipaddr);
941                                 result = 1;
942                                 goto done;
943                         }
944                 }
945         }
946
947         /* Get server as remaining unparsed argument.  Print usage if more
948            than one unparsed argument is present. */
949
950         server = poptGetArg(pc);
951
952         if (!server || poptGetArg(pc)) {
953                 poptPrintHelp(pc, stderr, 0);
954                 result = 1;
955                 goto done;
956         }
957
958         poptFreeContext(pc);
959
960         load_interfaces();
961
962         if (!init_names()) {
963                 result = 1;
964                 goto done;
965         }
966
967         /* save the workgroup...
968
969            FIXME!! do we need to do this for other options as well
970            (or maybe a generic way to keep lp_load() from overwriting
971            everything)?  */
972
973         fstrcpy( new_workgroup, lp_workgroup() );
974
975         /* Load smb.conf file */
976
977         if (!lp_load(get_dyn_CONFIGFILE(),True,False,False,True))
978                 fprintf(stderr, "Can't load %s\n", get_dyn_CONFIGFILE());
979
980         if ( strlen(new_workgroup) != 0 )
981                 set_global_myworkgroup( new_workgroup );
982
983         /*
984          * Get password
985          * from stdin if necessary
986          */
987
988         if (get_cmdline_auth_info_use_machine_account(rpcclient_auth_info) &&
989             !set_cmdline_auth_info_machine_account_creds(rpcclient_auth_info)) {
990                 result = 1;
991                 goto done;
992         }
993
994         set_cmdline_auth_info_getpass(rpcclient_auth_info);
995
996         if ((server[0] == '/' && server[1] == '/') ||
997                         (server[0] == '\\' && server[1] ==  '\\')) {
998                 server += 2;
999         }
1000
1001         nt_status = dcerpc_parse_binding(frame, server, &binding);
1002
1003         if (!NT_STATUS_IS_OK(nt_status)) {
1004
1005                 binding_string = talloc_asprintf(frame, "ncacn_np:%s",
1006                                                  strip_hostname(server));
1007                 if (!binding_string) {
1008                         result = 1;
1009                         goto done;
1010                 }
1011
1012                 nt_status = dcerpc_parse_binding(frame, binding_string, &binding);
1013                 if (!NT_STATUS_IS_OK(nt_status)) {
1014                         result = -1;
1015                         goto done;
1016                 }
1017         }
1018
1019         if (binding->transport == NCA_UNKNOWN) {
1020                 binding->transport = NCACN_NP;
1021         }
1022
1023         if (binding->flags & DCERPC_SIGN) {
1024                 pipe_default_auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
1025                 pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
1026         }
1027         if (binding->flags & DCERPC_SEAL) {
1028                 pipe_default_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
1029                 pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
1030         }
1031         if (binding->flags & DCERPC_AUTH_SPNEGO) {
1032                 pipe_default_auth_type = DCERPC_AUTH_TYPE_SPNEGO;
1033                 pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
1034         }
1035         if (binding->flags & DCERPC_AUTH_NTLM) {
1036                 /* If neither Integrity or Privacy are requested then
1037                  * Use just Connect level */
1038                 if (pipe_default_auth_level == DCERPC_AUTH_LEVEL_NONE) {
1039                         pipe_default_auth_level = DCERPC_AUTH_LEVEL_CONNECT;
1040                 }
1041
1042                 if (pipe_default_auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
1043                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
1044                 } else {
1045                         pipe_default_auth_type = DCERPC_AUTH_TYPE_NTLMSSP;
1046                 }
1047         }
1048         if (binding->flags & DCERPC_AUTH_KRB5) {
1049                 /* If neither Integrity or Privacy are requested then
1050                  * Use just Connect level */
1051                 if (pipe_default_auth_level == DCERPC_AUTH_LEVEL_NONE) {
1052                         pipe_default_auth_level = DCERPC_AUTH_LEVEL_CONNECT;
1053                 }
1054
1055                 if (pipe_default_auth_type == DCERPC_AUTH_TYPE_SPNEGO) {
1056                         pipe_default_auth_spnego_type = PIPE_AUTH_TYPE_SPNEGO_KRB5;
1057                 } else {
1058                         pipe_default_auth_type = DCERPC_AUTH_TYPE_KRB5;
1059                 }
1060         }
1061
1062         if (get_cmdline_auth_info_use_kerberos(rpcclient_auth_info)) {
1063                 flags |= CLI_FULL_CONNECTION_USE_KERBEROS |
1064                          CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
1065         }
1066         if (get_cmdline_auth_info_use_ccache(rpcclient_auth_info)) {
1067                 flags |= CLI_FULL_CONNECTION_USE_CCACHE;
1068         }
1069
1070         user = talloc_strdup(frame, get_cmdline_auth_info_username(rpcclient_auth_info));
1071         SMB_ASSERT(user != NULL);
1072         domain = talloc_strdup(frame, lp_workgroup());
1073         SMB_ASSERT(domain != NULL);
1074         set_cmdline_auth_info_domain(rpcclient_auth_info, domain);
1075
1076         if ((q = strchr_m(user,'\\'))) {
1077                 *q = 0;
1078                 set_cmdline_auth_info_domain(rpcclient_auth_info, user);
1079                 set_cmdline_auth_info_username(rpcclient_auth_info, q+1);
1080         }
1081
1082
1083         nt_status = cli_full_connection(&cli, global_myname(), binding->host,
1084                                         opt_ipaddr ? &server_ss : NULL, opt_port,
1085                                         "IPC$", "IPC",
1086                                         get_cmdline_auth_info_username(rpcclient_auth_info),
1087                                         get_cmdline_auth_info_domain(rpcclient_auth_info),
1088                                         get_cmdline_auth_info_password(rpcclient_auth_info),
1089                                         flags,
1090                                         get_cmdline_auth_info_signing_state(rpcclient_auth_info),
1091                                         NULL);
1092
1093         if (!NT_STATUS_IS_OK(nt_status)) {
1094                 DEBUG(0,("Cannot connect to server.  Error was %s\n", nt_errstr(nt_status)));
1095                 result = 1;
1096                 goto done;
1097         }
1098
1099         if (get_cmdline_auth_info_smb_encrypt(rpcclient_auth_info)) {
1100                 nt_status = cli_cm_force_encryption(cli,
1101                                         get_cmdline_auth_info_username(rpcclient_auth_info),
1102                                         get_cmdline_auth_info_password(rpcclient_auth_info),
1103                                         get_cmdline_auth_info_domain(rpcclient_auth_info),
1104                                         "IPC$");
1105                 if (!NT_STATUS_IS_OK(nt_status)) {
1106                         result = 1;
1107                         goto done;
1108                 }
1109         }
1110
1111 #if 0   /* COMMENT OUT FOR TESTING */
1112         memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password));
1113 #endif
1114
1115         /* Load command lists */
1116
1117         timeout = cli_set_timeout(cli, 10000);
1118
1119         cmd_set = rpcclient_command_list;
1120
1121         while(*cmd_set) {
1122                 add_command_set(*cmd_set);
1123                 add_command_set(separator_command);
1124                 cmd_set++;
1125         }
1126
1127         default_transport = binding->transport;
1128
1129         fetch_machine_sid(cli);
1130
1131        /* Do anything specified with -c */
1132         if (cmdstr && cmdstr[0]) {
1133                 char    *cmd;
1134                 char    *p = cmdstr;
1135
1136                 result = 0;
1137
1138                 while((cmd=next_command(&p)) != NULL) {
1139                         NTSTATUS cmd_result = process_cmd(rpcclient_auth_info, cli,
1140                                                           binding, cmd);
1141                         SAFE_FREE(cmd);
1142                         result = NT_STATUS_IS_ERR(cmd_result);
1143                 }
1144
1145                 goto done;
1146         }
1147
1148         /* Loop around accepting commands */
1149
1150         while(1) {
1151                 char *line = NULL;
1152
1153                 line = smb_readline("rpcclient $> ", NULL, completion_fn);
1154
1155                 if (line == NULL)
1156                         break;
1157
1158                 if (line[0] != '\n')
1159                         process_cmd(rpcclient_auth_info, cli, binding, line);
1160                 SAFE_FREE(line);
1161         }
1162
1163 done:
1164         if (cli != NULL) {
1165                 cli_shutdown(cli);
1166         }
1167         TALLOC_FREE(frame);
1168         return result;
1169 }