2 Unix SMB/Netbios implementation.
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.
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;
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
50 struct cmd_list *commands = cmd_list;
53 /* FIXME!!! -- what to do when completing argument? */
54 /* for words not at the start of the line fallback
55 to filename completion */
60 /* make sure we have a list of valid commands */
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)
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);
87 commands = commands->next;
93 matches[0] = strdup(matches[1]);
95 matches[count] = NULL;
99 /***********************************************************************
100 * read in username/password credentials from a file
102 static void read_authfile (
112 char *ptr, *val, *param;
114 if ((auth=sys_fopen(filename, "r")) == NULL)
116 printf ("ERROR: Unable to open credentials file!\n");
122 /* get a line from the file */
123 if (!fgets (buf, sizeof(buf), auth))
128 /* skip empty lines */
129 if ((len) && (buf[len-1]=='\n'))
137 /* break up the line into parameter & value.
138 will need to eat a little whitespace possibly */
140 if (!(ptr = strchr (buf, '=')))
145 /* eat leading white space */
146 while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
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));
163 static char* next_command (
167 static pstring command;
170 if (!cmdstr || !(*cmdstr))
173 p = strchr(*cmdstr, ';');
176 pstrcpy(command, *cmdstr);
182 static void get_username (char *username)
185 pstrcpy(username,getenv("USER"));
187 if (*username == 0 && getenv("LOGNAME"))
188 pstrcpy(username,getenv("LOGNAME"));
190 if (*username == 0) {
191 pstrcpy(username,"GUEST");
197 /* Fetch the SID for this domain */
198 void fetch_domain_sid(struct cli_state *cli)
201 uint32 result = 0, info_class = 5;
203 static BOOL got_domain_sid;
206 if (got_domain_sid) return;
208 if (!(mem_ctx=talloc_init()))
210 DEBUG(0,("fetch_domain_sid: talloc_init returned NULL!\n"));
215 if (!cli_nt_session_open (cli, PIPE_LSARPC)) {
216 fprintf(stderr, "could not initialise lsa pipe\n");
220 if ((result = cli_lsa_open_policy(cli, mem_ctx, True,
221 SEC_RIGHTS_MAXIMUM_ALLOWED,
222 &pol) != NT_STATUS_NOPROBLEMO)) {
226 if ((result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class,
227 domain_name, &domain_sid))
228 != NT_STATUS_NOPROBLEMO) {
232 got_domain_sid = True;
234 cli_lsa_close(cli, mem_ctx, &pol);
235 cli_nt_session_close(cli);
236 talloc_destroy(mem_ctx);
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));
250 /* Initialise client credentials for authenticated pipe access */
252 void init_rpcclient_creds(struct ntuser_creds *creds, char* username,
253 char* domain, char* password)
257 if (lp_encrypted_passwords()) {
258 pwd_make_lm_nt_16(&creds->pwd, password);
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);
285 static uint32 cmd_debuglevel(struct cli_state *cli, int argc, char **argv)
288 printf("Usage: %s [debuglevel]\n", argv[0]);
289 return NT_STATUS_NOPROBLEMO;
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)
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" },
320 static struct cmd_set separator_command[] = {
321 { "---------------", 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"));
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;
348 next_token(&p, buf, " ", sizeof(buf));
350 /* Count number of arguments first time through the loop then
351 allocate memory and strdup them. */
354 while(next_token(NULL, buf, " ", sizeof(buf))) {
356 argv[argc] = strdup(buf);
364 /* Create argument list */
366 argv = (char **)malloc(sizeof(char *) * argc);
369 fprintf(stderr, "out of memoryx\n");
374 next_token(&p, buf, " ", sizeof(buf));
375 argv[0] = strdup(buf);
381 /* Call the function */
383 result = cmd_entry->fn(cli, argc, argv);
386 fprintf (stderr, "Invalid command\n");
387 result = NT_STATUS_INVALID_PARAMETER;
392 for (i = 0; i < argc; i++) {
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;
411 if (cmd[strlen(cmd) - 1] == '\n')
412 cmd[strlen(cmd) - 1] = '\0';
414 if (!next_token(&p, buf, " ", sizeof(buf))) {
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)) {
426 result = do_cmd(cli, temp_set, cmd);
434 if (!found && buf[0]) {
435 printf("command not found: %s\n", buf);
440 printf("result was %s\n", get_nt_error_msg(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;
453 extern pstring global_myname;
454 struct ntuser_creds anon;
456 /* Initialise cli_state information */
457 if (!cli_initialise(cli)) {
463 anon.pwd.null_pwd = 1;
467 cli_init_creds(cli, creds);
469 /* Establish a SMB connection */
470 if (!resolve_srv_name(system_name, dest_host, &dest_ip)) {
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)) {
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");
505 int main(int argc, char *argv[])
509 extern pstring global_myname;
510 BOOL got_pass = False;
511 BOOL interactive = True;
515 servicesf = CONFIGFILE;
516 struct ntuser_creds creds;
517 struct cli_state cli;
523 charset_initialise();
534 pstrcpy(server, argv[1]);
539 while ((opt = getopt(argc, argv, "A:s:Nd:U:W:c:l:")) != EOF) {
542 /* only get the username, password, and domain from the file */
543 read_authfile (optarg, username, password, domain);
544 if (strlen (password))
549 pstrcpy(cmdstr, optarg);
553 DEBUGLEVEL = atoi(optarg);
557 slprintf(debugf, sizeof(debugf) - 1, "%s.client", optarg);
566 pstrcpy(servicesf, optarg);
571 pstrcpy(username,optarg);
572 if ((lp=strchr(username,'%'))) {
574 pstrcpy(password,lp+1);
576 memset(strchr(optarg,'%')+1,'X',strlen(password));
582 pstrcpy(domain, optarg);
592 /* the following functions are part of the Samba debugging
593 facilities. See lib/debug.c */
594 setup_logging (argv[0], interactive);
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());
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);
622 init_rpcclient_creds (&creds, username, domain, "");
623 pwd_read(&creds.pwd, "Enter Password: ", lp_encrypted_passwords());
626 init_rpcclient_creds (&creds, username, domain, password);
628 memset(password,'X',strlen(password));
630 /* open a connection to the specified server */
632 if (!setup_connection (&cli, server, &creds)) {
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 */
657 while((cmd=next_command(&p)) != NULL) {
658 process_cmd(&cli, cmd);
664 /* Loop around accepting commands */
669 slprintf(prompt, sizeof(prompt) - 1, "rpcclient $> ");
671 line = smb_readline(prompt, NULL, completion_fn);
677 process_cmd(&cli, line);