diff options
author | Luke Leighton <lkcl@samba.org> | 1998-09-25 21:01:52 +0000 |
---|---|---|
committer | Luke Leighton <lkcl@samba.org> | 1998-09-25 21:01:52 +0000 |
commit | 66d5d73a5d75e88a77970f7b27687b8354ab2e80 (patch) | |
tree | da1b7278847138fc219398238f7a895a1c7f7a82 /source3/rpcclient/rpcclient.c | |
parent | 1631d3fba7b887a5de23241b39430ffb5e036803 (diff) | |
download | samba-66d5d73a5d75e88a77970f7b27687b8354ab2e80.tar.gz samba-66d5d73a5d75e88a77970f7b27687b8354ab2e80.tar.xz samba-66d5d73a5d75e88a77970f7b27687b8354ab2e80.zip |
added rpcclient program
(This used to be commit aa38f39d67fade4dfd7badb7a9b39c833a1dd1ca)
Diffstat (limited to 'source3/rpcclient/rpcclient.c')
-rw-r--r-- | source3/rpcclient/rpcclient.c | 770 |
1 files changed, 770 insertions, 0 deletions
diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c new file mode 100644 index 00000000000..9c7d6f83055 --- /dev/null +++ b/source3/rpcclient/rpcclient.c @@ -0,0 +1,770 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB client + Copyright (C) Andrew Tridgell 1994-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" + +#ifndef REGISTER +#define REGISTER 0 +#endif + +extern pstring scope; + +extern pstring user_socket_options; + + +extern pstring debugf; +extern int DEBUGLEVEL; + + +extern file_info def_finfo; + +#define CNV_LANG(s) dos2unix_format(s,False) +#define CNV_INPUT(s) unix2dos_format(s,True) + +static int process_tok(fstring tok); +static void cmd_help(struct client_info *info); +static void cmd_quit(struct client_info *info); + +static struct cli_state smbcli; +struct cli_state *smb_cli = &smbcli; + +FILE *out_hnd = stdout; + +/**************************************************************************** +initialise smb client structure +****************************************************************************/ +void rpcclient_init(void) +{ + bzero(smb_cli, sizeof(smb_cli)); + cli_initialise(smb_cli); +} + +/**************************************************************************** +make smb client connection +****************************************************************************/ +static BOOL rpcclient_connect(struct client_info *info) +{ + struct nmb_name calling; + struct nmb_name called; + + make_nmb_name(&called , dns_to_netbios_name(info->dest_host ), info->name_type, scope); + make_nmb_name(&calling, dns_to_netbios_name(info->myhostname), 0x0 , scope); + + if (!cli_establish_connection(smb_cli, + info->dest_host, &info->dest_ip, + &calling, &called, + info->share, info->svc_type, + False, True)) + { + DEBUG(0,("rpcclient_connect: connection failed\n")); + cli_shutdown(smb_cli); + return False; + } + + return True; +} + +/**************************************************************************** +stop the smb connection(s?) +****************************************************************************/ +static void rpcclient_stop(void) +{ + cli_shutdown(smb_cli); +} +/**************************************************************************** + This defines the commands supported by this client + ****************************************************************************/ +struct +{ + char *name; + void (*fn)(struct client_info*); + char *description; +} commands[] = +{ +#if 0 + {"ntlogin", cmd_netlogon_login_test, "<username> NT Domain login test"}, + {"wksinfo", cmd_wks_query_info, "DCE/RPC - Workstation Query Info"}, + {"srvinfo", cmd_srv_query_info, "DCE/RPC - Server Query Info"}, + {"srvsessions",cmd_srv_enum_sess, "DCE/RPC - List sessions on a server"}, + {"srvshares", cmd_srv_enum_shares, "DCE/RPC - List shares on a server"}, + {"srvconnections",cmd_srv_enum_conn, "DCE/RPC - List connections on a server"}, + {"srvfiles", cmd_srv_enum_files, "DCE/RPC - List files on a server"}, +#endif + {"lsaquery", cmd_lsa_query_info, "Query Info Policy (domain member or server)"}, +#if 0 + {"enumusers", cmd_sam_enum_users, "SAM User Database Query (experimental!)"}, + {"samuser", cmd_sam_query_user, "<username> SAM User Query (experimental!)"}, + {"samtest", cmd_sam_test , "SAM User Encrypted RPC test (experimental!)"}, + {"enumaliases",cmd_sam_enum_aliases, "SAM Aliases Database Query (experimental!)"}, +#endif +#if 0 + {"enumgroups", cmd_sam_enum_groups, "SAM Group Database Query (experimental!)"}, +#endif +#if 0 + {"samgroups", cmd_sam_query_groups, "SAM Group Database Query (experimental!)"}, +#endif + {"quit", cmd_quit, "logoff the server"}, + {"q", cmd_quit, "logoff the server"}, + {"exit", cmd_quit, "logoff the server"}, + {"bye", cmd_quit, "logoff the server"}, + {"help", cmd_help, "[command] give help on a command"}, + {"?", cmd_help, "[command] give help on a command"}, + {"!", NULL, "run a shell command on the local system"}, + {"", NULL, NULL} +}; + + +/**************************************************************************** +do a (presumably graceful) quit... +****************************************************************************/ +static void cmd_quit(struct client_info *info) +{ + rpcclient_stop(); +#ifdef MEM_MAN + { + extern FILE* dbf; + smb_mem_write_status(dbf); + smb_mem_write_errors(dbf); + smb_mem_write_verbose(dbf); + } +#endif + exit(0); +} + +/**************************************************************************** +help +****************************************************************************/ +static void cmd_help(struct client_info *info) +{ + int i=0,j; + fstring buf; + + if (next_token(NULL,buf,NULL, sizeof(buf))) + { + if ((i = process_tok(buf)) >= 0) + fprintf(out_hnd, "HELP %s:\n\t%s\n\n",commands[i].name,commands[i].description); + } + else + while (commands[i].description) + { + for (j=0; commands[i].description && (j<5); j++) { + fprintf(out_hnd, "%-15s",commands[i].name); + i++; + } + fprintf(out_hnd, "\n"); + } +} + +/******************************************************************* + lookup a command string in the list of commands, including + abbreviations + ******************************************************************/ +static int process_tok(fstring tok) +{ + int i = 0, matches = 0; + int cmd=0; + int tok_len = strlen(tok); + + while (commands[i].fn != NULL) + { + if (strequal(commands[i].name,tok)) + { + matches = 1; + cmd = i; + break; + } + else if (strnequal(commands[i].name, tok, tok_len)) + { + matches++; + cmd = i; + } + i++; + } + + if (matches == 0) + return(-1); + else if (matches == 1) + return(cmd); + else + return(-2); +} + +/**************************************************************************** +wait for keyboard activity, swallowing network packets +****************************************************************************/ +static void wait_keyboard(struct cli_state *cli) +{ + fd_set fds; + int selrtn; + struct timeval timeout; + + while (1) + { + FD_ZERO(&fds); + FD_SET(cli->fd,&fds); + FD_SET(fileno(stdin),&fds); + + timeout.tv_sec = 20; + timeout.tv_usec = 0; + selrtn = sys_select(MAX(cli->fd,fileno(stdin))+1,&fds,&timeout); + + if (FD_ISSET(fileno(stdin),&fds)) + return; + + /* We deliberately use receive_smb instead of + client_receive_smb as we want to receive + session keepalives and then drop them here. + */ + if (FD_ISSET(cli->fd,&fds)) + receive_smb(cli->fd,cli->inbuf,0); + } +} + +/**************************************************************************** + process commands from the client +****************************************************************************/ +static void do_command(struct client_info *info, char *tok, char *line) +{ + int i; + + if ((i = process_tok(tok)) >= 0) + { + commands[i].fn(info); + } + else if (i == -2) + { + fprintf(out_hnd, "%s: command abbreviation ambiguous\n", CNV_LANG(tok)); + } + else + { + fprintf(out_hnd, "%s: command not found\n", CNV_LANG(tok)); + } +} + +/**************************************************************************** + process commands from the client +****************************************************************************/ +static BOOL process( struct client_info *info, char *cmd_str) +{ + extern FILE *dbf; + pstring line; + char *cmd = cmd_str; + + if (cmd[0] != '\0') while (cmd[0] != '\0') + { + char *p; + fstring tok; + + if ((p = strchr(cmd, ';')) == 0) + { + strncpy(line, cmd, 999); + line[1000] = '\0'; + cmd += strlen(cmd); + } + else + { + if (p - cmd > 999) p = cmd + 999; + strncpy(line, cmd, p - cmd); + line[p - cmd] = '\0'; + cmd = p + 1; + } + + /* input language code to internal one */ + CNV_INPUT (line); + + /* get the first part of the command */ + { + char *ptr = line; + if (!next_token(&ptr,tok,NULL, sizeof(tok))) continue; + } + + do_command(info, tok, line); + } + else while (!feof(stdin)) + { + fstring tok; + + /* display a prompt */ + fprintf(out_hnd, "smb: %s> ", CNV_LANG(info->cur_dir)); + fflush(out_hnd); + +#ifdef CLIX + line[0] = wait_keyboard(smb_cli); + /* this might not be such a good idea... */ + if ( line[0] == EOF) + { + break; + } +#else + wait_keyboard(smb_cli); +#endif + + /* and get a response */ +#ifdef CLIX + fgets( &line[1],999, stdin); +#else + if (!fgets(line,1000,stdin)) + { + break; + } +#endif + + /* input language code to internal one */ + CNV_INPUT (line); + + /* special case - first char is ! */ + if (*line == '!') + { + system(line + 1); + continue; + } + + fprintf(out_hnd, "%s\n", line); + + /* get the first part of the command */ + { + char *ptr = line; + if (!next_token(&ptr,tok,NULL, sizeof(tok))) continue; + } + + do_command(info, tok, line); + } + + return(True); +} + +/**************************************************************************** +usage on the program +****************************************************************************/ +static void usage(char *pname) +{ + fprintf(out_hnd, "Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ", + pname); + + fprintf(out_hnd, "\nVersion %s\n",VERSION); + fprintf(out_hnd, "\t-p port connect to the specified port\n"); + fprintf(out_hnd, "\t-d debuglevel set the debuglevel\n"); + fprintf(out_hnd, "\t-l log basename. Basename for log/debug files\n"); + fprintf(out_hnd, "\t-n netbios name. Use this name as my netbios name\n"); + fprintf(out_hnd, "\t-N don't ask for a password\n"); + fprintf(out_hnd, "\t-m max protocol set the max protocol level\n"); + fprintf(out_hnd, "\t-I dest IP use this IP to connect to\n"); + fprintf(out_hnd, "\t-E write messages to stderr instead of stdout\n"); + fprintf(out_hnd, "\t-U username set the network username\n"); + fprintf(out_hnd, "\t-W workgroup set the workgroup name\n"); + fprintf(out_hnd, "\t-c command string execute semicolon separated commands\n"); + fprintf(out_hnd, "\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"); + fprintf(out_hnd, "\n"); +} + +enum client_action +{ + CLIENT_NONE, + CLIENT_IPC, + CLIENT_SVC +}; + +/**************************************************************************** + main program +****************************************************************************/ + int main(int argc,char *argv[]) +{ + char *pname = argv[0]; + int port = SMB_PORT; + int opt; + extern FILE *dbf; + extern char *optarg; + extern int optind; + static pstring servicesf = CONFIGFILE; + pstring term_code; + char *p; + BOOL got_pass = False; + char *cmd_str=""; + int myumask = 0755; + enum client_action cli_action = CLIENT_NONE; + int ret = 0; + + struct client_info cli_info; + + pstring password; /* local copy only, if one is entered */ + pstring tmp; + + rpcclient_init(); + +#ifdef KANJI + pstrcpy(term_code, KANJI); +#else /* KANJI */ + *term_code = 0; +#endif /* KANJI */ + + DEBUGLEVEL = 2; + + cli_info.put_total_size = 0; + cli_info.put_total_time_ms = 0; + cli_info.get_total_size = 0; + cli_info.get_total_time_ms = 0; + + cli_info.dir_total = 0; + cli_info.newer_than = 0; + cli_info.archive_level = 0; + cli_info.print_mode = 1; + + cli_info.translation = False; + cli_info.recurse_dir = False; + cli_info.lowercase = False; + cli_info.prompt = True; + cli_info.abort_mget = True; + + cli_info.dest_ip.s_addr = 0; + cli_info.name_type = 0x20; + + pstrcpy(cli_info.cur_dir , "\\"); + pstrcpy(cli_info.file_sel, ""); + pstrcpy(cli_info.base_dir, ""); + pstrcpy(smb_cli->domain, ""); + pstrcpy(smb_cli->user_name, ""); + pstrcpy(cli_info.myhostname, ""); + pstrcpy(cli_info.dest_host, ""); + + pstrcpy(cli_info.svc_type, "A:"); + pstrcpy(cli_info.share, ""); + pstrcpy(cli_info.service, ""); + + pstrcpy(cli_info.dom.level3_sid, ""); + pstrcpy(cli_info.dom.level3_dom, ""); + pstrcpy(cli_info.dom.level5_sid, ""); + pstrcpy(cli_info.dom.level5_dom, ""); + + smb_cli->nt_pipe_fnum = 0xffff; + + setup_logging(pname, True); + + TimeInit(); + charset_initialise(); + + myumask = umask(0); + umask(myumask); + + if (getenv("USER")) + { + pstrcpy(smb_cli->user_name,getenv("USER")); + + /* modification to support userid%passwd syntax in the USER var + 25.Aug.97, jdblair@uab.edu */ + + if ((p=strchr(smb_cli->user_name,'%'))) + { + *p = 0; + pstrcpy(password,p+1); + got_pass = True; + memset(strchr(getenv("USER"),'%')+1,'X',strlen(password)); + } + strupper(smb_cli->user_name); + } + + password[0] = 0; + + /* modification to support PASSWD environmental var + 25.Aug.97, jdblair@uab.edu */ + if (getenv("PASSWD")) + { + pstrcpy(password,getenv("PASSWD")); + } + + if (*smb_cli->user_name == 0 && getenv("LOGNAME")) + { + pstrcpy(smb_cli->user_name,getenv("LOGNAME")); + strupper(smb_cli->user_name); + } + + if (argc < 2) + { + usage(pname); + exit(1); + } + + if (*argv[1] != '-') + { + + pstrcpy(cli_info.service, argv[1]); + /* Convert any '/' characters in the service name to '\' characters */ + string_replace( cli_info.service, '/','\\'); + argc--; + argv++; + + DEBUG(1,("service: %s\n", cli_info.service)); + + if (count_chars(cli_info.service,'\\') < 3) + { + usage(pname); + printf("\n%s: Not enough '\\' characters in service\n", cli_info.service); + exit(1); + } + + /* + if (count_chars(cli_info.service,'\\') > 3) + { + usage(pname); + printf("\n%s: Too many '\\' characters in service\n", cli_info.service); + exit(1); + } + */ + + if (argc > 1 && (*argv[1] != '-')) + { + got_pass = True; + pstrcpy(password,argv[1]); + memset(argv[1],'X',strlen(argv[1])); + argc--; + argv++; + } + + cli_action = CLIENT_SVC; + } + + while ((opt = getopt(argc, argv,"s:B:O:M:S:i:N:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF) + { + switch (opt) + { + case 'm': + { + int max_protocol = interpret_protocol(optarg,max_protocol); + fprintf(stderr, "max protocol not currently supported\n"); + break; + } + + case 'O': + { + pstrcpy(user_socket_options,optarg); + break; + } + + case 'S': + { + pstrcpy(cli_info.dest_host,optarg); + strupper(cli_info.dest_host); + cli_action = CLIENT_IPC; + break; + } + + case 'B': + { + iface_set_default(NULL,optarg,NULL); + break; + } + + case 'i': + { + pstrcpy(scope, optarg); + break; + } + + case 'U': + { + char *lp; + pstrcpy(smb_cli->user_name,optarg); + if ((lp=strchr(smb_cli->user_name,'%'))) + { + *lp = 0; + pstrcpy(password,lp+1); + got_pass = True; + memset(strchr(optarg,'%')+1,'X',strlen(password)); + } + break; + } + + case 'W': + { + pstrcpy(smb_cli->domain,optarg); + break; + } + + case 'E': + { + dbf = stderr; + break; + } + + case 'I': + { + cli_info.dest_ip = *interpret_addr2(optarg); + if (zero_ip(cli_info.dest_ip)) + { + exit(1); + } + break; + } + + case 'N': + { + got_pass = True; + break; + } + + case 'd': + { + if (*optarg == 'A') + DEBUGLEVEL = 10000; + else + DEBUGLEVEL = atoi(optarg); + break; + } + + case 'l': + { + slprintf(debugf, sizeof(debugf)-1, + "%s.client",optarg); + break; + } + + case 'p': + { + port = atoi(optarg); + break; + } + + case 'c': + { + cmd_str = optarg; + got_pass = True; + break; + } + + case 'h': + { + usage(pname); + exit(0); + break; + } + + case 's': + { + pstrcpy(servicesf, optarg); + break; + } + + case 't': + { + pstrcpy(term_code, optarg); + break; + } + + default: + { + usage(pname); + exit(1); + break; + } + } + } + + if (cli_action == CLIENT_NONE) + { + usage(pname); + exit(1); + } + + DEBUG(3,("%s client started (version %s)\n",timestring(),VERSION)); + + if (!get_myname(cli_info.myhostname, NULL)) + { + fprintf(stderr, "Failed to get my hostname.\n"); + } + + if (!lp_load(servicesf,True, False, False)) + { + fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf); + } + + codepage_initialise(lp_client_code_page()); + + if (*smb_cli->domain == 0) pstrcpy(smb_cli->domain,lp_workgroup()); + + load_interfaces(); + + if (cli_action == CLIENT_IPC) + { + pstrcpy(cli_info.share, "IPC$"); + pstrcpy(cli_info.svc_type, "IPC"); + } + + fstrcpy(cli_info.mach_acct, cli_info.myhostname); + strupper(cli_info.mach_acct); + fstrcat(cli_info.mach_acct, "$"); + + /* set the password cache info */ + if (got_pass) + { + if (password[0] == 0) + { + pwd_set_nullpwd(&(smb_cli->pwd)); + } + else + { + pwd_make_lm_nt_16(&(smb_cli->pwd), password); /* generate 16 byte hashes */ + } + } + else + { + pwd_read(&(smb_cli->pwd), "Enter Password:", True); + } + + /* paranoia: destroy the local copy of the password */ + bzero(password, sizeof(password)); + + /* establish connections. nothing to stop these being re-established. */ + rpcclient_connect(&cli_info); + + DEBUG(5,("rpcclient_connect: smb_cli->fd:%d\n", smb_cli->fd)); + if (smb_cli->fd <= 0) + { + fprintf(stderr, "warning: connection could not be established to %s<%02x>\n", + cli_info.dest_host, cli_info.name_type); + fprintf(stderr, "this version of smbclient may crash if you proceed\n"); + exit(-1); + } + + ret = 0; + + switch (cli_action) + { + case CLIENT_IPC: + { + ret = process(&cli_info, cmd_str) ? 0 : 1; + break; + } + + default: + { + fprintf(stderr, "unknown client action requested\n"); + ret = 1; + break; + } + } + + rpcclient_stop(); + + return(0); +} |