2 Unix SMB/Netbios implementation.
6 Copyright (C) Tim Potter 2000-2001
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.
24 #include "rpcclient.h"
28 /* List to hold groups of commands */
30 static struct cmd_list
{
31 struct cmd_list
*prev
, *next
;
32 struct cmd_set
*cmd_set
;
35 /****************************************************************************
36 handle completion of commands for readline
37 ****************************************************************************/
38 static char **completion_fn(const char *text
, int start
, int end
)
40 #define MAX_COMPLETIONS 100
43 struct cmd_list
*commands
= cmd_list
;
46 /* FIXME!!! -- what to do when completing argument? */
47 /* for words not at the start of the line fallback
48 to filename completion */
53 /* make sure we have a list of valid commands */
57 matches
= (char **)malloc(sizeof(matches
[0])*MAX_COMPLETIONS
);
58 if (!matches
) return NULL
;
60 matches
[count
++] = strdup(text
);
61 if (!matches
[0]) return NULL
;
63 while (commands
&& count
< MAX_COMPLETIONS
-1)
65 if (!commands
->cmd_set
)
68 for (i
=0; commands
->cmd_set
[i
].name
; i
++)
70 if ((strncmp(text
, commands
->cmd_set
[i
].name
, strlen(text
)) == 0) &&
71 commands
->cmd_set
[i
].fn
)
73 matches
[count
] = strdup(commands
->cmd_set
[i
].name
);
80 commands
= commands
->next
;
85 SAFE_FREE(matches
[0]);
86 matches
[0] = strdup(matches
[1]);
88 matches
[count
] = NULL
;
92 /***********************************************************************
93 * read in username/password credentials from a file
95 static void read_authfile (
105 char *ptr
, *val
, *param
;
107 if ((auth
=sys_fopen(filename
, "r")) == NULL
)
109 printf ("ERROR: Unable to open credentials file!\n");
115 /* get a line from the file */
116 if (!fgets (buf
, sizeof(buf
), auth
))
121 /* skip empty lines */
122 if ((len
) && (buf
[len
-1]=='\n'))
130 /* break up the line into parameter & value.
131 will need to eat a little whitespace possibly */
133 if (!(ptr
= strchr(buf
, '=')))
138 /* eat leading white space */
139 while ((*val
!='\0') && ((*val
==' ') || (*val
=='\t')))
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
);
149 memset(buf
, 0, sizeof(buf
));
156 static char* next_command (char** cmdstr
)
158 static pstring command
;
160 BOOL next_cmd
= False
;
162 if (!cmdstr
|| !(*cmdstr
))
165 printf("cmd = %s\n", *cmdstr
);
167 p
= strchr(*cmdstr
, ';');
172 pstrcpy(command
, *cmdstr
);
180 static void get_username (char *username
)
183 pstrcpy(username
,getenv("USER"));
185 if (*username
== 0 && getenv("LOGNAME"))
186 pstrcpy(username
,getenv("LOGNAME"));
188 if (*username
== 0) {
189 pstrcpy(username
,"GUEST");
195 /* Fetch the SID for this computer */
197 void fetch_machine_sid(struct cli_state
*cli
)
200 NTSTATUS result
= NT_STATUS_OK
;
201 uint32 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_machine_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 result
= cli_lsa_open_policy(cli
, mem_ctx
, True
,
221 SEC_RIGHTS_MAXIMUM_ALLOWED
,
223 if (!NT_STATUS_IS_OK(result
)) {
227 result
= cli_lsa_query_info_policy(cli
, mem_ctx
, &pol
, info_class
,
228 domain_name
, &domain_sid
);
229 if (!NT_STATUS_IS_OK(result
)) {
233 got_domain_sid
= True
;
235 cli_lsa_close(cli
, mem_ctx
, &pol
);
236 cli_nt_session_close(cli
);
237 talloc_destroy(mem_ctx
);
242 fprintf(stderr
, "could not obtain sid for domain %s\n", cli
->domain
);
244 if (!NT_STATUS_IS_OK(result
)) {
245 fprintf(stderr
, "error: %s\n", get_nt_error_msg(result
));
251 /* List the available commands on a given pipe */
253 static NTSTATUS
cmd_listcommands(struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
254 int argc
, char **argv
)
256 struct cmd_list
*tmp
;
257 struct cmd_set
*tmp_set
;
263 printf("Usage: %s <pipe>\n", argv
[0]);
267 /* Help on one command */
269 for (tmp
= cmd_list
; tmp
; tmp
= tmp
->next
)
271 tmp_set
= tmp
->cmd_set
;
273 if (!StrCaseCmp(argv
[1], tmp_set
->name
))
275 printf("Available commands on the %s pipe:\n\n", tmp_set
->name
);
279 while(tmp_set
->name
) {
280 printf("%20s", tmp_set
->name
);
287 /* drop out of the loop */
296 /* Display help on commands */
298 static NTSTATUS
cmd_help(struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
299 int argc
, char **argv
)
301 struct cmd_list
*tmp
;
302 struct cmd_set
*tmp_set
;
307 printf("Usage: %s [command]\n", argv
[0]);
311 /* Help on one command */
314 for (tmp
= cmd_list
; tmp
; tmp
= tmp
->next
) {
316 tmp_set
= tmp
->cmd_set
;
318 while(tmp_set
->name
) {
319 if (strequal(argv
[1], tmp_set
->name
)) {
320 if (tmp_set
->usage
&&
322 printf("%s\n", tmp_set
->usage
);
324 printf("No help for %s\n", tmp_set
->name
);
333 printf("No such command: %s\n", argv
[1]);
337 /* List all commands */
339 for (tmp
= cmd_list
; tmp
; tmp
= tmp
->next
) {
341 tmp_set
= tmp
->cmd_set
;
343 while(tmp_set
->name
) {
345 printf("%15s\t\t%s\n", tmp_set
->name
,
346 tmp_set
->description
? tmp_set
->description
:
356 /* Change the debug level */
358 static NTSTATUS
cmd_debuglevel(struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
359 int argc
, char **argv
)
362 printf("Usage: %s [debuglevel]\n", argv
[0]);
367 DEBUGLEVEL
= atoi(argv
[1]);
370 printf("debuglevel is %d\n", DEBUGLEVEL
);
375 static NTSTATUS
cmd_quit(struct cli_state
*cli
, TALLOC_CTX
*mem_ctx
,
376 int argc
, char **argv
)
379 return NT_STATUS_OK
; /* NOTREACHED */
382 /* Build in rpcclient commands */
384 static struct cmd_set rpcclient_commands
[] = {
386 { "GENERAL OPTIONS" },
388 { "help", cmd_help
, NULL
, "Get help on commands", "[command]" },
389 { "?", cmd_help
, NULL
, "Get help on commands", "[command]" },
390 { "debuglevel", cmd_debuglevel
, NULL
, "Set debug level", "level" },
391 { "list", cmd_listcommands
, NULL
, "List available commands on <pipe>", "pipe" },
392 { "exit", cmd_quit
, NULL
, "Exit program", "" },
393 { "quit", cmd_quit
, NULL
, "Exit program", "" },
398 static struct cmd_set separator_command
[] = {
399 { "---------------", NULL
, NULL
, "----------------------" },
404 /* Various pipe commands */
406 extern struct cmd_set lsarpc_commands
[];
407 extern struct cmd_set samr_commands
[];
408 extern struct cmd_set spoolss_commands
[];
409 extern struct cmd_set netlogon_commands
[];
410 extern struct cmd_set srvsvc_commands
[];
411 extern struct cmd_set dfs_commands
[];
412 extern struct cmd_set reg_commands
[];
414 static struct cmd_set
*rpcclient_command_list
[] = {
426 static void add_command_set(struct cmd_set
*cmd_set
)
428 struct cmd_list
*entry
;
430 if (!(entry
= (struct cmd_list
*)malloc(sizeof(struct cmd_list
)))) {
431 DEBUG(0, ("out of memory\n"));
437 entry
->cmd_set
= cmd_set
;
438 DLIST_ADD(cmd_list
, entry
);
441 static NTSTATUS
do_cmd(struct cli_state
*cli
, struct cmd_set
*cmd_entry
,
444 char *p
= cmd
, **argv
= NULL
;
445 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
449 /* Count number of arguments first time through the loop then
450 allocate memory and strdup them. */
453 while(next_token(&p
, buf
, " ", sizeof(buf
))) {
455 argv
[argc
] = strdup(buf
);
463 /* Create argument list */
465 argv
= (char **)malloc(sizeof(char *) * argc
);
466 memset(argv
, 0, sizeof(char *) * argc
);
469 fprintf(stderr
, "out of memory\n");
470 result
= NT_STATUS_NO_MEMORY
;
480 /* Call the function */
487 if (!(mem_ctx
= talloc_init())) {
488 DEBUG(0, ("talloc_init() failed\n"));
495 if (!cli_nt_session_open(cli
, cmd_entry
->pipe
)) {
496 DEBUG(0, ("Could not initialise %s\n",
503 result
= cmd_entry
->fn(cli
, mem_ctx
, argc
, argv
);
508 cli_nt_session_close(cli
);
510 talloc_destroy(mem_ctx
);
513 fprintf (stderr
, "Invalid command\n");
522 for (i
= 0; i
< argc
; i
++)
531 /* Process a command entered at the prompt or as part of -c */
533 static NTSTATUS
process_cmd(struct cli_state
*cli
, char *cmd
)
535 struct cmd_list
*temp_list
;
539 NTSTATUS result
= NT_STATUS_OK
;
542 if (cmd
[strlen(cmd
) - 1] == '\n')
543 cmd
[strlen(cmd
) - 1] = '\0';
545 if (!next_token(&p
, buf
, " ", sizeof(buf
))) {
549 /* strip the trainly \n if it exsists */
551 if (buf
[len
-1] == '\n')
554 /* Search for matching commands */
556 for (temp_list
= cmd_list
; temp_list
; temp_list
= temp_list
->next
) {
557 struct cmd_set
*temp_set
= temp_list
->cmd_set
;
559 while(temp_set
->name
) {
560 if (strequal(buf
, temp_set
->name
)) {
562 result
= do_cmd(cli
, temp_set
, cmd
);
571 if (!found
&& buf
[0]) {
572 printf("command not found: %s\n", buf
);
576 if (!NT_STATUS_IS_OK(result
)) {
577 printf("result was %s\n", get_nt_error_msg(result
));
584 /* Print usage information */
585 static void usage(void)
587 printf("Usage: rpcclient [options] server\n");
589 printf("\t-A authfile file containing user credentials\n");
590 printf("\t-c \"command string\" execute semicolon separated cmds\n");
591 printf("\t-d debuglevel set the debuglevel\n");
592 printf("\t-l logfile name of logfile to use as opposed to stdout\n");
593 printf("\t-h Print this help message.\n");
594 printf("\t-N don't ask for a password\n");
595 printf("\t-s configfile specify an alternative config file\n");
596 printf("\t-U username set the network username\n");
597 printf("\t-W domain set the domain name for user account\n");
603 int main(int argc
, char *argv
[])
607 extern pstring global_myname
;
608 BOOL got_pass
= False
;
609 BOOL interactive
= True
;
613 servicesf
= CONFIGFILE
;
618 struct cli_state
*cli
;
620 struct cmd_set
**cmd_set
;
621 struct in_addr server_ip
;
623 extern BOOL AllowDebugChange
;
628 AllowDebugChange
= False
;
638 * M. Sweet: getopt() behaves slightly differently on various
639 * platforms. The following loop ensures that the System V,
640 * BSD, and Linux (glibc) implementations work similarly to
641 * allow the server name anywhere on the command-line.
646 while (argc
> optind
) {
647 while ((opt
= getopt(argc
, argv
, "A:s:Nd:U:W:c:l:h")) != EOF
) {
650 /* only get the username, password, and domain from the file */
651 read_authfile (optarg
, username
, password
, domain
);
652 if (strlen (password
))
657 pstrcpy(cmdstr
, optarg
);
661 DEBUGLEVEL
= atoi(optarg
);
665 slprintf(logfile
, sizeof(logfile
) - 1, "%s.client", optarg
);
666 lp_set_logfile(logfile
);
675 pstrcpy(servicesf
, optarg
);
680 pstrcpy(username
,optarg
);
681 if ((lp
=strchr(username
,'%'))) {
683 pstrcpy(password
,lp
+1);
685 memset(strchr(optarg
,'%')+1,'X',strlen(password
));
691 pstrcpy(domain
, optarg
);
702 if (strncmp("//", argv
[optind
], 2) == 0 ||
703 strncmp("\\\\", argv
[optind
], 2) == 0)
708 pstrcpy(server
, argv
[optind
]);
718 /* the following functions are part of the Samba debugging
719 facilities. See lib/debug.c */
720 setup_logging("rpcclient", interactive
);
725 charset_initialise();
727 /* Load smb.conf file */
728 /* FIXME! How to get this DEBUGLEVEL to last over lp_load()? */
729 olddebug
= DEBUGLEVEL
;
730 if (!lp_load(servicesf
,True
,False
,False
)) {
731 fprintf(stderr
, "Can't load %s\n", servicesf
);
733 DEBUGLEVEL
= olddebug
;
735 codepage_initialise(lp_client_code_page());
739 get_myname((*global_myname
)?NULL
:global_myname
);
740 strupper(global_myname
);
742 /* Resolve the IP address */
744 if (!resolve_name(server
, &server_ip
, 0x20)) {
745 DEBUG(1,("Unable to resolve %s\n", server
));
751 * from stdin if necessary
755 char *pass
= getpass("Password:");
757 fstrcpy(password
, pass
);
761 if (!strlen(username
) && !got_pass
)
762 get_username(username
);
764 nt_status
= cli_full_connection(&cli
, global_myname
, server
,
768 password
, strlen(password
));
770 if (!NT_STATUS_IS_OK(nt_status
)) {
771 DEBUG(1,("Cannot connect to server. Error was %s\n", nt_errstr(nt_status
)));
775 memset(password
,'X',sizeof(password
));
777 /* Load command lists */
779 cmd_set
= rpcclient_command_list
;
782 add_command_set(*cmd_set
);
783 add_command_set(separator_command
);
787 fetch_machine_sid(cli
);
789 /* Do anything specified with -c */
794 while((cmd
=next_command(&p
)) != NULL
) {
795 process_cmd(cli
, cmd
);
802 /* Loop around accepting commands */
808 slprintf(prompt
, sizeof(prompt
) - 1, "rpcclient $> ");
810 line
= smb_readline(prompt
, NULL
, completion_fn
);
816 process_cmd(cli
, line
);