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
);