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