r23372: Remove restriction on string length for rpcclient commands.
[ira/wip.git] / source3 / rpcclient / rpcclient.c
1 /* 
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4
5    Copyright (C) Tim Potter 2000-2001
6    Copyright (C) Martin Pool 2003
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "rpcclient.h"
25
26 DOM_SID domain_sid;
27
28 static enum pipe_auth_type pipe_default_auth_type = PIPE_AUTH_TYPE_NONE;
29 static enum pipe_auth_level pipe_default_auth_level = PIPE_AUTH_LEVEL_NONE;
30 static unsigned int timeout = 0;
31
32 /* List to hold groups of commands.
33  *
34  * Commands are defined in a list of arrays: arrays are easy to
35  * statically declare, and lists are easier to dynamically extend.
36  */
37
38 static struct cmd_list {
39         struct cmd_list *prev, *next;
40         struct cmd_set *cmd_set;
41 } *cmd_list;
42
43 /****************************************************************************
44 handle completion of commands for readline
45 ****************************************************************************/
46 static char **completion_fn(const char *text, int start, int end)
47 {
48 #define MAX_COMPLETIONS 100
49         char **matches;
50         int i, count=0;
51         struct cmd_list *commands = cmd_list;
52
53 #if 0   /* JERRY */
54         /* FIXME!!!  -- what to do when completing argument? */
55         /* for words not at the start of the line fallback 
56            to filename completion */
57         if (start) 
58                 return NULL;
59 #endif
60
61         /* make sure we have a list of valid commands */
62         if (!commands) {
63                 return NULL;
64         }
65
66         matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
67         if (!matches) {
68                 return NULL;
69         }
70
71         matches[count++] = SMB_STRDUP(text);
72         if (!matches[0]) {
73                 SAFE_FREE(matches);
74                 return NULL;
75         }
76
77         while (commands && count < MAX_COMPLETIONS-1) {
78                 if (!commands->cmd_set) {
79                         break;
80                 }
81                 
82                 for (i=0; commands->cmd_set[i].name; i++) {
83                         if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
84                                 (( commands->cmd_set[i].returntype == RPC_RTYPE_NTSTATUS &&
85                         commands->cmd_set[i].ntfn ) || 
86                       ( commands->cmd_set[i].returntype == RPC_RTYPE_WERROR &&
87                         commands->cmd_set[i].wfn))) {
88                                 matches[count] = SMB_STRDUP(commands->cmd_set[i].name);
89                                 if (!matches[count]) {
90                                         for (i = 0; i < count; i++) {
91                                                 SAFE_FREE(matches[count]);
92                                         }
93                                         SAFE_FREE(matches);
94                                         return NULL;
95                                 }
96                                 count++;
97                         }
98                 }
99                 commands = commands->next;
100                 
101         }
102
103         if (count == 2) {
104                 SAFE_FREE(matches[0]);
105                 matches[0] = SMB_STRDUP(matches[1]);
106         }
107         matches[count] = NULL;
108         return matches;
109 }
110
111 static char *next_command (char **cmdstr)
112 {
113         char *command;
114         char                    *p;
115         
116         if (!cmdstr || !(*cmdstr))
117                 return NULL;
118         
119         p = strchr_m(*cmdstr, ';');
120         if (p)
121                 *p = '\0';
122         command = SMB_STRDUP(*cmdstr);
123         if (p)
124                 *cmdstr = p + 1;
125         else
126                 *cmdstr = NULL;
127         
128         return command;
129 }
130
131 /* Fetch the SID for this computer */
132
133 static void fetch_machine_sid(struct cli_state *cli)
134 {
135         POLICY_HND pol;
136         NTSTATUS result = NT_STATUS_OK;
137         uint32 info_class = 5;
138         char *domain_name = NULL;
139         static BOOL got_domain_sid;
140         TALLOC_CTX *mem_ctx;
141         DOM_SID *dom_sid = NULL;
142         struct rpc_pipe_client *lsapipe = NULL;
143
144         if (got_domain_sid) return;
145
146         if (!(mem_ctx=talloc_init("fetch_machine_sid"))) {
147                 DEBUG(0,("fetch_machine_sid: talloc_init returned NULL!\n"));
148                 goto error;
149         }
150
151         if ((lsapipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result)) == NULL) {
152                 fprintf(stderr, "could not initialise lsa pipe. Error was %s\n", nt_errstr(result) );
153                 goto error;
154         }
155         
156         result = rpccli_lsa_open_policy(lsapipe, mem_ctx, True, 
157                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
158                                      &pol);
159         if (!NT_STATUS_IS_OK(result)) {
160                 goto error;
161         }
162
163         result = rpccli_lsa_query_info_policy(lsapipe, mem_ctx, &pol, info_class, 
164                                            &domain_name, &dom_sid);
165         if (!NT_STATUS_IS_OK(result)) {
166                 goto error;
167         }
168
169         got_domain_sid = True;
170         sid_copy( &domain_sid, dom_sid );
171
172         rpccli_lsa_Close(lsapipe, mem_ctx, &pol);
173         cli_rpc_pipe_close(lsapipe);
174         talloc_destroy(mem_ctx);
175
176         return;
177
178  error:
179
180         if (lsapipe) {
181                 cli_rpc_pipe_close(lsapipe);
182         }
183
184         fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
185
186         if (!NT_STATUS_IS_OK(result)) {
187                 fprintf(stderr, "error: %s\n", nt_errstr(result));
188         }
189
190         exit(1);
191 }
192
193 /* List the available commands on a given pipe */
194
195 static NTSTATUS cmd_listcommands(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
196                                  int argc, const char **argv)
197 {
198         struct cmd_list *tmp;
199         struct cmd_set *tmp_set;
200         int i;
201
202         /* Usage */
203
204         if (argc != 2) {
205                 printf("Usage: %s <pipe>\n", argv[0]);
206                 return NT_STATUS_OK;
207         }
208
209         /* Help on one command */
210
211         for (tmp = cmd_list; tmp; tmp = tmp->next) 
212         {
213                 tmp_set = tmp->cmd_set;
214                 
215                 if (!StrCaseCmp(argv[1], tmp_set->name))
216                 {
217                         printf("Available commands on the %s pipe:\n\n", tmp_set->name);
218
219                         i = 0;
220                         tmp_set++;
221                         while(tmp_set->name) {
222                                 printf("%30s", tmp_set->name);
223                                 tmp_set++;
224                                 i++;
225                                 if (i%3 == 0)
226                                         printf("\n");
227                         }
228                         
229                         /* drop out of the loop */
230                         break;
231                 }
232         }
233         printf("\n\n");
234
235         return NT_STATUS_OK;
236 }
237
238 /* Display help on commands */
239
240 static NTSTATUS cmd_help(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
241                          int argc, const char **argv)
242 {
243         struct cmd_list *tmp;
244         struct cmd_set *tmp_set;
245
246         /* Usage */
247
248         if (argc > 2) {
249                 printf("Usage: %s [command]\n", argv[0]);
250                 return NT_STATUS_OK;
251         }
252
253         /* Help on one command */
254
255         if (argc == 2) {
256                 for (tmp = cmd_list; tmp; tmp = tmp->next) {
257                         
258                         tmp_set = tmp->cmd_set;
259
260                         while(tmp_set->name) {
261                                 if (strequal(argv[1], tmp_set->name)) {
262                                         if (tmp_set->usage &&
263                                             tmp_set->usage[0])
264                                                 printf("%s\n", tmp_set->usage);
265                                         else
266                                                 printf("No help for %s\n", tmp_set->name);
267
268                                         return NT_STATUS_OK;
269                                 }
270
271                                 tmp_set++;
272                         }
273                 }
274
275                 printf("No such command: %s\n", argv[1]);
276                 return NT_STATUS_OK;
277         }
278
279         /* List all commands */
280
281         for (tmp = cmd_list; tmp; tmp = tmp->next) {
282
283                 tmp_set = tmp->cmd_set;
284
285                 while(tmp_set->name) {
286
287                         printf("%15s\t\t%s\n", tmp_set->name,
288                                tmp_set->description ? tmp_set->description:
289                                "");
290
291                         tmp_set++;
292                 }
293         }
294
295         return NT_STATUS_OK;
296 }
297
298 /* Change the debug level */
299
300 static NTSTATUS cmd_debuglevel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
301                                int argc, const char **argv)
302 {
303         if (argc > 2) {
304                 printf("Usage: %s [debuglevel]\n", argv[0]);
305                 return NT_STATUS_OK;
306         }
307
308         if (argc == 2) {
309                 DEBUGLEVEL = atoi(argv[1]);
310         }
311
312         printf("debuglevel is %d\n", DEBUGLEVEL);
313
314         return NT_STATUS_OK;
315 }
316
317 static NTSTATUS cmd_quit(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
318                          int argc, const char **argv)
319 {
320         exit(0);
321         return NT_STATUS_OK; /* NOTREACHED */
322 }
323
324 static NTSTATUS cmd_set_ss_level(void)
325 {
326         struct cmd_list *tmp;
327
328         /* Close any existing connections not at this level. */
329
330         for (tmp = cmd_list; tmp; tmp = tmp->next) {
331                 struct cmd_set *tmp_set;
332
333                 for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
334                         if (tmp_set->rpc_pipe == NULL) {
335                                 continue;
336                         }
337
338                         if (tmp_set->rpc_pipe->auth.auth_type != pipe_default_auth_type ||
339                                         tmp_set->rpc_pipe->auth.auth_level != pipe_default_auth_level) {
340                                 cli_rpc_pipe_close(tmp_set->rpc_pipe);
341                                 tmp_set->rpc_pipe = NULL;
342                         }
343                 }
344         }
345         return NT_STATUS_OK;
346 }
347
348 static NTSTATUS cmd_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
349                          int argc, const char **argv)
350 {
351         pipe_default_auth_level = PIPE_AUTH_LEVEL_INTEGRITY;
352         pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
353
354         if (argc > 2) {
355                 printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]);
356                 return NT_STATUS_OK;
357         }
358
359         if (argc == 2) {
360                 if (strequal(argv[1], "NTLMSSP")) {
361                         pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
362                 } else if (strequal(argv[1], "NTLMSSP_SPNEGO")) {
363                         pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
364                 } else if (strequal(argv[1], "SCHANNEL")) {
365                         pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
366                 } else {
367                         printf("unknown type %s\n", argv[1]);
368                         return NT_STATUS_INVALID_LEVEL;
369                 }
370         }
371
372         printf("debuglevel is %d\n", DEBUGLEVEL);
373         return cmd_set_ss_level();
374 }
375
376 static NTSTATUS cmd_seal(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
377                          int argc, const char **argv)
378 {
379         pipe_default_auth_level = PIPE_AUTH_LEVEL_PRIVACY;
380         pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
381
382         if (argc > 2) {
383                 printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]);
384                 return NT_STATUS_OK;
385         }
386
387         if (argc == 2) {
388                 if (strequal(argv[1], "NTLMSSP")) {
389                         pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
390                 } else if (strequal(argv[1], "NTLMSSP_SPNEGO")) {
391                         pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
392                 } else if (strequal(argv[1], "SCHANNEL")) {
393                         pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
394                 } else {
395                         printf("unknown type %s\n", argv[1]);
396                         return NT_STATUS_INVALID_LEVEL;
397                 }
398         }
399         return cmd_set_ss_level();
400 }
401
402 static NTSTATUS cmd_timeout(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
403                             int argc, const char **argv)
404 {
405         struct cmd_list *tmp;
406
407         if (argc > 2) {
408                 printf("Usage: %s timeout\n", argv[0]);
409                 return NT_STATUS_OK;
410         }
411
412         if (argc == 2) {
413                 timeout = atoi(argv[1]);
414
415                 for (tmp = cmd_list; tmp; tmp = tmp->next) {
416                         
417                         struct cmd_set *tmp_set;
418
419                         for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
420                                 if (tmp_set->rpc_pipe == NULL) {
421                                         continue;
422                                 }
423
424                                 cli_set_timeout(tmp_set->rpc_pipe->cli, timeout);
425                         }
426                 }
427         }
428
429         printf("timeout is %d\n", timeout);
430
431         return NT_STATUS_OK;
432 }
433
434
435 static NTSTATUS cmd_none(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
436                          int argc, const char **argv)
437 {
438         pipe_default_auth_level = PIPE_AUTH_LEVEL_NONE;
439         pipe_default_auth_type = PIPE_AUTH_TYPE_NONE;
440
441         return cmd_set_ss_level();
442 }
443
444 static NTSTATUS cmd_schannel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
445                              int argc, const char **argv)
446 {
447         d_printf("Setting schannel - sign and seal\n");
448         pipe_default_auth_level = PIPE_AUTH_LEVEL_PRIVACY;
449         pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
450
451         return cmd_set_ss_level();
452 }
453
454 static NTSTATUS cmd_schannel_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
455                              int argc, const char **argv)
456 {
457         d_printf("Setting schannel - sign only\n");
458         pipe_default_auth_level = PIPE_AUTH_LEVEL_INTEGRITY;
459         pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
460
461         return cmd_set_ss_level();
462 }
463
464
465 /* Built in rpcclient commands */
466
467 static struct cmd_set rpcclient_commands[] = {
468
469         { "GENERAL OPTIONS" },
470
471         { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL,     -1, NULL,     "Get help on commands", "[command]" },
472         { "?",  RPC_RTYPE_NTSTATUS, cmd_help, NULL,       -1, NULL,     "Get help on commands", "[command]" },
473         { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   -1, NULL, "Set debug level", "level" },
474         { "debug", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   -1,      NULL, "Set debug level", "level" },
475         { "list",       RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, -1, NULL, "List available commands on <pipe>", "pipe" },
476         { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,   -1,     NULL,   "Exit program", "" },
477         { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,     -1,   NULL, "Exit program", "" },
478         { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL,     -1,   NULL, "Force RPC pipe connections to be signed", "" },
479         { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL,     -1,   NULL, "Force RPC pipe connections to be sealed", "" },
480         { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL,     -1, NULL,     "Force RPC pipe connections to be sealed with 'schannel'.  Assumes valid machine account to this domain controller.", "" },
481         { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL,    -1, NULL, "Force RPC pipe connections to be signed (not sealed) with 'schannel'.  Assumes valid machine account to this domain controller.", "" },
482         { "timeout", RPC_RTYPE_NTSTATUS, cmd_timeout, NULL,       -1, NULL, "Set timeout (in milliseonds) for RPC operations", "" },
483         { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL,     -1, NULL, "Force RPC pipe connections to have no special properties", "" },
484
485         { NULL }
486 };
487
488 static struct cmd_set separator_command[] = {
489         { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL,   -1, NULL, "----------------------" },
490         { NULL }
491 };
492
493
494 /* Various pipe commands */
495
496 extern struct cmd_set unixinfo_commands[];
497 extern struct cmd_set lsarpc_commands[];
498 extern struct cmd_set samr_commands[];
499 extern struct cmd_set spoolss_commands[];
500 extern struct cmd_set netlogon_commands[];
501 extern struct cmd_set srvsvc_commands[];
502 extern struct cmd_set dfs_commands[];
503 extern struct cmd_set ds_commands[];
504 extern struct cmd_set echo_commands[];
505 extern struct cmd_set shutdown_commands[];
506 extern struct cmd_set test_commands[];
507
508 static struct cmd_set *rpcclient_command_list[] = {
509         rpcclient_commands,
510         unixinfo_commands,
511         lsarpc_commands,
512         ds_commands,
513         samr_commands,
514         spoolss_commands,
515         netlogon_commands,
516         srvsvc_commands,
517         dfs_commands,
518         echo_commands,
519         shutdown_commands,
520         test_commands,
521         NULL
522 };
523
524 static void add_command_set(struct cmd_set *cmd_set)
525 {
526         struct cmd_list *entry;
527
528         if (!(entry = SMB_MALLOC_P(struct cmd_list))) {
529                 DEBUG(0, ("out of memory\n"));
530                 return;
531         }
532
533         ZERO_STRUCTP(entry);
534
535         entry->cmd_set = cmd_set;
536         DLIST_ADD(cmd_list, entry);
537 }
538
539
540 /**
541  * Call an rpcclient function, passing an argv array.
542  *
543  * @param cmd Command to run, as a single string.
544  **/
545 static NTSTATUS do_cmd(struct cli_state *cli,
546                        struct cmd_set *cmd_entry,
547                        int argc, char **argv)
548 {
549         NTSTATUS ntresult;
550         WERROR wresult;
551         
552         TALLOC_CTX *mem_ctx;
553
554         /* Create mem_ctx */
555
556         if (!(mem_ctx = talloc_init("do_cmd"))) {
557                 DEBUG(0, ("talloc_init() failed\n"));
558                 return NT_STATUS_NO_MEMORY;
559         }
560
561         /* Open pipe */
562
563         if (cmd_entry->pipe_idx != -1 && cmd_entry->rpc_pipe == NULL) {
564                 switch (pipe_default_auth_type) {
565                         case PIPE_AUTH_TYPE_NONE:
566                                 cmd_entry->rpc_pipe = cli_rpc_pipe_open_noauth(cli,
567                                                                 cmd_entry->pipe_idx,
568                                                                 &ntresult);
569                                 break;
570                         case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
571                                 cmd_entry->rpc_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli,
572                                                                 cmd_entry->pipe_idx,
573                                                                 pipe_default_auth_level,
574                                                                 lp_workgroup(),
575                                                                 cmdline_auth_info.username,
576                                                                 cmdline_auth_info.password,
577                                                                 &ntresult);
578                                 break;
579                         case PIPE_AUTH_TYPE_NTLMSSP:
580                                 cmd_entry->rpc_pipe = cli_rpc_pipe_open_ntlmssp(cli,
581                                                                 cmd_entry->pipe_idx,
582                                                                 pipe_default_auth_level,
583                                                                 lp_workgroup(),
584                                                                 cmdline_auth_info.username,
585                                                                 cmdline_auth_info.password,
586                                                                 &ntresult);
587                                 break;
588                         case PIPE_AUTH_TYPE_SCHANNEL:
589                                 cmd_entry->rpc_pipe = cli_rpc_pipe_open_schannel(cli,
590                                                                 cmd_entry->pipe_idx,
591                                                                 pipe_default_auth_level,
592                                                                 lp_workgroup(),
593                                                                 &ntresult);
594                                 break;
595                         default:
596                                 DEBUG(0, ("Could not initialise %s. Invalid auth type %u\n",
597                                         cli_get_pipe_name(cmd_entry->pipe_idx),
598                                         pipe_default_auth_type ));
599                                 return NT_STATUS_UNSUCCESSFUL;
600                 }
601                 if (!cmd_entry->rpc_pipe) {
602                         DEBUG(0, ("Could not initialise %s. Error was %s\n",
603                                 cli_get_pipe_name(cmd_entry->pipe_idx),
604                                 nt_errstr(ntresult) ));
605                         return ntresult;
606                 }
607
608                 if (cmd_entry->pipe_idx == PI_NETLOGON) {
609                         uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
610                         uint32 sec_channel_type;
611                         uchar trust_password[16];
612         
613                         if (!secrets_fetch_trust_account_password(lp_workgroup(),
614                                                         trust_password,
615                                                         NULL, &sec_channel_type)) {
616                                 return NT_STATUS_UNSUCCESSFUL;
617                         }
618                 
619                         ntresult = rpccli_netlogon_setup_creds(cmd_entry->rpc_pipe,
620                                                 cli->desthost,   /* server name */
621                                                 lp_workgroup(),  /* domain */
622                                                 global_myname(), /* client name */
623                                                 global_myname(), /* machine account name */
624                                                 trust_password,
625                                                 sec_channel_type,
626                                                 &neg_flags);
627
628                         if (!NT_STATUS_IS_OK(ntresult)) {
629                                 DEBUG(0, ("Could not initialise credentials for %s.\n",
630                                         cli_get_pipe_name(cmd_entry->pipe_idx)));
631                                 return ntresult;
632                         }
633                 }
634         }
635
636         /* Run command */
637
638         if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) {
639                 ntresult = cmd_entry->ntfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv);
640                 if (!NT_STATUS_IS_OK(ntresult)) {
641                         printf("result was %s\n", nt_errstr(ntresult));
642                 }
643         } else {
644                 wresult = cmd_entry->wfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv);
645                 /* print out the DOS error */
646                 if (!W_ERROR_IS_OK(wresult)) {
647                         printf( "result was %s\n", dos_errstr(wresult));
648                 }
649                 ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
650         }
651
652         /* Cleanup */
653
654         talloc_destroy(mem_ctx);
655
656         return ntresult;
657 }
658
659
660 /**
661  * Process a command entered at the prompt or as part of -c
662  *
663  * @returns The NTSTATUS from running the command.
664  **/
665 static NTSTATUS process_cmd(struct cli_state *cli, char *cmd)
666 {
667         struct cmd_list *temp_list;
668         NTSTATUS result = NT_STATUS_OK;
669         int ret;
670         int argc;
671         char **argv = NULL;
672
673         if ((ret = poptParseArgvString(cmd, &argc, (const char ***) &argv)) != 0) {
674                 fprintf(stderr, "rpcclient: %s\n", poptStrerror(ret));
675                 return NT_STATUS_UNSUCCESSFUL;
676         }
677
678
679         /* Walk through a dlist of arrays of commands. */
680         for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
681                 struct cmd_set *temp_set = temp_list->cmd_set;
682
683                 while (temp_set->name) {
684                         if (strequal(argv[0], temp_set->name)) {
685                                 if (!(temp_set->returntype == RPC_RTYPE_NTSTATUS && temp_set->ntfn ) &&
686                          !(temp_set->returntype == RPC_RTYPE_WERROR && temp_set->wfn )) {
687                                         fprintf (stderr, "Invalid command\n");
688                                         goto out_free;
689                                 }
690
691                                 result = do_cmd(cli, temp_set, argc, argv);
692
693                                 goto out_free;
694                         }
695                         temp_set++;
696                 }
697         }
698
699         if (argv[0]) {
700                 printf("command not found: %s\n", argv[0]);
701         }
702
703 out_free:
704 /* moved to do_cmd()
705         if (!NT_STATUS_IS_OK(result)) {
706                 printf("result was %s\n", nt_errstr(result));
707         }
708 */
709
710         /* NOTE: popt allocates the whole argv, including the
711          * strings, as a single block.  So a single free is
712          * enough to release it -- we don't free the
713          * individual strings.  rtfm. */
714         free(argv);
715         
716         return result;
717 }
718
719
720 /* Main function */
721
722  int main(int argc, char *argv[])
723 {
724         int                     opt;
725         static char             *cmdstr = NULL;
726         const char *server;
727         struct cli_state        *cli;
728         static char             *opt_ipaddr=NULL;
729         struct cmd_set          **cmd_set;
730         struct in_addr          server_ip;
731         NTSTATUS                nt_status;
732         static int              opt_port = 0;
733         fstring new_workgroup;
734
735         /* make sure the vars that get altered (4th field) are in
736            a fixed location or certain compilers complain */
737         poptContext pc;
738         struct poptOption long_options[] = {
739                 POPT_AUTOHELP
740                 {"command",     'c', POPT_ARG_STRING,   &cmdstr, 'c', "Execute semicolon separated cmds", "COMMANDS"},
741                 {"dest-ip", 'I', POPT_ARG_STRING,   &opt_ipaddr, 'I', "Specify destination IP address", "IP"},
742                 {"port", 'p', POPT_ARG_INT,   &opt_port, 'p', "Specify port number", "PORT"},
743                 POPT_COMMON_SAMBA
744                 POPT_COMMON_CONNECTION
745                 POPT_COMMON_CREDENTIALS
746                 POPT_TABLEEND
747         };
748
749         load_case_tables();
750
751         ZERO_STRUCT(server_ip);
752
753         setlinebuf(stdout);
754
755         /* the following functions are part of the Samba debugging
756            facilities.  See lib/debug.c */
757         setup_logging("rpcclient", True);
758         
759         /* Parse options */
760
761         pc = poptGetContext("rpcclient", argc, (const char **) argv,
762                             long_options, 0);
763
764         if (argc == 1) {
765                 poptPrintHelp(pc, stderr, 0);
766                 return 0;
767         }
768         
769         while((opt = poptGetNextOpt(pc)) != -1) {
770                 switch (opt) {
771
772                 case 'I':
773                         if ( (server_ip.s_addr=inet_addr(opt_ipaddr)) == INADDR_NONE ) {
774                                 fprintf(stderr, "%s not a valid IP address\n",
775                                         opt_ipaddr);
776                                 return 1;
777                         }
778                 }
779         }
780
781         /* Get server as remaining unparsed argument.  Print usage if more
782            than one unparsed argument is present. */
783
784         server = poptGetArg(pc);
785         
786         if (!server || poptGetArg(pc)) {
787                 poptPrintHelp(pc, stderr, 0);
788                 return 1;
789         }
790
791         poptFreeContext(pc);
792
793         load_interfaces();
794
795         if (!init_names())
796                 return 1;
797
798         /* save the workgroup...
799         
800            FIXME!! do we need to do this for other options as well 
801            (or maybe a generic way to keep lp_load() from overwriting 
802            everything)?  */
803         
804         fstrcpy( new_workgroup, lp_workgroup() );
805
806         /* Load smb.conf file */
807
808         if (!lp_load(dyn_CONFIGFILE,True,False,False,True))
809                 fprintf(stderr, "Can't load %s\n", dyn_CONFIGFILE);
810
811         if ( strlen(new_workgroup) != 0 )
812                 set_global_myworkgroup( new_workgroup );
813
814         /*
815          * Get password
816          * from stdin if necessary
817          */
818
819         if (!cmdline_auth_info.got_pass) {
820                 char *pass = getpass("Password:");
821                 if (pass) {
822                         pstrcpy(cmdline_auth_info.password, pass);
823                 }
824         }
825         
826         if ((server[0] == '/' && server[1] == '/') ||
827                         (server[0] == '\\' && server[1] ==  '\\')) {
828                 server += 2;
829         }
830
831         nt_status = cli_full_connection(&cli, global_myname(), server, 
832                                         opt_ipaddr ? &server_ip : NULL, opt_port,
833                                         "IPC$", "IPC",  
834                                         cmdline_auth_info.username, 
835                                         lp_workgroup(),
836                                         cmdline_auth_info.password, 
837                                         cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
838                                         cmdline_auth_info.signing_state,NULL);
839         
840         if (!NT_STATUS_IS_OK(nt_status)) {
841                 DEBUG(0,("Cannot connect to server.  Error was %s\n", nt_errstr(nt_status)));
842                 return 1;
843         }
844
845 #if 0   /* COMMENT OUT FOR TESTING */
846         memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password));
847 #endif
848
849         /* Load command lists */
850
851         timeout = cli_set_timeout(cli, 10000);
852
853         cmd_set = rpcclient_command_list;
854
855         while(*cmd_set) {
856                 add_command_set(*cmd_set);
857                 add_command_set(separator_command);
858                 cmd_set++;
859         }
860
861         fetch_machine_sid(cli);
862  
863        /* Do anything specified with -c */
864         if (cmdstr && cmdstr[0]) {
865                 char    *cmd;
866                 char    *p = cmdstr;
867                 int result = 0;
868  
869                 while((cmd=next_command(&p)) != NULL) {
870                         NTSTATUS cmd_result = process_cmd(cli, cmd);
871                         SAFE_FREE(cmd);
872                         result = NT_STATUS_IS_ERR(cmd_result);
873                 }
874                 
875                 cli_shutdown(cli);
876                 return result;
877         }
878
879         /* Loop around accepting commands */
880
881         while(1) {
882                 pstring prompt;
883                 char *line;
884
885                 slprintf(prompt, sizeof(prompt) - 1, "rpcclient $> ");
886
887                 line = smb_readline(prompt, NULL, completion_fn);
888
889                 if (line == NULL)
890                         break;
891
892                 if (line[0] != '\n')
893                         process_cmd(cli, line);
894         }
895         
896         cli_shutdown(cli);
897         return 0;
898 }