merging Tim's changes form HEAD
[Samba.git] / source / rpcclient / rpcclient.c
blobdc93c0536bbe65ae118bb093f363b57b5c4a016f
1 /*
2 Unix SMB/Netbios implementation.
3 Version 2.2
4 RPC pipe client
6 Copyright (C) Tim Potter 2000
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.
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.
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.
23 #include "includes.h"
25 extern int DEBUGLEVEL;
26 extern fstring debugf;
28 /* Various pipe commands */
29 extern struct cmd_set lsarpc_commands[];
30 extern struct cmd_set samr_commands[];
31 extern struct cmd_set spoolss_commands[];
33 /* List to hold groups of commands */
34 static struct cmd_list {
35 struct cmd_list *prev, *next;
36 struct cmd_set *cmd_set;
37 } *cmd_list;
40 DOM_SID domain_sid;
42 /****************************************************************************
43 handle completion of commands for readline
44 ****************************************************************************/
45 static char **completion_fn(char *text, int start, int end)
47 #define MAX_COMPLETIONS 100
48 char **matches;
49 int i, count=0;
50 struct cmd_list *commands = cmd_list;
52 #if 0 /* JERRY */
53 /* FIXME!!! -- what to do when completing argument? */
54 /* for words not at the start of the line fallback
55 to filename completion */
56 if (start)
57 return NULL;
58 #endif
60 /* make sure we have a list of valid commands */
61 if (!commands)
62 return NULL;
64 matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS);
65 if (!matches) return NULL;
67 matches[count++] = strdup(text);
68 if (!matches[0]) return NULL;
70 while (commands && count < MAX_COMPLETIONS-1)
72 if (!commands->cmd_set)
73 break;
75 for (i=0; commands->cmd_set[i].name; i++)
77 if ((strncmp(text, commands->cmd_set[i].name, strlen(text)) == 0) &&
78 commands->cmd_set[i].fn)
80 matches[count] = strdup(commands->cmd_set[i].name);
81 if (!matches[count])
82 return NULL;
83 count++;
87 commands = commands->next;
91 if (count == 2) {
92 free(matches[0]);
93 matches[0] = strdup(matches[1]);
95 matches[count] = NULL;
96 return matches;
99 /***********************************************************************
100 * read in username/password credentials from a file
102 static void read_authfile (
103 char *filename,
104 char* username,
105 char* password,
106 char* domain
109 FILE *auth;
110 fstring buf;
111 uint16 len = 0;
112 char *ptr, *val, *param;
114 if ((auth=sys_fopen(filename, "r")) == NULL)
116 printf ("ERROR: Unable to open credentials file!\n");
117 return;
120 while (!feof(auth))
122 /* get a line from the file */
123 if (!fgets (buf, sizeof(buf), auth))
124 continue;
126 len = strlen(buf);
128 /* skip empty lines */
129 if ((len) && (buf[len-1]=='\n'))
131 buf[len-1] = '\0';
132 len--;
134 if (len == 0)
135 continue;
137 /* break up the line into parameter & value.
138 will need to eat a little whitespace possibly */
139 param = buf;
140 if (!(ptr = strchr (buf, '=')))
141 continue;
142 val = ptr+1;
143 *ptr = '\0';
145 /* eat leading white space */
146 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
147 val++;
149 if (strwicmp("password", param) == 0)
150 fstrcpy (password, val);
151 else if (strwicmp("username", param) == 0)
152 fstrcpy (username, val);
153 else if (strwicmp("domain", param) == 0)
154 fstrcpy (domain, val);
156 memset(buf, 0, sizeof(buf));
158 fclose(auth);
160 return;
163 static char* next_command (
164 char** cmdstr
167 static pstring command;
168 char *p;
170 if (!cmdstr || !(*cmdstr))
171 return NULL;
173 p = strchr(*cmdstr, ';');
174 if (p)
175 *p = '\0';
176 pstrcpy(command, *cmdstr);
177 *cmdstr = p;
179 return command;
182 static void get_username (char *username)
184 if (getenv("USER"))
185 pstrcpy(username,getenv("USER"));
187 if (*username == 0 && getenv("LOGNAME"))
188 pstrcpy(username,getenv("LOGNAME"));
190 if (*username == 0) {
191 pstrcpy(username,"GUEST");
194 return;
197 /* Fetch the SID for this domain */
198 void fetch_domain_sid(struct cli_state *cli)
200 POLICY_HND pol;
201 uint32 result = 0, info_class = 5;
202 fstring domain_name;
203 static BOOL got_domain_sid;
204 TALLOC_CTX *mem_ctx;
206 if (got_domain_sid) return;
208 if (!(mem_ctx=talloc_init()))
210 DEBUG(0,("fetch_domain_sid: talloc_init returned NULL!\n"));
211 goto error;
215 if (!cli_nt_session_open (cli, PIPE_LSARPC)) {
216 fprintf(stderr, "could not initialise lsa pipe\n");
217 goto error;
220 if ((result = cli_lsa_open_policy(cli, mem_ctx, True,
221 SEC_RIGHTS_MAXIMUM_ALLOWED,
222 &pol) != NT_STATUS_NOPROBLEMO)) {
223 goto error;
226 if ((result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class,
227 domain_name, &domain_sid))
228 != NT_STATUS_NOPROBLEMO) {
229 goto error;
232 got_domain_sid = True;
234 cli_lsa_close(cli, mem_ctx, &pol);
235 cli_nt_session_close(cli);
236 talloc_destroy(mem_ctx);
238 return;
240 error:
241 fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
243 if (result != NT_STATUS_NOPROBLEMO) {
244 fprintf(stderr, "error: %s\n", get_nt_error_msg(result));
247 exit(1);
250 /* Initialise client credentials for authenticated pipe access */
252 void init_rpcclient_creds(struct ntuser_creds *creds, char* username,
253 char* domain, char* password)
255 ZERO_STRUCTP(creds);
257 if (lp_encrypted_passwords()) {
258 pwd_make_lm_nt_16(&creds->pwd, password);
259 } else {
260 pwd_set_cleartext(&creds->pwd, password);
263 fstrcpy(creds->user_name, username);
264 fstrcpy(creds->domain, domain);
268 static uint32 cmd_help(struct cli_state *cli, int argc, char **argv)
270 struct cmd_list *temp_list;
272 for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
273 struct cmd_set *temp_set = temp_list->cmd_set;
275 while(temp_set->name) {
276 printf("%15s\t\t%s\n", temp_set->name,
277 temp_set->description);
278 temp_set++;
282 return 0;
285 static uint32 cmd_debuglevel(struct cli_state *cli, int argc, char **argv)
287 if (argc > 2) {
288 printf("Usage: %s [debuglevel]\n", argv[0]);
289 return NT_STATUS_NOPROBLEMO;
292 if (argc == 2) {
293 DEBUGLEVEL = atoi(argv[1]);
296 printf("debuglevel is %d\n", DEBUGLEVEL);
298 return NT_STATUS_NOPROBLEMO;
301 static uint32 cmd_quit(struct cli_state *cli, int argc, char **argv)
303 exit(0);
304 return NT_STATUS_NOPROBLEMO; /* NOTREACHED */
307 /* Build in rpcclient commands */
309 static struct cmd_set rpcclient_commands[] = {
310 { "GENERAL OPTIONS", NULL, "" },
311 { "help", cmd_help, "Print list of commands" },
312 { "?", cmd_help, "Print list of commands" },
313 { "debuglevel", cmd_debuglevel, "Set debug level" },
314 { "exit", cmd_quit, "Exit program" },
315 { "quit", cmd_quit, "Exit program" },
317 { NULL, NULL, NULL }
320 static struct cmd_set separator_command[] = {
321 { "---------------", NULL, "----------------------" },
322 { NULL, NULL, NULL }
326 void add_command_set(struct cmd_set *cmd_set)
328 struct cmd_list *entry;
330 if (!(entry = (struct cmd_list *)malloc(sizeof(struct cmd_list)))) {
331 DEBUG(0, ("out of memory\n"));
332 return;
335 ZERO_STRUCTP(entry);
337 entry->cmd_set = cmd_set;
338 DLIST_ADD(cmd_list, entry);
341 static uint32 do_cmd(struct cli_state *cli, struct cmd_set *cmd_entry, char *cmd)
343 char *p = cmd, **argv = NULL;
344 uint32 result;
345 pstring buf;
346 int argc = 1, i;
348 next_token(&p, buf, " ", sizeof(buf));
350 /* Count number of arguments first time through the loop then
351 allocate memory and strdup them. */
353 again:
354 while(next_token(NULL, buf, " ", sizeof(buf))) {
355 if (argv) {
356 argv[argc] = strdup(buf);
359 argc++;
362 if (!argv) {
364 /* Create argument list */
366 argv = (char **)malloc(sizeof(char *) * argc);
368 if (!argv) {
369 fprintf(stderr, "out of memoryx\n");
370 return 0;
373 p = cmd;
374 next_token(&p, buf, " ", sizeof(buf));
375 argv[0] = strdup(buf);
376 argc = 1;
378 goto again;
381 /* Call the function */
382 if (cmd_entry->fn) {
383 result = cmd_entry->fn(cli, argc, argv);
385 else {
386 fprintf (stderr, "Invalid command\n");
387 result = NT_STATUS_INVALID_PARAMETER;
391 /* Cleanup */
392 for (i = 0; i < argc; i++) {
393 free(argv[i]);
396 free(argv);
398 return result;
401 /* Process a command entered at the prompt or as part of -c */
403 static uint32 process_cmd(struct cli_state *cli, char *cmd)
405 struct cmd_list *temp_list;
406 BOOL found = False;
407 pstring buf;
408 char *p = cmd;
409 uint32 result=0;
411 if (cmd[strlen(cmd) - 1] == '\n')
412 cmd[strlen(cmd) - 1] = '\0';
414 if (!next_token(&p, buf, " ", sizeof(buf))) {
415 return 0;
418 /* Search for matching commands */
420 for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) {
421 struct cmd_set *temp_set = temp_list->cmd_set;
423 while(temp_set->name) {
424 if (strequal(buf, temp_set->name)) {
425 found = True;
426 result = do_cmd(cli, temp_set, cmd);
427 goto done;
429 temp_set++;
433 done:
434 if (!found && buf[0]) {
435 printf("command not found: %s\n", buf);
436 return 0;
439 if (result != 0) {
440 printf("result was %s\n", get_nt_error_msg(result));
443 return result;
446 /************************************************************************/
447 struct cli_state *setup_connection(struct cli_state *cli, char *system_name,
448 struct ntuser_creds *creds)
450 struct in_addr dest_ip;
451 struct nmb_name calling, called;
452 fstring dest_host;
453 extern pstring global_myname;
454 struct ntuser_creds anon;
456 /* Initialise cli_state information */
457 if (!cli_initialise(cli)) {
458 return NULL;
461 if (!creds) {
462 ZERO_STRUCT(anon);
463 anon.pwd.null_pwd = 1;
464 creds = &anon;
467 cli_init_creds(cli, creds);
469 /* Establish a SMB connection */
470 if (!resolve_srv_name(system_name, dest_host, &dest_ip)) {
471 return NULL;
474 make_nmb_name(&called, dns_to_netbios_name(dest_host), 0x20);
475 make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
477 if (!cli_establish_connection(cli, dest_host, &dest_ip, &calling,
478 &called, "IPC$", "IPC", False, True)) {
479 return NULL;
482 return cli;
486 /* Print usage information */
487 static void usage(char *pname)
489 printf("Usage: %s server [options]\n", pname);
491 printf("\t-A authfile file containing user credentials\n");
492 printf("\t-c \"command string\" execute semicolon separated cmds\n");
493 printf("\t-d debuglevel set the debuglevel\n");
494 printf("\t-l logfile name of logfile to use as opposed to stdout\n");
495 printf("\t-h Print this help message.\n");
496 printf("\t-N don't ask for a password\n");
497 printf("\t-s configfile specify an alternative config file\n");
498 printf("\t-U username set the network username\n");
499 printf("\t-W domain set the domain name for user account\n");
500 printf("\n");
503 /* Main function */
505 int main(int argc, char *argv[])
507 extern char *optarg;
508 extern int optind;
509 extern pstring global_myname;
510 BOOL got_pass = False;
511 BOOL interactive = True;
512 int opt;
513 int olddebug;
514 pstring cmdstr = "",
515 servicesf = CONFIGFILE;
516 struct ntuser_creds creds;
517 struct cli_state cli;
518 fstring password,
519 username,
520 domain,
521 server;
523 charset_initialise();
524 setlinebuf(stdout);
526 DEBUGLEVEL = 1;
528 /* Parse options */
529 if (argc < 2) {
530 usage(argv[0]);
531 return 0;
534 pstrcpy(server, argv[1]);
536 argv++;
537 argc--;
539 while ((opt = getopt(argc, argv, "A:s:Nd:U:W:c:l:")) != EOF) {
540 switch (opt) {
541 case 'A':
542 /* only get the username, password, and domain from the file */
543 read_authfile (optarg, username, password, domain);
544 if (strlen (password))
545 got_pass = True;
546 break;
548 case 'c':
549 pstrcpy(cmdstr, optarg);
550 break;
552 case 'd':
553 DEBUGLEVEL = atoi(optarg);
554 break;
556 case 'l':
557 slprintf(debugf, sizeof(debugf) - 1, "%s.client", optarg);
558 interactive = False;
559 break;
561 case 'N':
562 got_pass = True;
563 break;
565 case 's':
566 pstrcpy(servicesf, optarg);
567 break;
569 case 'U': {
570 char *lp;
571 pstrcpy(username,optarg);
572 if ((lp=strchr(username,'%'))) {
573 *lp = 0;
574 pstrcpy(password,lp+1);
575 got_pass = True;
576 memset(strchr(optarg,'%')+1,'X',strlen(password));
578 break;
581 case 'W':
582 pstrcpy(domain, optarg);
583 break;
585 case 'h':
586 default:
587 usage(argv[0]);
588 exit(1);
592 /* the following functions are part of the Samba debugging
593 facilities. See lib/debug.c */
594 setup_logging (argv[0], interactive);
595 if (!interactive)
596 reopen_logs();
598 /* Load smb.conf file */
599 /* FIXME! How to get this DEBUGLEVEL to last over lp_load()? */
600 olddebug = DEBUGLEVEL;
601 if (!lp_load(servicesf,True,False,False)) {
602 fprintf(stderr, "Can't load %s\n", servicesf);
604 DEBUGLEVEL = olddebug;
606 codepage_initialise(lp_client_code_page());
607 load_interfaces();
609 TimeInit();
611 get_myname((*global_myname)?NULL:global_myname);
612 strupper(global_myname);
615 * initialize the credentials struct. Get password
616 * from stdin if necessary
618 if (!strlen(username))
619 get_username (username);
621 if (!got_pass) {
622 init_rpcclient_creds (&creds, username, domain, "");
623 pwd_read(&creds.pwd, "Enter Password: ", lp_encrypted_passwords());
625 else {
626 init_rpcclient_creds (&creds, username, domain, password);
628 memset(password,'X',strlen(password));
630 /* open a connection to the specified server */
631 ZERO_STRUCTP (&cli);
632 if (!setup_connection (&cli, server, &creds)) {
633 return 0;
636 /* There are no pointers in ntuser_creds struct so zero it out */
637 ZERO_STRUCTP (&creds);
639 /* Load command lists */
640 add_command_set(rpcclient_commands);
641 add_command_set(separator_command);
643 add_command_set(spoolss_commands);
644 add_command_set(separator_command);
646 add_command_set(lsarpc_commands);
647 add_command_set(separator_command);
649 add_command_set(samr_commands);
650 add_command_set(separator_command);
652 /* Do anything specified with -c */
653 if (cmdstr[0]) {
654 char *cmd;
655 char *p = cmdstr;
657 while((cmd=next_command(&p)) != NULL) {
658 process_cmd(&cli, cmd);
661 return 0;
664 /* Loop around accepting commands */
665 while(1) {
666 pstring prompt;
667 char *line;
669 slprintf(prompt, sizeof(prompt) - 1, "rpcclient $> ");
671 line = smb_readline(prompt, NULL, completion_fn);
673 if (line == NULL)
674 break;
676 if (line[0] != '\n')
677 process_cmd(&cli, line);
680 return 0;