Removed global debugf. Replaced with lp_set_logfile(name).
[bbaumbach/samba-autobuild/.git] / source3 / rpcclient / rpcclient.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.2
4    RPC pipe client
5
6    Copyright (C) Tim Potter 2000-2001
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 /* List to hold groups of commands */
29
30 static struct cmd_list {
31         struct cmd_list *prev, *next;
32         struct cmd_set *cmd_set;
33 } *cmd_list;
34
35 /****************************************************************************
36 handle completion of commands for readline
37 ****************************************************************************/
38 static char **completion_fn(char *text, int start, int end)
39 {
40 #define MAX_COMPLETIONS 100
41         char **matches;
42         int i, count=0;
43         struct cmd_list *commands = cmd_list;
44
45 #if 0   /* JERRY */
46         /* FIXME!!!  -- what to do when completing argument? */
47         /* for words not at the start of the line fallback 
48            to filename completion */
49         if (start) 
50                 return NULL;
51 #endif
52
53         /* make sure we have a list of valid commands */
54         if (!commands) 
55                 return NULL;
56
57         matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS);
58         if (!matches) return NULL;
59
60         matches[count++] = strdup(text);
61         if (!matches[0]) return NULL;
62
63         while (commands && count < MAX_COMPLETIONS-1) 
64         {
65                 if (!commands->cmd_set)
66                         break;
67                 
68                 for (i=0; commands->cmd_set[i].name; i++)
69                 {
70                         if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
71                                 commands->cmd_set[i].fn) 
72                         {
73                                 matches[count] = strdup(commands->cmd_set[i].name);
74                                 if (!matches[count]) 
75                                         return NULL;
76                                 count++;
77                         }
78                 }
79                 
80                 commands = commands->next;
81                 
82         }
83
84         if (count == 2) {
85                 SAFE_FREE(matches[0]);
86                 matches[0] = strdup(matches[1]);
87         }
88         matches[count] = NULL;
89         return matches;
90 }
91
92 /***********************************************************************
93  * read in username/password credentials from a file
94  */
95 static void read_authfile (
96         char *filename, 
97         char* username, 
98         char* password, 
99         char* domain
100 )
101 {
102         FILE *auth;
103         fstring buf;
104         uint16 len = 0;
105         char *ptr, *val, *param;
106                                
107         if ((auth=sys_fopen(filename, "r")) == NULL)
108         {
109                 printf ("ERROR: Unable to open credentials file!\n");
110                 return;
111         }
112                                 
113         while (!feof(auth))
114         {  
115                 /* get a line from the file */
116                 if (!fgets (buf, sizeof(buf), auth))
117                         continue;
118                 
119                 len = strlen(buf);
120                 
121                 /* skip empty lines */                  
122                 if ((len) && (buf[len-1]=='\n'))
123                 {
124                         buf[len-1] = '\0';
125                         len--;
126                 }       
127                 if (len == 0)
128                         continue;
129                                         
130                 /* break up the line into parameter & value.
131                    will need to eat a little whitespace possibly */
132                 param = buf;
133                 if (!(ptr = strchr_m(buf, '=')))
134                         continue;
135                 val = ptr+1;
136                 *ptr = '\0';
137                                         
138                 /* eat leading white space */
139                 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
140                         val++;
141                                         
142                 if (strwicmp("password", param) == 0)
143                         fstrcpy (password, val);
144                 else if (strwicmp("username", param) == 0)
145                         fstrcpy (username, val);
146                 else if (strwicmp("domain", param) == 0)
147                         fstrcpy (domain, val);
148                                                 
149                 memset(buf, 0, sizeof(buf));
150         }
151         fclose(auth);
152         
153         return;
154 }
155
156 static char* next_command (char** cmdstr)
157 {
158         static pstring          command;
159         char                    *p;
160         
161         if (!cmdstr || !(*cmdstr))
162                 return NULL;
163         
164         p = strchr_m(*cmdstr, ';');
165         if (p)
166                 *p = '\0';
167         pstrcpy(command, *cmdstr);
168         *cmdstr = p;
169         
170         return command;
171 }
172
173 static void get_username (char *username)
174 {
175         if (getenv("USER"))
176                 pstrcpy(username,getenv("USER"));
177  
178         if (*username == 0 && getenv("LOGNAME"))
179                 pstrcpy(username,getenv("LOGNAME"));
180  
181         if (*username == 0) {
182                 pstrcpy(username,"GUEST");
183         }
184
185         return;
186 }
187
188 /* Fetch the SID for this computer */
189
190 void fetch_machine_sid(struct cli_state *cli)
191 {
192         POLICY_HND pol;
193         NTSTATUS result = NT_STATUS_OK;
194         uint32 info_class = 5;
195         fstring domain_name;
196         static BOOL got_domain_sid;
197         TALLOC_CTX *mem_ctx;
198
199         if (got_domain_sid) return;
200
201         if (!(mem_ctx=talloc_init()))
202         {
203                 DEBUG(0,("fetch_domain_sid: talloc_init returned NULL!\n"));
204                 goto error;
205         }
206
207
208         if (!cli_nt_session_open (cli, PIPE_LSARPC)) {
209                 fprintf(stderr, "could not initialise lsa pipe\n");
210                 goto error;
211         }
212         
213         result = cli_lsa_open_policy(cli, mem_ctx, True, 
214                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
215                                      &pol);
216         if (!NT_STATUS_IS_OK(result)) {
217                 goto error;
218         }
219
220         result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, 
221                                            domain_name, &domain_sid);
222         if (!NT_STATUS_IS_OK(result)) {
223                 goto error;
224         }
225
226         got_domain_sid = True;
227
228         cli_lsa_close(cli, mem_ctx, &pol);
229         cli_nt_session_close(cli);
230         talloc_destroy(mem_ctx);
231
232         return;
233
234  error:
235         fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
236
237         if (!NT_STATUS_IS_OK(result)) {
238                 fprintf(stderr, "error: %s\n", get_nt_error_msg(result));
239         }
240
241         exit(1);
242 }
243
244
245 /* Display help on commands */
246
247 static NTSTATUS cmd_help(struct cli_state *cli, TALLOC_CTX *mem_ctx,
248                          int argc, char **argv)
249 {
250         struct cmd_list *tmp;
251         struct cmd_set *tmp_set;
252
253         /* Usage */
254
255         if (argc > 2) {
256                 printf("Usage: %s [command]\n", argv[0]);
257                 return NT_STATUS_OK;
258         }
259
260         /* Help on one command */
261
262         if (argc == 2) {
263                 for (tmp = cmd_list; tmp; tmp = tmp->next) {
264                         
265                         tmp_set = tmp->cmd_set;
266
267                         while(tmp_set->name) {
268                                 if (strequal(argv[1], tmp_set->name)) {
269                                         if (tmp_set->usage &&
270                                             tmp_set->usage[0])
271                                                 printf("%s\n", tmp_set->usage);
272                                         else
273                                                 printf("No help for %s\n", tmp_set->name);
274
275                                         return NT_STATUS_OK;
276                                 }
277
278                                 tmp_set++;
279                         }
280                 }
281
282                 printf("No such command: %s\n", argv[1]);
283                 return NT_STATUS_OK;
284         }
285
286         /* List all commands */
287
288         for (tmp = cmd_list; tmp; tmp = tmp->next) {
289
290                 tmp_set = tmp->cmd_set;
291
292                 while(tmp_set->name) {
293
294                         printf("%15s\t\t%s\n", tmp_set->name,
295                                tmp_set->description);
296
297                         tmp_set++;
298                 }
299         }
300
301         return NT_STATUS_OK;
302 }
303
304 /* Change the debug level */
305
306 static NTSTATUS cmd_debuglevel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
307                                int argc, char **argv)
308 {
309         if (argc > 2) {
310                 printf("Usage: %s [debuglevel]\n", argv[0]);
311                 return NT_STATUS_OK;
312         }
313
314         if (argc == 2) {
315                 DEBUGLEVEL = atoi(argv[1]);
316         }
317
318         printf("debuglevel is %d\n", DEBUGLEVEL);
319
320         return NT_STATUS_OK;
321 }
322
323 static NTSTATUS cmd_quit(struct cli_state *cli, TALLOC_CTX *mem_ctx,
324                          int argc, char **argv)
325 {
326         exit(0);
327         return NT_STATUS_OK; /* NOTREACHED */
328 }
329
330 /* Build in rpcclient commands */
331
332 static struct cmd_set rpcclient_commands[] = {
333
334         { "GENERAL OPTIONS" },
335
336         { "help",       cmd_help,       NULL,   "Get help on commands", "[command]" },
337         { "?",          cmd_help,       NULL,   "Get help on commands", "[command]" },
338         { "debuglevel", cmd_debuglevel, NULL,   "Set debug level", "level" },
339         { "exit",       cmd_quit,       NULL,   "Exit program", "" },
340         { "quit",       cmd_quit,       NULL,   "Exit program", "" },
341
342         { NULL }
343 };
344
345 static struct cmd_set separator_command[] = {
346         { "---------------", NULL,      NULL,   "----------------------" },
347         { NULL }
348 };
349
350
351 /* Various pipe commands */
352
353 extern struct cmd_set lsarpc_commands[];
354 extern struct cmd_set samr_commands[];
355 extern struct cmd_set spoolss_commands[];
356 extern struct cmd_set netlogon_commands[];
357 extern struct cmd_set srvsvc_commands[];
358 extern struct cmd_set dfs_commands[];
359 extern struct cmd_set reg_commands[];
360
361 static struct cmd_set *rpcclient_command_list[] = {
362         rpcclient_commands,
363         lsarpc_commands,
364         samr_commands,
365         spoolss_commands,
366         netlogon_commands,
367         srvsvc_commands,
368         dfs_commands,
369         reg_commands,
370         NULL
371 };
372
373 static void add_command_set(struct cmd_set *cmd_set)
374 {
375         struct cmd_list *entry;
376
377         if (!(entry = (struct cmd_list *)malloc(sizeof(struct cmd_list)))) {
378                 DEBUG(0, ("out of memory\n"));
379                 return;
380         }
381
382         ZERO_STRUCTP(entry);
383
384         entry->cmd_set = cmd_set;
385         DLIST_ADD(cmd_list, entry);
386 }
387
388 static NTSTATUS do_cmd(struct cli_state *cli, struct cmd_set *cmd_entry, 
389                        char *cmd)
390 {
391         char *p = cmd, **argv = NULL;
392         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
393         pstring buf;
394         int argc = 0, i;
395
396         /* Count number of arguments first time through the loop then
397            allocate memory and strdup them. */
398
399  again:
400         while(next_token(&p, buf, " ", sizeof(buf))) {
401                 if (argv) {
402                         argv[argc] = strdup(buf);
403                 }
404                 
405                 argc++;
406         }
407                                 
408         if (!argv) {
409
410                 /* Create argument list */
411
412                 argv = (char **)malloc(sizeof(char *) * argc);
413                 memset(argv, 0, sizeof(char *) * argc);
414
415                 if (!argv) {
416                         fprintf(stderr, "out of memory\n");
417                         result = NT_STATUS_NO_MEMORY;
418                         goto done;
419                 }
420                                         
421                 p = cmd;
422                 argc = 0;
423                                         
424                 goto again;
425         }
426
427         /* Call the function */
428
429         if (cmd_entry->fn) {
430                 TALLOC_CTX *mem_ctx;
431
432                 /* Create mem_ctx */
433
434                 if (!(mem_ctx = talloc_init())) {
435                         DEBUG(0, ("talloc_init() failed\n"));
436                         goto done;
437                 }
438
439                 /* Open pipe */
440
441                 if (cmd_entry->pipe)
442                         if (!cli_nt_session_open(cli, cmd_entry->pipe)) {
443                                 DEBUG(0, ("Could not initialise %s\n",
444                                           cmd_entry->pipe));
445                                 goto done;
446                         }
447
448                 /* Run command */
449
450                 result = cmd_entry->fn(cli, mem_ctx, argc, argv);
451
452                 /* Cleanup */
453
454                 if (cmd_entry->pipe)
455                         cli_nt_session_close(cli);
456
457                 talloc_destroy(mem_ctx);
458
459         } else {
460                 fprintf (stderr, "Invalid command\n");
461                 goto done;
462         }
463
464  done:
465                                                 
466         /* Cleanup */
467
468         if (argv) {
469                 for (i = 0; i < argc; i++)
470                         SAFE_FREE(argv[i]);
471         
472                 SAFE_FREE(argv);
473         }
474         
475         return result;
476 }
477
478 /* Process a command entered at the prompt or as part of -c */
479
480 static NTSTATUS process_cmd(struct cli_state *cli, char *cmd)
481 {
482         struct cmd_list *temp_list;
483         BOOL found = False;
484         pstring buf;
485         char *p = cmd;
486         NTSTATUS result = NT_STATUS_OK;
487         int len = 0;
488
489         if (cmd[strlen(cmd) - 1] == '\n')
490                 cmd[strlen(cmd) - 1] = '\0';
491
492         if (!next_token(&p, buf, " ", sizeof(buf))) {
493                 return NT_STATUS_OK;
494         }
495
496         /* strip the trainly \n if it exsists */
497         len = strlen(buf);
498         if (buf[len-1] == '\n')
499                 buf[len-1] = '\0';
500
501         /* Search for matching commands */
502
503         for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
504                 struct cmd_set *temp_set = temp_list->cmd_set;
505
506                 while(temp_set->name) {
507                         if (strequal(buf, temp_set->name)) {
508                                 found = True;
509                                 result = do_cmd(cli, temp_set, cmd);
510
511                                 goto done;
512                         }
513                         temp_set++;
514                 }
515         }
516
517  done:
518         if (!found && buf[0]) {
519                 printf("command not found: %s\n", buf);
520                 return NT_STATUS_OK;
521         }
522
523         if (!NT_STATUS_IS_OK(result)) {
524                 printf("result was %s\n", get_nt_error_msg(result));
525         }
526
527         return result;
528 }
529
530
531 /* Print usage information */
532 static void usage(void)
533 {
534         printf("Usage: rpcclient server [options]\n");
535
536         printf("\t-A authfile           file containing user credentials\n");
537         printf("\t-c \"command string\"   execute semicolon separated cmds\n");
538         printf("\t-d debuglevel         set the debuglevel\n");
539         printf("\t-l logfile            name of logfile to use as opposed to stdout\n");
540         printf("\t-h                    Print this help message.\n");
541         printf("\t-N                    don't ask for a password\n");
542         printf("\t-s configfile         specify an alternative config file\n");
543         printf("\t-U username           set the network username\n");
544         printf("\t-W domain             set the domain name for user account\n");
545         printf("\n");
546 }
547
548 /* Main function */
549
550  int main(int argc, char *argv[])
551 {
552         extern char             *optarg;
553         extern int              optind;
554         extern pstring          global_myname;
555         BOOL                    got_pass = False;
556         BOOL                    interactive = True;
557         int                     opt;
558         int                     olddebug;
559         pstring                 cmdstr = "";
560         struct cli_state        *cli;
561         fstring                 password="",
562                                 username="",
563                                 domain="",
564                                 server="";
565         struct cmd_set **cmd_set;
566         struct in_addr server_ip;
567         NTSTATUS nt_status;
568
569         setlinebuf(stdout);
570
571         DEBUGLEVEL = 1;
572
573         while ((opt = getopt(argc, argv, "A:s:Nd:U:W:c:l:h")) != EOF) {
574                 switch (opt) {
575                 case 'A':
576                         /* only get the username, password, and domain from the file */
577                         read_authfile (optarg, username, password, domain);
578                         if (strlen (password))
579                                 got_pass = True;
580                         break;
581
582                 case 'c':
583                         pstrcpy(cmdstr, optarg);
584                         break;
585
586                 case 'd':
587                         DEBUGLEVEL = atoi(optarg);
588                         break;
589
590                 case 'l':
591                         slprintf(logfile, sizeof(logfile) - 1, "%s.client", optarg);
592                         lp_set_logfile(logfile);
593                         interactive = False;
594                         break;
595
596                 case 'N':
597                         got_pass = True;
598                         break;
599                         
600                 case 's':
601                         pstrcpy(dyn_CONFIGFILE, optarg);
602                         break;
603
604                 case 'U': {
605                         char *lp;
606                         pstrcpy(username,optarg);
607                         if ((lp=strchr_m(username,'%'))) {
608                                 *lp = 0;
609                                 pstrcpy(password,lp+1);
610                                 got_pass = True;
611                                 memset(strchr_m(optarg,'%')+1,'X',strlen(password));
612                         }
613                         break;
614                 }
615                 
616                 case 'W':
617                         pstrcpy(domain, optarg);
618                         break;
619                         
620                 case 'h':
621                 default:
622                         usage();
623                         exit(1);
624                 }
625         }
626
627         argv += optind;
628         argc -= optind;
629
630         /* Parse options */
631         if (argc == 0) {
632                 usage();
633                 return 0;
634         }
635         
636         if (strncmp("//", argv[0], 2) == 0 || strncmp("\\\\", argv[0], 2) == 0)
637                 argv[0] += 2;
638
639         pstrcpy(server, argv[0]);
640
641         /* the following functions are part of the Samba debugging
642            facilities.  See lib/debug.c */
643         setup_logging("rpcclient", interactive);
644         if (!interactive) 
645                 reopen_logs();
646         
647         /* Load smb.conf file */
648         /* FIXME!  How to get this DEBUGLEVEL to last over lp_load()? */
649         olddebug = DEBUGLEVEL;
650         if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
651                 fprintf(stderr, "Can't load %s\n", dyn_CONFIGFILE);
652         }
653         DEBUGLEVEL = olddebug;
654
655         load_interfaces();
656
657         get_myname((*global_myname)?NULL:global_myname);
658         strupper(global_myname);
659
660         
661         /* resolve the IP address */
662         if (!resolve_name(server, &server_ip, 0x20))  {
663                 DEBUG(1,("Unable to resolve server name\n"));
664                 return 1;
665         }
666         
667         /*
668          * Get password
669          * from stdin if necessary
670          */
671
672         if (!got_pass) {
673                 char *pass = getpass("Password:");
674                 if (pass) {
675                         fstrcpy(password, pass);
676                 }
677         }
678         
679         if (!strlen(username) && !got_pass)
680                 get_username(username);
681                 
682         nt_status = cli_full_connection(&cli, global_myname, server, 
683                                         &server_ip, 0,
684                                         "IPC$", "IPC",  
685                                         username, domain,
686                                         password, strlen(password));
687         
688         if (!NT_STATUS_IS_OK(nt_status)) {
689                 DEBUG(1,("Cannot connect to server.  Error was %s\n", get_nt_error_msg(nt_status)));
690                 return 1;
691         }
692
693         memset(password,'X',sizeof(password));
694
695         /* Load command lists */
696
697         cmd_set = rpcclient_command_list;
698
699         while(*cmd_set) {
700                 add_command_set(*cmd_set);
701                 add_command_set(separator_command);
702                 cmd_set++;
703         }
704
705         fetch_machine_sid(cli);
706  
707        /* Do anything specified with -c */
708         if (cmdstr[0]) {
709                 char    *cmd;
710                 char    *p = cmdstr;
711  
712                 while((cmd=next_command(&p)) != NULL) {
713                         process_cmd(cli, cmd);
714                 }
715                 
716                 cli_shutdown(cli);
717                 return 0;
718         }
719
720         /* Loop around accepting commands */
721
722         while(1) {
723                 pstring prompt;
724                 char *line;
725
726                 slprintf(prompt, sizeof(prompt) - 1, "rpcclient $> ");
727
728                 line = smb_readline(prompt, NULL, completion_fn);
729
730                 if (line == NULL)
731                         break;
732
733                 if (line[0] != '\n')
734                         process_cmd(cli, line);
735         }
736         
737         cli_shutdown(cli);
738         return 0;
739 }