s3:libsmb: Pass memory context to cli_full_connection_creds()
[samba.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 "../libcli/auth/netlogon_creds_cli.h"
24 #include "rpcclient.h"
25 #include "../libcli/auth/libcli_auth.h"
26 #include "../librpc/gen_ndr/ndr_lsa_c.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 #include "../libcli/security/security.h"
32 #include "passdb.h"
33 #include "libsmb/libsmb.h"
34 #include "auth/gensec/gensec.h"
35 #include "../libcli/smb/smbXcli_base.h"
36 #include "messages.h"
37 #include "cmdline_contexts.h"
38 #include "../librpc/gen_ndr/ndr_samr.h"
39 #include "lib/cmdline/cmdline.h"
40 #include "lib/param/param.h"
41
42 enum pipe_auth_type_spnego {
43         PIPE_AUTH_TYPE_SPNEGO_NONE = 0,
44         PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
45         PIPE_AUTH_TYPE_SPNEGO_KRB5
46 };
47
48 static unsigned int timeout = 10000;
49
50 struct messaging_context *rpcclient_msg_ctx;
51 struct netlogon_creds_cli_context *rpcclient_netlogon_creds;
52 static const char *rpcclient_netlogon_domain;
53
54 /* List to hold groups of commands.
55  *
56  * Commands are defined in a list of arrays: arrays are easy to
57  * statically declare, and lists are easier to dynamically extend.
58  */
59
60 static struct cmd_list {
61         struct cmd_list *prev, *next;
62         struct cmd_set *cmd_set;
63 } *cmd_list;
64
65 /****************************************************************************
66 handle completion of commands for readline
67 ****************************************************************************/
68 static char **completion_fn(const char *text, int start, int end)
69 {
70 #define MAX_COMPLETIONS 1000
71         char **matches;
72         size_t i, count=0;
73         struct cmd_list *commands = cmd_list;
74
75 #if 0   /* JERRY */
76         /* FIXME!!!  -- what to do when completing argument? */
77         /* for words not at the start of the line fallback
78            to filename completion */
79         if (start)
80                 return NULL;
81 #endif
82
83         /* make sure we have a list of valid commands */
84         if (!commands) {
85                 return NULL;
86         }
87
88         matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
89         if (!matches) {
90                 return NULL;
91         }
92
93         matches[count++] = SMB_STRDUP(text);
94         if (!matches[0]) {
95                 SAFE_FREE(matches);
96                 return NULL;
97         }
98
99         while (commands && count < MAX_COMPLETIONS-1) {
100                 if (!commands->cmd_set) {
101                         break;
102                 }
103
104                 for (i=0; commands->cmd_set[i].name; i++) {
105                         if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
106                                 (( commands->cmd_set[i].returntype == RPC_RTYPE_NTSTATUS &&
107                         commands->cmd_set[i].ntfn ) ||
108                       ( commands->cmd_set[i].returntype == RPC_RTYPE_WERROR &&
109                         commands->cmd_set[i].wfn))) {
110                                 matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
111                                 if (!matches[count]) {
112                                         for (i = 0; i < count; i++) {
113                                                 SAFE_FREE(matches[count]);
114                                         }
115                                         SAFE_FREE(matches);
116                                         return NULL;
117                                 }
118                                 count++;
119                         }
120                 }
121                 commands = commands->next;
122         }
123
124         if (count == 2) {
125                 SAFE_FREE(matches[0]);
126                 matches[0] = SMB_STRDUP(matches[1]);
127         }
128         matches[count] = NULL;
129         return matches;
130 }
131
132 static char *next_command (char **cmdstr)
133 {
134         char *command;
135         char                    *p;
136
137         if (!cmdstr || !(*cmdstr))
138                 return NULL;
139
140         p = strchr_m(*cmdstr, ';');
141         if (p)
142                 *p = '\0';
143         command = SMB_STRDUP(*cmdstr);
144         if (p)
145                 *cmdstr = p + 1;
146         else
147                 *cmdstr = NULL;
148
149         return command;
150 }
151
152 static void binding_get_auth_info(
153         const struct dcerpc_binding *b,
154         enum dcerpc_AuthType *_auth_type,
155         enum dcerpc_AuthLevel *_auth_level,
156         enum credentials_use_kerberos *_krb5_state)
157 {
158         uint32_t bflags = dcerpc_binding_get_flags(b);
159         enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
160         enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
161         enum credentials_use_kerberos krb5_state = CRED_USE_KERBEROS_DESIRED;
162
163         if (_krb5_state != NULL) {
164                 krb5_state = *_krb5_state;
165         }
166
167         if (bflags & DCERPC_CONNECT) {
168                 auth_level = DCERPC_AUTH_LEVEL_CONNECT;
169         }
170         if (bflags & DCERPC_PACKET) {
171                 auth_level = DCERPC_AUTH_LEVEL_PACKET;
172         }
173         if (bflags & DCERPC_SIGN) {
174                 auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
175         }
176         if (bflags & DCERPC_SEAL) {
177                 auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
178         }
179
180         if (bflags & DCERPC_SCHANNEL) {
181                 auth_type = DCERPC_AUTH_TYPE_SCHANNEL;
182         }
183
184         if ((auth_level != DCERPC_AUTH_LEVEL_NONE) &&
185             (auth_type == DCERPC_AUTH_TYPE_NONE)) {
186                 auth_type = (krb5_state == CRED_USE_KERBEROS_REQUIRED) ?
187                         DCERPC_AUTH_TYPE_KRB5 : DCERPC_AUTH_TYPE_NTLMSSP;
188         }
189
190         if (bflags & DCERPC_AUTH_SPNEGO) {
191                 auth_type = DCERPC_AUTH_TYPE_SPNEGO;
192
193                 if (bflags & DCERPC_AUTH_NTLM) {
194                         krb5_state = CRED_USE_KERBEROS_DISABLED;
195                 }
196                 if (bflags & DCERPC_AUTH_KRB5) {
197                         krb5_state = CRED_USE_KERBEROS_REQUIRED;
198                 }
199         }
200
201         if (auth_type != DCERPC_AUTH_TYPE_NONE) {
202                 /* If nothing is requested then default to integrity */
203                 if (auth_level == DCERPC_AUTH_LEVEL_NONE) {
204                         auth_level = DCERPC_AUTH_LEVEL_INTEGRITY;
205                 }
206         }
207
208         if (_auth_type != NULL) {
209                 *_auth_type = auth_type;
210         }
211         if (_auth_level != NULL) {
212                 *_auth_level = auth_level;
213         }
214         if (_krb5_state != NULL) {
215                 *_krb5_state = krb5_state;
216         }
217 }
218
219 /* List the available commands on a given pipe */
220
221 static NTSTATUS cmd_listcommands(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
222                                  int argc, const char **argv)
223 {
224         struct cmd_list *tmp;
225         struct cmd_set *tmp_set;
226         int i;
227
228         /* Usage */
229
230         if (argc != 2) {
231                 printf("Usage: %s <pipe>\n", argv[0]);
232                 return NT_STATUS_OK;
233         }
234
235         /* Help on one command */
236
237         for (tmp = cmd_list; tmp; tmp = tmp->next)
238         {
239                 tmp_set = tmp->cmd_set;
240
241                 if (!strcasecmp_m(argv[1], tmp_set->name))
242                 {
243                         printf("Available commands on the %s pipe:\n\n", tmp_set->name);
244
245                         i = 0;
246                         tmp_set++;
247                         while(tmp_set->name) {
248                                 printf("%30s", tmp_set->name);
249                                 tmp_set++;
250                                 i++;
251                                 if (i%3 == 0)
252                                         printf("\n");
253                         }
254
255                         /* drop out of the loop */
256                         break;
257                 }
258         }
259         printf("\n\n");
260
261         return NT_STATUS_OK;
262 }
263
264 /* Display help on commands */
265
266 static NTSTATUS cmd_help(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
267                          int argc, const char **argv)
268 {
269         struct cmd_list *tmp;
270         struct cmd_set *tmp_set;
271
272         /* Usage */
273
274         if (argc > 2) {
275                 printf("Usage: %s [command]\n", argv[0]);
276                 return NT_STATUS_OK;
277         }
278
279         /* Help on one command */
280
281         if (argc == 2) {
282                 for (tmp = cmd_list; tmp; tmp = tmp->next) {
283
284                         tmp_set = tmp->cmd_set;
285
286                         while(tmp_set->name) {
287                                 if (strequal(argv[1], tmp_set->name)) {
288                                         if (tmp_set->usage &&
289                                             tmp_set->usage[0])
290                                                 printf("%s\n", tmp_set->usage);
291                                         else
292                                                 printf("No help for %s\n", tmp_set->name);
293
294                                         return NT_STATUS_OK;
295                                 }
296
297                                 tmp_set++;
298                         }
299                 }
300
301                 printf("No such command: %s\n", argv[1]);
302                 return NT_STATUS_OK;
303         }
304
305         /* List all commands */
306
307         for (tmp = cmd_list; tmp; tmp = tmp->next) {
308
309                 tmp_set = tmp->cmd_set;
310
311                 while(tmp_set->name) {
312
313                         printf("%15s\t\t%s\n", tmp_set->name,
314                                tmp_set->description ? tmp_set->description:
315                                "");
316
317                         tmp_set++;
318                 }
319         }
320
321         return NT_STATUS_OK;
322 }
323
324 /* Change the debug level */
325
326 static NTSTATUS cmd_debuglevel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
327                                int argc, const char **argv)
328 {
329         if (argc > 2) {
330                 printf("Usage: %s [debuglevel]\n", argv[0]);
331                 return NT_STATUS_OK;
332         }
333
334         if (argc == 2) {
335                 struct loadparm_context *lp_ctx = samba_cmdline_get_lp_ctx();
336                 lpcfg_set_cmdline(lp_ctx, "log level", argv[1]);
337         }
338
339         printf("debuglevel is %d\n", DEBUGLEVEL);
340
341         return NT_STATUS_OK;
342 }
343
344 static NTSTATUS cmd_quit(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
345                          int argc, const char **argv)
346 {
347         exit(0);
348         return NT_STATUS_OK; /* NOTREACHED */
349 }
350
351 static NTSTATUS cmd_set_ss_level(struct dcerpc_binding *binding)
352 {
353         struct cmd_list *tmp;
354         enum dcerpc_AuthType auth_type;
355         enum dcerpc_AuthLevel auth_level;
356
357         /* Close any existing connections not at this level. */
358
359         binding_get_auth_info(binding, &auth_type, &auth_level, NULL);
360
361         for (tmp = cmd_list; tmp; tmp = tmp->next) {
362                 struct cmd_set *tmp_set;
363
364                 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
365                         if (tmp_set->rpc_pipe == NULL) {
366                                 continue;
367                         }
368
369                         if ((tmp_set->rpc_pipe->auth->auth_type
370                              != auth_type)
371                             || (tmp_set->rpc_pipe->auth->auth_level
372                                 != auth_level)) {
373                                 TALLOC_FREE(tmp_set->rpc_pipe);
374                                 tmp_set->rpc_pipe = NULL;
375                         }
376                 }
377         }
378         return NT_STATUS_OK;
379 }
380
381 static NTSTATUS cmd_set_transport(struct dcerpc_binding *b)
382 {
383         enum dcerpc_transport_t t = dcerpc_binding_get_transport(b);
384         struct cmd_list *tmp;
385
386         /* Close any existing connections not at this level. */
387
388         for (tmp = cmd_list; tmp; tmp = tmp->next) {
389                 struct cmd_set *tmp_set;
390
391                 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
392                         if (tmp_set->rpc_pipe == NULL) {
393                                 continue;
394                         }
395
396                         if (tmp_set->rpc_pipe->transport->transport != t) {
397                                 TALLOC_FREE(tmp_set->rpc_pipe);
398                                 tmp_set->rpc_pipe = NULL;
399                         }
400                 }
401         }
402         return NT_STATUS_OK;
403 }
404
405 static NTSTATUS binding_reset_auth(struct dcerpc_binding *b)
406 {
407         NTSTATUS status = dcerpc_binding_set_flags(
408                 b,
409                 0,
410                 DCERPC_PACKET|
411                 DCERPC_CONNECT|
412                 DCERPC_SIGN|
413                 DCERPC_SEAL|
414                 DCERPC_SCHANNEL|
415                 DCERPC_AUTH_SPNEGO|
416                 DCERPC_AUTH_KRB5|
417                 DCERPC_AUTH_NTLM);
418         return status;
419 }
420
421 static NTSTATUS binding_set_auth(
422         struct dcerpc_binding *b, const char *level, const char *type)
423 {
424         NTSTATUS status;
425
426         status = binding_reset_auth(b);
427         if (!NT_STATUS_IS_OK(status)) {
428                 return status;
429         }
430
431         if (level != NULL) {
432                 status = dcerpc_binding_set_string_option(b, level, level);
433                 if (!NT_STATUS_IS_OK(status)) {
434                         return status;
435                 }
436         }
437
438         if (strequal(type, "SPNEGO")) {
439                 status = dcerpc_binding_set_string_option(
440                         b, "spnego", "spnego");
441                 return status;
442         }
443         if (strequal(type, "NTLMSSP")) {
444                 status = dcerpc_binding_set_string_option(b, "ntlm", "ntlm");
445                 return status;
446         }
447         if (strequal(type, "NTLMSSP_SPNEGO")) {
448                 status = dcerpc_binding_set_string_option(
449                         b, "spnego", "spnego");
450                 if (!NT_STATUS_IS_OK(status)) {
451                         return status;
452                 }
453                 status = dcerpc_binding_set_string_option(b, "ntlm", "ntlm");
454                 return status;
455         }
456         if (strequal(type, "KRB5")) {
457                 status = dcerpc_binding_set_string_option(b, "krb5", "krb5");
458                 return status;
459         }
460         if (strequal(type, "KRB5_SPNEGO")) {
461                 status = dcerpc_binding_set_string_option(
462                         b, "spnego", "spnego");
463                 if (!NT_STATUS_IS_OK(status)) {
464                         return status;
465                 }
466                 status = dcerpc_binding_set_string_option(b, "krb5", "krb5");
467                 return status;
468         }
469         if (strequal(type, "SCHANNEL")) {
470                 status = dcerpc_binding_set_string_option(
471                         b, "schannel", "schannel");
472                 return status;
473         }
474
475         return NT_STATUS_INVALID_PARAMETER;
476 }
477
478 static NTSTATUS cmd_set_auth(
479         struct dcerpc_binding *binding,
480         const char *level,
481         const char *display,
482         int argc,
483         const char **argv)
484 {
485         const char *p = "[KRB5|KRB5_SPNEGO|NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]";
486         const char *type = "NTLMSSP";
487         NTSTATUS status;
488
489         if (argc > 2) {
490                 printf("Usage: %s %s\n", argv[0], p);
491                 return NT_STATUS_OK;
492         }
493
494         if (argc == 2) {
495                 type = argv[1];
496         }
497
498         status = binding_set_auth(binding, level, type);
499         if (!NT_STATUS_IS_OK(status)) {
500                 printf("Usage: %s %s\n", argv[0], p);
501                 return status;
502         }
503
504         d_printf("Setting %s - %s: %s\n", type, display, nt_errstr(status));
505
506         status = cmd_set_ss_level(binding);
507         return status;
508 }
509
510 static NTSTATUS cmd_sign(
511         struct dcerpc_binding *binding,
512         TALLOC_CTX *mem_ctx,
513         int argc,
514         const char **argv)
515 {
516         NTSTATUS status = cmd_set_auth(binding, "sign", "sign", argc, argv);
517         return status;
518 }
519
520 static NTSTATUS cmd_seal(
521         struct dcerpc_binding *binding,
522         TALLOC_CTX *mem_ctx,
523         int argc,
524         const char **argv)
525 {
526         NTSTATUS status = cmd_set_auth(
527                 binding, "seal", "sign and seal", argc, argv);
528         return status;
529 }
530
531 static NTSTATUS cmd_packet(
532         struct dcerpc_binding *binding,
533         TALLOC_CTX *mem_ctx,
534         int argc,
535         const char **argv)
536 {
537         NTSTATUS status = cmd_set_auth(
538                 binding, "packet", "packet", argc, argv);
539         return status;
540 }
541
542 static NTSTATUS cmd_timeout(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
543                             int argc, const char **argv)
544 {
545         if (argc > 2) {
546                 printf("Usage: %s timeout\n", argv[0]);
547                 return NT_STATUS_OK;
548         }
549
550         if (argc == 2) {
551                 timeout = atoi(argv[1]);
552         }
553
554         printf("timeout is %d\n", timeout);
555
556         return NT_STATUS_OK;
557 }
558
559
560 static NTSTATUS cmd_none(
561         struct dcerpc_binding *binding,
562         TALLOC_CTX *mem_ctx,
563         int argc,
564         const char **argv)
565 {
566         NTSTATUS status = binding_reset_auth(binding);
567         if (!NT_STATUS_IS_OK(status)) {
568                 return status;
569         }
570         status = cmd_set_ss_level(binding);
571         return status;
572 }
573
574 static NTSTATUS cmd_schannel(
575         struct dcerpc_binding *binding,
576         TALLOC_CTX *mem_ctx,
577         int argc,
578         const char **_argv)
579 {
580         const char *argv[] = { "schannel", "SCHANNEL" };
581         NTSTATUS status = cmd_set_auth(
582                 binding, "seal", "sign and seal", 2, argv);
583         return status;
584 }
585
586 static NTSTATUS cmd_schannel_sign(
587         struct dcerpc_binding *binding,
588         TALLOC_CTX *mem_ctx,
589         int argc,
590         const char **_argv)
591 {
592         const char *argv[] = { "schannel_sign", "SCHANNEL" };
593         NTSTATUS status = cmd_set_auth(binding, "sign", "sign only", 2, argv);
594         return status;
595 }
596
597 static NTSTATUS cmd_choose_transport(
598         struct dcerpc_binding *binding,
599         TALLOC_CTX *mem_ctx,
600         int argc,
601         const char **argv)
602 {
603         NTSTATUS status;
604         enum dcerpc_transport_t transport;
605
606         if (argc != 2) {
607                 printf("Usage: %s [NCACN_NP|NCACN_IP_TCP]\n", argv[0]);
608                 return NT_STATUS_OK;
609         }
610
611         transport = dcerpc_transport_by_name(argv[1]);
612         if (transport == NCA_UNKNOWN) {
613                 printf("transport type %s unknown\n", argv[1]);
614                 return NT_STATUS_NOT_SUPPORTED;
615         }
616         if (!((transport == NCACN_IP_TCP) ||
617               (transport == NCACN_NP) ||
618               (transport == NCALRPC))) {
619                 printf("transport %s not supported\n", argv[1]);
620                 return NT_STATUS_NOT_SUPPORTED;
621         }
622
623         status = dcerpc_binding_set_transport(binding, transport);
624         if (!NT_STATUS_IS_OK(status)) {
625                 return status;
626         }
627
628         status = cmd_set_transport(binding);
629         if (!NT_STATUS_IS_OK(status)) {
630                 return status;
631         }
632
633         printf("default transport is now: %s\n", argv[1]);
634
635         return NT_STATUS_OK;
636 }
637
638 /* Built in rpcclient commands */
639
640 static struct cmd_set rpcclient_commands[] = {
641
642         {
643                 .name = "GENERAL OPTIONS",
644         },
645
646         {
647                 .name               = "help",
648                 .returntype         = RPC_RTYPE_NTSTATUS,
649                 .ntfn               = cmd_help,
650                 .description        = "Get help on commands",
651                 .usage              = "[command]",
652         },
653         {
654                 .name               = "?",
655                 .returntype         = RPC_RTYPE_NTSTATUS,
656                 .ntfn               = cmd_help,
657                 .description        = "Get help on commands",
658                 .usage              = "[command]",
659         },
660         {
661                 .name               = "debuglevel",
662                 .returntype         = RPC_RTYPE_NTSTATUS,
663                 .ntfn               = cmd_debuglevel,
664                 .description        = "Set debug level",
665                 .usage              = "level",
666         },
667         {
668                 .name               = "debug",
669                 .returntype         = RPC_RTYPE_NTSTATUS,
670                 .ntfn               = cmd_debuglevel,
671                 .description        = "Set debug level",
672                 .usage              = "level",
673         },
674         {
675                 .name               = "list",
676                 .returntype         = RPC_RTYPE_NTSTATUS,
677                 .ntfn               = cmd_listcommands,
678                 .description        = "List available commands on <pipe>",
679                 .usage              = "pipe",
680         },
681         {
682                 .name               = "exit",
683                 .returntype         = RPC_RTYPE_NTSTATUS,
684                 .ntfn               = cmd_quit,
685                 .description        = "Exit program",
686                 .usage              = "",
687         },
688         {
689                 .name               = "quit",
690                 .returntype         = RPC_RTYPE_NTSTATUS,
691                 .ntfn               = cmd_quit,
692                 .description        = "Exit program",
693                 .usage              = "",
694         },
695         {
696                 .name               = "sign",
697                 .returntype         = RPC_RTYPE_BINDING,
698                 .bfn                = cmd_sign,
699                 .description        = "Force RPC pipe connections to be signed",
700                 .usage              = "",
701         },
702         {
703                 .name               = "seal",
704                 .returntype         = RPC_RTYPE_BINDING,
705                 .bfn                = cmd_seal,
706                 .description        = "Force RPC pipe connections to be sealed",
707                 .usage              = "",
708         },
709         {
710                 .name               = "packet",
711                 .returntype         = RPC_RTYPE_BINDING,
712                 .bfn                = cmd_packet,
713                 .description        = "Force RPC pipe connections with packet authentication level",
714                 .usage              = "",
715         },
716         {
717                 .name               = "schannel",
718                 .returntype         = RPC_RTYPE_BINDING,
719                 .bfn                = cmd_schannel,
720                 .description        = "Force RPC pipe connections to be sealed with 'schannel'. "
721                                       "Assumes valid machine account to this domain controller.",
722                 .usage              = "",
723         },
724         {
725                 .name               = "schannelsign",
726                 .returntype         = RPC_RTYPE_BINDING,
727                 .bfn                = cmd_schannel_sign,
728                 .description        = "Force RPC pipe connections to be signed (not sealed) with "
729                                       "'schannel'.  Assumes valid machine account to this domain "
730                                       "controller.",
731                 .usage              = "",
732         },
733         {
734                 .name               = "timeout",
735                 .returntype         = RPC_RTYPE_NTSTATUS,
736                 .ntfn               = cmd_timeout,
737                 .description        = "Set timeout (in milliseconds) for RPC operations",
738                 .usage              = "",
739         },
740         {
741                 .name               = "transport",
742                 .returntype         = RPC_RTYPE_BINDING,
743                 .bfn                = cmd_choose_transport,
744                 .description        = "Choose ncacn transport for RPC operations",
745                 .usage              = "",
746         },
747         {
748                 .name               = "none",
749                 .returntype         = RPC_RTYPE_BINDING,
750                 .bfn                = cmd_none,
751                 .description        = "Force RPC pipe connections to have no special properties",
752                 .usage              = "",
753         },
754
755         { .name = NULL, },
756 };
757
758 static struct cmd_set separator_command[] = {
759         {
760                 .name               = "---------------",
761                 .returntype         = MAX_RPC_RETURN_TYPE,
762                 .description        = "----------------------"
763         },
764         { .name = NULL, },
765 };
766
767
768 /* Various pipe commands */
769
770 extern struct cmd_set lsarpc_commands[];
771 extern struct cmd_set samr_commands[];
772 extern struct cmd_set spoolss_commands[];
773 extern struct cmd_set iremotewinspool_commands[];
774 extern struct cmd_set netlogon_commands[];
775 extern struct cmd_set srvsvc_commands[];
776 extern struct cmd_set dfs_commands[];
777 extern struct cmd_set ds_commands[];
778 extern struct cmd_set echo_commands[];
779 extern struct cmd_set epmapper_commands[];
780 extern struct cmd_set shutdown_commands[];
781 extern struct cmd_set wkssvc_commands[];
782 extern struct cmd_set ntsvcs_commands[];
783 extern struct cmd_set drsuapi_commands[];
784 extern struct cmd_set eventlog_commands[];
785 extern struct cmd_set winreg_commands[];
786 extern struct cmd_set fss_commands[];
787 extern struct cmd_set witness_commands[];
788 extern struct cmd_set clusapi_commands[];
789 extern struct cmd_set spotlight_commands[];
790 extern struct cmd_set unixinfo_commands[];
791
792 static struct cmd_set *rpcclient_command_list[] = {
793         rpcclient_commands,
794         lsarpc_commands,
795         ds_commands,
796         samr_commands,
797         spoolss_commands,
798         iremotewinspool_commands,
799         netlogon_commands,
800         srvsvc_commands,
801         dfs_commands,
802         echo_commands,
803         epmapper_commands,
804         shutdown_commands,
805         wkssvc_commands,
806         ntsvcs_commands,
807         drsuapi_commands,
808         eventlog_commands,
809         winreg_commands,
810         fss_commands,
811         witness_commands,
812         clusapi_commands,
813         spotlight_commands,
814         unixinfo_commands,
815         NULL
816 };
817
818 static void add_command_set(struct cmd_set *cmd_set)
819 {
820         struct cmd_list *entry;
821
822         if (!(entry = SMB_MALLOC_P(struct cmd_list))) {
823                 DEBUG(0, ("out of memory\n"));
824                 return;
825         }
826
827         ZERO_STRUCTP(entry);
828
829         entry->cmd_set = cmd_set;
830         DLIST_ADD(cmd_list, entry);
831 }
832
833 static NTSTATUS rpccli_ncalrpc_connect(
834         const struct ndr_interface_table *iface,
835         TALLOC_CTX *mem_ctx,
836         struct rpc_pipe_client **prpccli)
837 {
838         struct rpc_pipe_client *rpccli = NULL;
839         struct pipe_auth_data *auth = NULL;
840         NTSTATUS status;
841
842         status = rpc_pipe_open_ncalrpc(mem_ctx, iface, &rpccli);
843         if (!NT_STATUS_IS_OK(status)) {
844                 DBG_DEBUG("rpc_pipe_open_ncalrpc failed: %s\n",
845                           nt_errstr(status));
846                 goto fail;
847         }
848
849         status = rpccli_ncalrpc_bind_data(rpccli, &auth);
850         if (!NT_STATUS_IS_OK(status)) {
851                 DBG_DEBUG("rpccli_ncalrpc_bind_data failed: %s\n",
852                           nt_errstr(status));
853                 goto fail;
854         }
855
856         status = rpc_pipe_bind(rpccli, auth);
857         if (!NT_STATUS_IS_OK(status)) {
858                 DBG_DEBUG("rpc_pipe_bind failed: %s\n", nt_errstr(status));
859                 goto fail;
860         }
861
862         *prpccli = rpccli;
863         return NT_STATUS_OK;
864 fail:
865         TALLOC_FREE(rpccli);
866         return status;
867 }
868 /**
869  * Call an rpcclient function, passing an argv array.
870  *
871  * @param cmd Command to run, as a single string.
872  **/
873 static NTSTATUS do_cmd(struct cli_state *cli,
874                        struct cli_credentials *creds,
875                        struct cmd_set *cmd_entry,
876                        struct dcerpc_binding *binding,
877                        int argc, const char **argv)
878 {
879         NTSTATUS ntresult;
880         WERROR wresult;
881         enum dcerpc_transport_t transport;
882
883         TALLOC_CTX *mem_ctx = talloc_stackframe();
884         const char *remote_name = NULL;
885         const struct sockaddr_storage *remote_sockaddr = NULL;
886         struct sockaddr_storage remote_ss = {
887                 .ss_family = AF_UNSPEC,
888         };
889
890         transport = dcerpc_binding_get_transport(binding);
891
892         if (cli != NULL) {
893                 remote_name = smbXcli_conn_remote_name(cli->conn);
894                 remote_sockaddr = smbXcli_conn_remote_sockaddr(cli->conn);
895         } else {
896                 const char *remote_host =
897                         dcerpc_binding_get_string_option(binding, "host");
898                 remote_name = dcerpc_binding_get_string_option(
899                                 binding, "target_hostname");
900
901                 if (remote_host != NULL) {
902                         bool ok = interpret_string_addr(
903                                 &remote_ss, remote_host, 0);
904                         if (ok) {
905                                 remote_sockaddr = &remote_ss;
906                         }
907                 }
908         }
909
910         /* Open pipe */
911
912         if ((cmd_entry->table != NULL) && (cmd_entry->rpc_pipe == NULL)) {
913                 if (transport == NCALRPC) {
914                         ntresult = rpccli_ncalrpc_connect(
915                                 cmd_entry->table, cli, &cmd_entry->rpc_pipe);
916                         if (!NT_STATUS_IS_OK(ntresult)) {
917                                 TALLOC_FREE(mem_ctx);
918                                 return ntresult;
919                         }
920                 } else {
921                         enum dcerpc_AuthType auth_type;
922                         enum dcerpc_AuthLevel auth_level;
923                         enum credentials_use_kerberos krb5_state =
924                                 cli_credentials_get_kerberos_state(creds);
925
926                         binding_get_auth_info(
927                                 binding, &auth_type, &auth_level, &krb5_state);
928
929                         switch (auth_type) {
930                         case DCERPC_AUTH_TYPE_NONE:
931                                 ntresult = cli_rpc_pipe_open_noauth_transport(
932                                         cli, transport,
933                                         cmd_entry->table,
934                                         remote_name,
935                                         remote_sockaddr,
936                                         &cmd_entry->rpc_pipe);
937                                 break;
938                         case DCERPC_AUTH_TYPE_SPNEGO:
939                         case DCERPC_AUTH_TYPE_NTLMSSP:
940                         case DCERPC_AUTH_TYPE_KRB5:
941                                 cli_credentials_set_kerberos_state(creds,
942                                                                    krb5_state,
943                                                                    CRED_SPECIFIED);
944
945                                 ntresult = cli_rpc_pipe_open_with_creds(
946                                         cli, cmd_entry->table,
947                                         transport,
948                                         auth_type,
949                                         auth_level,
950                                         remote_name,
951                                         remote_sockaddr,
952                                         creds,
953                                         &cmd_entry->rpc_pipe);
954                                 break;
955                         case DCERPC_AUTH_TYPE_SCHANNEL:
956                                 TALLOC_FREE(rpcclient_netlogon_creds);
957                                 ntresult = cli_rpc_pipe_open_schannel(
958                                         cli, rpcclient_msg_ctx,
959                                         cmd_entry->table,
960                                         transport,
961                                         rpcclient_netlogon_domain,
962                                         remote_name,
963                                         remote_sockaddr,
964                                         &cmd_entry->rpc_pipe,
965                                         rpcclient_msg_ctx,
966                                         &rpcclient_netlogon_creds);
967                                 break;
968                         default:
969                                 DEBUG(0, ("Could not initialise %s. Invalid "
970                                           "auth type %u\n",
971                                           cmd_entry->table->name,
972                                           auth_type ));
973                                 talloc_free(mem_ctx);
974                                 return NT_STATUS_UNSUCCESSFUL;
975                         }
976                         if (!NT_STATUS_IS_OK(ntresult)) {
977                                 DBG_ERR("Could not initialise %s. "
978                                         "Error was %s\n",
979                                         cmd_entry->table->name,
980                                         nt_errstr(ntresult));
981                                 talloc_free(mem_ctx);
982                                 return ntresult;
983                         }
984
985                         if (rpcclient_netlogon_creds == NULL &&
986                             cmd_entry->use_netlogon_creds) {
987                                 const char *dc_name =
988                                         cmd_entry->rpc_pipe->desthost;
989                                 const char *domain = rpcclient_netlogon_domain;
990                                 struct cli_credentials *trust_creds = NULL;
991
992                                 ntresult = pdb_get_trust_credentials(
993                                         domain,
994                                         NULL,
995                                         mem_ctx,
996                                         &trust_creds);
997                                 if (!NT_STATUS_IS_OK(ntresult)) {
998                                         DBG_ERR("Failed to fetch trust "
999                                                 "credentials for "
1000                                                 "%s to connect to %s: %s\n",
1001                                                 domain,
1002                                                 cmd_entry->table->name,
1003                                                 nt_errstr(ntresult));
1004                                         TALLOC_FREE(cmd_entry->rpc_pipe);
1005                                         talloc_free(mem_ctx);
1006                                         return ntresult;
1007                                 }
1008
1009                                 ntresult = rpccli_create_netlogon_creds_ctx(
1010                                         trust_creds,
1011                                         dc_name,
1012                                         rpcclient_msg_ctx,
1013                                         rpcclient_msg_ctx,
1014                                         &rpcclient_netlogon_creds);
1015                                 if (!NT_STATUS_IS_OK(ntresult)) {
1016                                         DBG_ERR("Could not initialise "
1017                                                 "credentials for %s.\n",
1018                                                 cmd_entry->table->name);
1019                                         TALLOC_FREE(cmd_entry->rpc_pipe);
1020                                         TALLOC_FREE(mem_ctx);
1021                                         return ntresult;
1022                                 }
1023
1024                                 ntresult = rpccli_setup_netlogon_creds(
1025                                         cli,
1026                                         NCACN_NP,
1027                                         rpcclient_netlogon_creds,
1028                                         false, /* force_reauth */
1029                                         trust_creds);
1030                                 TALLOC_FREE(trust_creds);
1031                                 if (!NT_STATUS_IS_OK(ntresult)) {
1032                                         DBG_ERR("Could not initialise "
1033                                                 "credentials for %s.\n",
1034                                                 cmd_entry->table->name);
1035                                         TALLOC_FREE(cmd_entry->rpc_pipe);
1036                                         TALLOC_FREE(rpcclient_netlogon_creds);
1037                                         TALLOC_FREE(mem_ctx);
1038                                         return ntresult;
1039                                 }
1040                         }
1041                 }
1042         }
1043
1044         /* Set timeout for new connections */
1045         if (cmd_entry->rpc_pipe) {
1046                 rpccli_set_timeout(cmd_entry->rpc_pipe, timeout);
1047         }
1048
1049         /* Run command */
1050
1051         if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) {
1052                 ntresult = cmd_entry->ntfn(cmd_entry->rpc_pipe, mem_ctx, argc, argv);
1053                 if (!NT_STATUS_IS_OK(ntresult)) {
1054                         printf("result was %s\n", nt_errstr(ntresult));
1055                 }
1056         } else if (cmd_entry->returntype == RPC_RTYPE_BINDING) {
1057                 ntresult = cmd_entry->bfn(binding, mem_ctx, argc, argv);
1058                 if (!NT_STATUS_IS_OK(ntresult)) {
1059                         printf("result was %s\n", nt_errstr(ntresult));
1060                 }
1061         } else {
1062                 wresult = cmd_entry->wfn(cmd_entry->rpc_pipe, mem_ctx, argc, argv);
1063                 /* print out the DOS error */
1064                 if (!W_ERROR_IS_OK(wresult)) {
1065                         printf( "result was %s\n", win_errstr(wresult));
1066                 }
1067                 ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
1068         }
1069
1070         /* Cleanup */
1071
1072         talloc_free(mem_ctx);
1073
1074         return ntresult;
1075 }
1076
1077
1078 /**
1079  * Process a command entered at the prompt or as part of -c
1080  *
1081  * @returns The NTSTATUS from running the command.
1082  **/
1083 static NTSTATUS process_cmd(struct cli_credentials *creds,
1084                             struct cli_state *cli,
1085                             struct dcerpc_binding *binding,
1086                             char *cmd)
1087 {
1088         struct cmd_list *temp_list;
1089         NTSTATUS result = NT_STATUS_OK;
1090         int ret;
1091         int argc;
1092         const char **argv = NULL;
1093
1094         if ((ret = poptParseArgvString(cmd, &argc, &argv)) != 0) {
1095                 fprintf(stderr, "rpcclient: %s\n", poptStrerror(ret));
1096                 return NT_STATUS_UNSUCCESSFUL;
1097         }
1098
1099
1100         /* Walk through a dlist of arrays of commands. */
1101         for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
1102                 struct cmd_set *set = temp_list->cmd_set;
1103
1104                 while (set->name != NULL) {
1105                         if (!strequal(argv[0], set->name)) {
1106                                 set += 1;
1107                                 continue;
1108                         }
1109
1110                         if (((set->returntype == RPC_RTYPE_NTSTATUS) &&
1111                              (set->ntfn == NULL)) ||
1112                             ((set->returntype == RPC_RTYPE_WERROR) &&
1113                              (set->wfn == NULL)) ||
1114                             ((set->returntype == RPC_RTYPE_BINDING) &&
1115                              (set->bfn == NULL))) {
1116                                 fprintf (stderr, "Invalid command\n");
1117                                 goto out_free;
1118                         }
1119
1120                         result = do_cmd(
1121                                 cli, creds, set, binding, argc, argv);
1122                         goto out_free;
1123                 }
1124         }
1125
1126         if (argv[0]) {
1127                 printf("command not found: %s\n", argv[0]);
1128         }
1129
1130 out_free:
1131 /* moved to do_cmd()
1132         if (!NT_STATUS_IS_OK(result)) {
1133                 printf("result was %s\n", nt_errstr(result));
1134         }
1135 */
1136
1137         /* NOTE: popt allocates the whole argv, including the
1138          * strings, as a single block.  So a single free is
1139          * enough to release it -- we don't free the
1140          * individual strings.  rtfm. */
1141         free(argv);
1142
1143         return result;
1144 }
1145
1146
1147 /* Main function */
1148
1149  int main(int argc, char *argv[])
1150 {
1151         const char **const_argv = discard_const_p(const char *, argv);
1152         int                     opt;
1153         static char             *cmdstr = NULL;
1154         const char *server;
1155         struct cli_state        *cli = NULL;
1156         static char             *opt_ipaddr=NULL;
1157         struct cmd_set          **cmd_set;
1158         struct sockaddr_storage server_ss;
1159         NTSTATUS                nt_status;
1160         static int              opt_port = 0;
1161         int result = 0;
1162         TALLOC_CTX *frame = talloc_stackframe();
1163         uint32_t flags = CLI_FULL_CONNECTION_IPC;
1164         struct dcerpc_binding *binding = NULL;
1165         enum dcerpc_transport_t transport;
1166         const char *binding_string = NULL;
1167         const char *host;
1168         struct cli_credentials *creds = NULL;
1169         struct loadparm_context *lp_ctx = NULL;
1170         bool ok;
1171
1172         /* make sure the vars that get altered (4th field) are in
1173            a fixed location or certain compilers complain */
1174         poptContext pc;
1175         struct poptOption long_options[] = {
1176                 POPT_AUTOHELP
1177                 {"command",     'c', POPT_ARG_STRING,   &cmdstr, 'c', "Execute semicolon separated cmds", "COMMANDS"},
1178                 {"dest-ip", 'I', POPT_ARG_STRING,   &opt_ipaddr, 'I', "Specify destination IP address", "IP"},
1179                 {"port", 'p', POPT_ARG_INT,   &opt_port, 'p', "Specify port number", "PORT"},
1180                 POPT_COMMON_SAMBA
1181                 POPT_COMMON_CONNECTION
1182                 POPT_COMMON_CREDENTIALS
1183                 POPT_LEGACY_S3
1184                 POPT_COMMON_VERSION
1185                 POPT_TABLEEND
1186         };
1187
1188         smb_init_locale();
1189
1190         zero_sockaddr(&server_ss);
1191
1192         setlinebuf(stdout);
1193
1194         ok = samba_cmdline_init(frame,
1195                                 SAMBA_CMDLINE_CONFIG_CLIENT,
1196                                 false /* require_smbconf */);
1197         if (!ok) {
1198                 DBG_ERR("Failed to init cmdline parser!\n");
1199         }
1200         lp_ctx = samba_cmdline_get_lp_ctx();
1201         lpcfg_set_cmdline(lp_ctx, "log level", "0");
1202
1203         /* Parse options */
1204         pc = samba_popt_get_context(getprogname(),
1205                                     argc,
1206                                     const_argv,
1207                                     long_options,
1208                                     0);
1209         if (pc == NULL) {
1210                 DBG_ERR("Failed to setup popt context!\n");
1211                 exit(1);
1212         }
1213
1214         poptSetOtherOptionHelp(pc, "[OPTION...] BINDING-STRING|HOST\nOptions:");
1215
1216         if (argc == 1) {
1217                 poptPrintHelp(pc, stderr, 0);
1218                 goto done;
1219         }
1220
1221         while((opt = poptGetNextOpt(pc)) != -1) {
1222                 switch (opt) {
1223
1224                 case 'I':
1225                         if (!interpret_string_addr(&server_ss,
1226                                                 opt_ipaddr,
1227                                                 AI_NUMERICHOST)) {
1228                                 fprintf(stderr, "%s not a valid IP address\n",
1229                                         opt_ipaddr);
1230                                 result = 1;
1231                                 goto done;
1232                         }
1233                         break;
1234                 case POPT_ERROR_BADOPT:
1235                         fprintf(stderr, "\nInvalid option %s: %s\n\n",
1236                                 poptBadOption(pc, 0), poptStrerror(opt));
1237                         poptPrintUsage(pc, stderr, 0);
1238                         exit(1);
1239                 }
1240         }
1241
1242         /* Get server as remaining unparsed argument.  Print usage if more
1243            than one unparsed argument is present. */
1244
1245         server = talloc_strdup(frame, poptGetArg(pc));
1246
1247         if (!server || poptGetArg(pc)) {
1248                 poptPrintHelp(pc, stderr, 0);
1249                 result = 1;
1250                 goto done;
1251         }
1252
1253         poptFreeContext(pc);
1254         samba_cmdline_burn(argc, argv);
1255
1256         rpcclient_msg_ctx = cmdline_messaging_context(get_dyn_CONFIGFILE());
1257         creds = samba_cmdline_get_creds();
1258
1259         /*
1260          * Get password
1261          * from stdin if necessary
1262          */
1263
1264         if ((server[0] == '/' && server[1] == '/') ||
1265                         (server[0] == '\\' && server[1] ==  '\\')) {
1266                 server += 2;
1267         }
1268
1269         nt_status = dcerpc_parse_binding(frame, server, &binding);
1270
1271         if (!NT_STATUS_IS_OK(nt_status)) {
1272
1273                 binding_string = talloc_asprintf(frame, "ncacn_np:%s",
1274                                                  strip_hostname(server));
1275                 if (!binding_string) {
1276                         result = 1;
1277                         goto done;
1278                 }
1279
1280                 nt_status = dcerpc_parse_binding(frame, binding_string, &binding);
1281                 if (!NT_STATUS_IS_OK(nt_status)) {
1282                         result = -1;
1283                         goto done;
1284                 }
1285         }
1286
1287         transport = dcerpc_binding_get_transport(binding);
1288
1289         if (transport == NCA_UNKNOWN) {
1290                 transport = NCACN_NP;
1291                 nt_status = dcerpc_binding_set_transport(binding, transport);
1292                 if (!NT_STATUS_IS_OK(nt_status)) {
1293                         result = -1;
1294                         goto done;
1295                 }
1296         }
1297
1298         host = dcerpc_binding_get_string_option(binding, "host");
1299
1300         rpcclient_netlogon_domain = cli_credentials_get_domain(creds);
1301         if (rpcclient_netlogon_domain == NULL ||
1302             rpcclient_netlogon_domain[0] == '\0')
1303         {
1304                 rpcclient_netlogon_domain = lp_workgroup();
1305         }
1306
1307         if (transport == NCACN_NP) {
1308                 nt_status = cli_full_connection_creds(frame,
1309                                                       &cli,
1310                                                       lp_netbios_name(),
1311                                                       host,
1312                                                       opt_ipaddr ? &server_ss
1313                                                                  : NULL,
1314                                                       opt_port,
1315                                                       "IPC$",
1316                                                       "IPC",
1317                                                       creds,
1318                                                       flags);
1319
1320                 if (!NT_STATUS_IS_OK(nt_status)) {
1321                         DEBUG(0, ("Cannot connect to server.  Error was %s\n",
1322                                   nt_errstr(nt_status)));
1323                         result = 1;
1324                         goto done;
1325                 }
1326
1327                 /* Load command lists */
1328                 cli_set_timeout(cli, timeout);
1329         }
1330
1331 #if 0   /* COMMENT OUT FOR TESTING */
1332         memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password));
1333 #endif
1334
1335         cmd_set = rpcclient_command_list;
1336
1337         while(*cmd_set) {
1338                 add_command_set(*cmd_set);
1339                 add_command_set(separator_command);
1340                 cmd_set++;
1341         }
1342
1343        /* Do anything specified with -c */
1344         if (cmdstr && cmdstr[0]) {
1345                 char    *cmd;
1346                 char    *p = cmdstr;
1347
1348                 result = 0;
1349
1350                 while((cmd=next_command(&p)) != NULL) {
1351                         NTSTATUS cmd_result = process_cmd(creds,
1352                                                           cli,
1353                                                           binding,
1354                                                           cmd);
1355                         SAFE_FREE(cmd);
1356                         result = NT_STATUS_IS_ERR(cmd_result);
1357                 }
1358
1359                 goto done;
1360         }
1361
1362         /* Loop around accepting commands */
1363
1364         while(1) {
1365                 char *line = NULL;
1366
1367                 line = smb_readline("rpcclient $> ", NULL, completion_fn);
1368
1369                 if (line == NULL) {
1370                         printf("\n");
1371                         break;
1372                 }
1373
1374                 if (line[0] != '\n')
1375                         process_cmd(creds,
1376                                     cli,
1377                                     binding,
1378                                     line);
1379                 SAFE_FREE(line);
1380         }
1381
1382 done:
1383         if (cli != NULL) {
1384                 cli_shutdown(cli);
1385         }
1386         netlogon_creds_cli_close_global_db();
1387         TALLOC_FREE(rpcclient_msg_ctx);
1388         TALLOC_FREE(frame);
1389         return result;
1390 }