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