mirror of
https://github.com/samba-team/samba.git
synced 2024-12-29 11:21:54 +03:00
08e73efdbc
the password was being set to "" instead of NULL.
..and yes Elrond, I'll merge this into TNG.
P
jerry
(This used to be commit cc611ecc67
)
1406 lines
28 KiB
C
1406 lines
28 KiB
C
/*
|
|
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"
|
|
#include "rpc_parse.h"
|
|
#include "rpc_client.h"
|
|
|
|
#ifndef REGISTER
|
|
#define REGISTER 0
|
|
#endif
|
|
|
|
extern pstring debugf;
|
|
extern pstring global_myname;
|
|
|
|
extern pstring user_socket_options;
|
|
|
|
/* found in rpc_client/cli_connect.c */
|
|
extern struct user_creds *usr_creds;
|
|
|
|
|
|
extern int DEBUGLEVEL;
|
|
|
|
|
|
#define CNV_LANG(s) dos2unix_format(s,False)
|
|
#define CNV_INPUT(s) unix2dos_format(s,True)
|
|
|
|
static int process_tok(fstring tok);
|
|
static uint32 cmd_help(struct client_info *info, int argc, char *argv[]);
|
|
static uint32 cmd_quit(struct client_info *info, int argc, char *argv[]);
|
|
static uint32 cmd_set(struct client_info *info, int argc, char *argv[]);
|
|
static uint32 cmd_use(struct client_info *info, int argc, char *argv[]);
|
|
|
|
static struct user_creds usr;
|
|
|
|
struct client_info cli_info;
|
|
|
|
char **cmd_argv = NULL;
|
|
uint32 cmd_argc = 0;
|
|
|
|
FILE *out_hnd;
|
|
|
|
|
|
static void cmd_set_free(struct command_set *item)
|
|
{
|
|
if (item != NULL)
|
|
{
|
|
safe_free(item->name);
|
|
}
|
|
safe_free(item);
|
|
}
|
|
|
|
static struct command_set *cmd_set_dup(const struct command_set *from)
|
|
{
|
|
if (from != NULL)
|
|
{
|
|
struct command_set *copy =
|
|
(struct command_set
|
|
*)malloc(sizeof(struct command_set));
|
|
if (copy != NULL)
|
|
{
|
|
memcpy(copy, from, sizeof(struct command_set));
|
|
if (from->name != NULL)
|
|
{
|
|
copy->name = strdup(from->name);
|
|
}
|
|
}
|
|
return copy;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void free_cmd_set_array(uint32 num_entries, struct command_set **entries)
|
|
{
|
|
void (*fn) (void *) = (void (*)(void *))&cmd_set_free;
|
|
free_void_array(num_entries, (void **)entries, *fn);
|
|
}
|
|
|
|
struct command_set *add_cmd_set_to_array(uint32 *len,
|
|
struct command_set ***array,
|
|
const struct command_set *cmd)
|
|
{
|
|
void *(*fn) (const void *) = (void *(*)(const void *))&cmd_set_dup;
|
|
return (struct command_set *)add_copy_to_array(len,
|
|
(void ***)array,
|
|
(const void *)cmd, *fn,
|
|
False);
|
|
|
|
}
|
|
|
|
static struct command_set **commands = NULL;
|
|
static uint32 num_commands = 0;
|
|
|
|
/****************************************************************************
|
|
add in individual command-sets.
|
|
****************************************************************************/
|
|
void add_command_set(const struct command_set *cmds)
|
|
{
|
|
while (! ((cmds->fn==NULL) && (strlen(cmds->name)==0)))
|
|
{
|
|
add_cmd_set_to_array(&num_commands, &commands, cmds);
|
|
cmds++;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
This defines the commands supported by this client
|
|
****************************************************************************/
|
|
static struct command_set general_commands[] = {
|
|
/*
|
|
* maintenance
|
|
*/
|
|
|
|
{"General", NULL, NULL, {NULL, NULL}},
|
|
|
|
{ "set", cmd_set,
|
|
"run rpcclient inside rpcclient (change options etc.)",
|
|
{NULL, NULL}
|
|
},
|
|
|
|
{ "use", cmd_use,
|
|
"net use and net view",
|
|
{NULL, NULL}
|
|
},
|
|
|
|
/*
|
|
* bye bye
|
|
*/
|
|
|
|
{ "quit", cmd_quit,
|
|
"logoff the server",
|
|
{NULL, NULL}
|
|
},
|
|
{ "q", cmd_quit,
|
|
"logoff the server",
|
|
{NULL, NULL}
|
|
},
|
|
{ "exit", cmd_quit,
|
|
"logoff the server",
|
|
{NULL, NULL}
|
|
},
|
|
{ "bye", cmd_quit,
|
|
"logoff the server",
|
|
{NULL, NULL}
|
|
},
|
|
|
|
/*
|
|
* eek!
|
|
*/
|
|
|
|
{ "help", cmd_help,
|
|
"[command] give help on a command",
|
|
{NULL, NULL}
|
|
},
|
|
{ "?", cmd_help,
|
|
"[command] give help on a command",
|
|
{NULL, NULL}
|
|
},
|
|
|
|
/*
|
|
* shell
|
|
*/
|
|
|
|
{ "!", NULL,
|
|
"run a shell command on the local system",
|
|
{NULL, NULL}
|
|
},
|
|
|
|
/*
|
|
* oop!
|
|
*/
|
|
|
|
{ "", NULL, NULL,
|
|
{NULL, NULL}
|
|
}
|
|
};
|
|
|
|
|
|
/****************************************************************************
|
|
do a (presumably graceful) quit...
|
|
****************************************************************************/
|
|
static uint32 cmd_quit(struct client_info *info, int argc, char *argv[])
|
|
{
|
|
#ifdef MEM_MAN
|
|
{
|
|
extern FILE *dbf;
|
|
smb_mem_write_status(dbf);
|
|
smb_mem_write_errors(dbf);
|
|
smb_mem_write_verbose(dbf);
|
|
dbgflush();
|
|
}
|
|
#endif
|
|
|
|
free_connections();
|
|
exit(0);
|
|
/* NOTREACHED */
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
help
|
|
****************************************************************************/
|
|
static uint32 cmd_help(struct client_info *info, int argc, char *argv[])
|
|
{
|
|
int i = 0;
|
|
|
|
/* get help on a specific command */
|
|
if (argc > 0)
|
|
{
|
|
if ((i = process_tok(argv[1])) >= 0)
|
|
{
|
|
fprintf(out_hnd, "HELP %s:\n\t%s\n\n",
|
|
commands[i]->name, commands[i]->description);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Print out the list of available commands */
|
|
for (i = 0; i < num_commands; i++)
|
|
{
|
|
if (commands[i]->fn == NULL)
|
|
fprintf (out_hnd, "\n");
|
|
else
|
|
fprintf (out_hnd, "\t");
|
|
|
|
fprintf(out_hnd, "%s\n", commands[i]->name);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*******************************************************************
|
|
lookup a command string in the list of commands, including
|
|
abbreviations
|
|
******************************************************************/
|
|
static int process_tok(char *tok)
|
|
{
|
|
int i = 0, matches = 0;
|
|
int cmd = 0;
|
|
int tok_len = strlen(tok);
|
|
|
|
for (i = 0; i < num_commands; i++)
|
|
{
|
|
if (strequal(commands[i]->name, tok))
|
|
{
|
|
matches = 1;
|
|
cmd = i;
|
|
break;
|
|
}
|
|
else if (strnequal(commands[i]->name, tok, tok_len))
|
|
{
|
|
matches++;
|
|
cmd = i;
|
|
}
|
|
}
|
|
|
|
if (matches == 0)
|
|
return (-1);
|
|
else if (matches == 1)
|
|
return (cmd);
|
|
else
|
|
return (-2);
|
|
}
|
|
|
|
/****************************************************************************
|
|
turn command line into command argument array
|
|
****************************************************************************/
|
|
static BOOL get_cmd_args(char *line)
|
|
{
|
|
char *ptr = line;
|
|
pstring tok;
|
|
cmd_argc = 0;
|
|
cmd_argv = NULL;
|
|
|
|
/* get the first part of the command */
|
|
if (!next_token(&ptr, tok, NULL, sizeof(tok)))
|
|
{
|
|
return False;
|
|
}
|
|
|
|
do
|
|
{
|
|
add_chars_to_array(&cmd_argc, &cmd_argv, tok);
|
|
}
|
|
while (next_token(NULL, tok, NULL, sizeof(tok)));
|
|
|
|
add_chars_to_array(&cmd_argc, &cmd_argv, NULL);
|
|
|
|
return True;
|
|
}
|
|
|
|
/* command options mask */
|
|
static uint32 cmd_set_options = 0xffffffff;
|
|
|
|
/****************************************************************************
|
|
process commands from the client
|
|
****************************************************************************/
|
|
static uint32 do_command(struct client_info *info, char *line)
|
|
{
|
|
uint32 status = 0x0;
|
|
int i;
|
|
|
|
if (!get_cmd_args(line))
|
|
return False;
|
|
|
|
if (cmd_argc == 0)
|
|
{
|
|
return False;
|
|
}
|
|
|
|
i = process_tok(cmd_argv[0]);
|
|
if (i >= 0)
|
|
{
|
|
int argc = ((int)cmd_argc)-1;
|
|
char **argv = cmd_argv;
|
|
optind = 0;
|
|
|
|
status = commands[i]->fn(info, argc, argv);
|
|
}
|
|
else if (i == -2)
|
|
{
|
|
fprintf(out_hnd, "%s: command abbreviation ambiguous\n",
|
|
CNV_LANG(cmd_argv[0]));
|
|
}
|
|
else
|
|
{
|
|
fprintf(out_hnd, "%s: command not found\n",
|
|
CNV_LANG(cmd_argv[0]));
|
|
}
|
|
|
|
free_char_array(cmd_argc, cmd_argv);
|
|
parse_talloc_free(); /* Free up init_XXX memory. */
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
process commands from the client
|
|
****************************************************************************/
|
|
static uint32 process(struct client_info *info, char *cmd_str)
|
|
{
|
|
uint32 status = 0;
|
|
pstring line;
|
|
char *cmd = cmd_str;
|
|
|
|
if (cmd != NULL)
|
|
{
|
|
while (cmd[0] != '\0')
|
|
{
|
|
char *p;
|
|
|
|
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);
|
|
|
|
status = do_command(info, line);
|
|
if (status == 0x0)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (!feof(stdin))
|
|
{
|
|
#ifdef HAVE_LIBREADLINE
|
|
char *ret_line;
|
|
#endif
|
|
pstring pline;
|
|
BOOL at_sym = False;
|
|
|
|
pline[0] = 0;
|
|
if (info->show_prompt)
|
|
{
|
|
safe_strcat(pline, "[", sizeof(pline) - 1);
|
|
if (usr.ntc.domain[0] != 0)
|
|
{
|
|
safe_strcat(pline, usr.ntc.domain,
|
|
sizeof(pline) - 1);
|
|
safe_strcat(pline, "\\", sizeof(pline) - 1);
|
|
at_sym = True;
|
|
}
|
|
if (usr.ntc.user_name[0] != 0)
|
|
{
|
|
safe_strcat(pline, usr.ntc.user_name,
|
|
sizeof(pline) - 1);
|
|
at_sym = True;
|
|
}
|
|
if (at_sym)
|
|
safe_strcat(pline, "@", sizeof(pline) - 1);
|
|
|
|
safe_strcat(pline, cli_info.dest_host,
|
|
sizeof(pline) - 1);
|
|
safe_strcat(pline, "]$ ", sizeof(pline) - 1);
|
|
}
|
|
#ifndef HAVE_LIBREADLINE
|
|
|
|
/* display a prompt */
|
|
fprintf(out_hnd, "%s", CNV_LANG(pline));
|
|
fflush(out_hnd);
|
|
|
|
cli_use_wait_keyboard();
|
|
|
|
/* and get a response */
|
|
if (!fgets(line, 1000, stdin))
|
|
{
|
|
break;
|
|
}
|
|
|
|
#else /* HAVE_LIBREADLINE */
|
|
|
|
if (!(ret_line = readline(pline)))
|
|
break;
|
|
safe_free(ret_line);
|
|
|
|
/* Copy read line to samba buffer */
|
|
|
|
pstrcpy(line, rl_line_buffer);
|
|
|
|
/* Add to history */
|
|
|
|
if (strlen(line) > 0)
|
|
add_history(line);
|
|
#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);
|
|
|
|
status = do_command(info, line);
|
|
if (status == 0x0)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/****************************************************************************
|
|
usage on the program
|
|
****************************************************************************/
|
|
static void usage(char *pname)
|
|
{
|
|
fprintf(out_hnd,
|
|
"Usage: %s [\\server] [password] [-U user] -[W domain] [-l log] ",
|
|
pname);
|
|
|
|
fprintf(out_hnd, "\nVersion %s\n", VERSION);
|
|
fprintf(out_hnd, "\t-d debuglevel set the debuglevel\n");
|
|
fprintf(out_hnd,
|
|
"\t-S <\\>server Server to connect to\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-A filename file from which to read the authentication credentials\n");
|
|
fprintf(out_hnd,
|
|
"\t-P hide prompt (used for shell scripts)\n");
|
|
fprintf(out_hnd,
|
|
"\t-U username set the network username\n");
|
|
fprintf(out_hnd,
|
|
"\t-U username%%pass set the network username and password\n");
|
|
fprintf(out_hnd, "\t-W domain set the domain 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");
|
|
}
|
|
|
|
#ifdef HAVE_LIBREADLINE
|
|
|
|
/****************************************************************************
|
|
GNU readline completion functions
|
|
****************************************************************************/
|
|
|
|
/* Complete an rpcclient command */
|
|
|
|
static char *complete_cmd(char *text, int state)
|
|
{
|
|
static int cmd_index;
|
|
char *name;
|
|
|
|
/* Initialise */
|
|
|
|
if (state == 0)
|
|
{
|
|
cmd_index = 0;
|
|
}
|
|
|
|
/* Return the next name which partially matches the list of commands */
|
|
|
|
while ((cmd_index < num_commands)
|
|
&& (strlen(name = commands[cmd_index++]->name) > 0))
|
|
{
|
|
if (strncmp(name, text, strlen(text)) == 0)
|
|
{
|
|
return strdup(name);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* Main completion function */
|
|
|
|
static char **completion_fn(char *text, int start, int end)
|
|
{
|
|
pstring cmd_partial;
|
|
int cmd_index;
|
|
int num_words;
|
|
|
|
int i;
|
|
char lastch = ' ';
|
|
|
|
(void)get_cmd_args(rl_line_buffer);
|
|
|
|
safe_strcpy(cmd_partial, rl_line_buffer,
|
|
MAX(sizeof(cmd_partial), end) - 1);
|
|
|
|
/* Complete rpcclient command */
|
|
|
|
if (start == 0)
|
|
{
|
|
return completion_matches(text, complete_cmd);
|
|
}
|
|
|
|
/* Count # of words in command */
|
|
|
|
num_words = 0;
|
|
for (i = 0; i <= end; i++)
|
|
{
|
|
if ((rl_line_buffer[i] != ' ') && (lastch == ' '))
|
|
{
|
|
num_words++;
|
|
}
|
|
lastch = rl_line_buffer[i];
|
|
}
|
|
|
|
if (rl_line_buffer[end] == ' ')
|
|
num_words++;
|
|
|
|
/* Work out which command we are completing for */
|
|
|
|
for (cmd_index = 0; cmd_index < num_commands; cmd_index++)
|
|
{
|
|
|
|
/* Check each command in array */
|
|
|
|
if (strncmp(rl_line_buffer, commands[cmd_index]->name,
|
|
strlen(commands[cmd_index]->name)) == 0)
|
|
{
|
|
|
|
/* Call appropriate completion function */
|
|
|
|
if (num_words == 2 || num_words == 3)
|
|
{
|
|
char *(*fn) (char *, int);
|
|
fn =
|
|
commands[cmd_index]->compl_args
|
|
[num_words - 2];
|
|
if (fn != NULL)
|
|
{
|
|
return completion_matches(text, fn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Eeek! */
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* To avoid filename completion being activated when no valid
|
|
completions are found, we assign this stub completion function
|
|
to the rl_completion_entry_function variable. */
|
|
|
|
static char *complete_cmd_null(char *text, int state)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#endif /* HAVE_LIBREADLINE */
|
|
|
|
static void set_user_password(struct ntuser_creds *u,
|
|
BOOL got_pass, char *password)
|
|
{
|
|
/* set the password cache info */
|
|
if (got_pass)
|
|
{
|
|
if (password == NULL)
|
|
{
|
|
DEBUG(10, ("set_user_password: NULL pwd\n"));
|
|
pwd_set_nullpwd(&(u->pwd));
|
|
}
|
|
else
|
|
{
|
|
/* generate 16 byte hashes */
|
|
DEBUG(10, ("set_user_password: generate\n"));
|
|
pwd_make_lm_nt_16(&(u->pwd), password);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DEBUG(10, ("set_user_password: read\n"));
|
|
pwd_read(&(u->pwd), "Enter Password:", True);
|
|
}
|
|
}
|
|
|
|
static uint32 cmd_use(struct client_info *info, int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
BOOL net_use = False;
|
|
BOOL net_use_add = True;
|
|
BOOL force_close = False;
|
|
fstring dest_host;
|
|
fstring srv_name;
|
|
BOOL null_pwd = False;
|
|
BOOL got_pwd = False;
|
|
pstring password;
|
|
|
|
|
|
if (usr_creds != NULL)
|
|
{
|
|
copy_nt_creds(&usr.ntc, &usr_creds->ntc);
|
|
}
|
|
else
|
|
{
|
|
copy_nt_creds(&usr.ntc, NULL);
|
|
}
|
|
|
|
pstrcpy(dest_host, cli_info.dest_host);
|
|
pstrcpy(usr.ntc.user_name, optarg);
|
|
info->reuse = False;
|
|
|
|
if (argc <= 1)
|
|
{
|
|
report(out_hnd,
|
|
"net [\\\\Server] [-U user%%pass] [-W domain] [-d] [-f]\n");
|
|
report(out_hnd, " -d Deletes a connection\n");
|
|
report(out_hnd, " -f Forcibly deletes a connection\n");
|
|
report(out_hnd, "net -u Shows all connections\n");
|
|
return 0;
|
|
}
|
|
|
|
if (argc > 1 && (*argv[1] != '-'))
|
|
{
|
|
if (strnequal("\\\\", argv[1], 2) ||
|
|
strnequal("//", argv[1], 2))
|
|
{
|
|
pstrcpy(dest_host, argv[1] + 2);
|
|
}
|
|
argc--;
|
|
argv++;
|
|
}
|
|
|
|
while ((opt = getopt(argc, argv, "udU:W:")) != EOF)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case 'u':
|
|
{
|
|
net_use = True;
|
|
break;
|
|
}
|
|
|
|
case 'U':
|
|
{
|
|
char *lp;
|
|
pstrcpy(usr.ntc.user_name, optarg);
|
|
if ((lp = strchr(usr.ntc.user_name, '%')))
|
|
{
|
|
*lp = 0;
|
|
pstrcpy(password, lp + 1);
|
|
memset(strchr(optarg, '%') + 1, 'X',
|
|
strlen(password));
|
|
got_pwd = True;
|
|
}
|
|
if (usr.ntc.user_name[0] == 0
|
|
&& password[0] == 0)
|
|
{
|
|
null_pwd = True;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 'N':
|
|
{
|
|
null_pwd = True;
|
|
}
|
|
case 'W':
|
|
{
|
|
pstrcpy(usr.ntc.domain, optarg);
|
|
break;
|
|
}
|
|
|
|
case 'd':
|
|
{
|
|
net_use_add = False;
|
|
break;
|
|
}
|
|
|
|
case 'f':
|
|
{
|
|
force_close = True;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
report(out_hnd,
|
|
"net -S \\server [-U user%%pass] [-W domain] [-d] [-f]\n");
|
|
report(out_hnd, "net -u\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (strnequal("\\\\", dest_host, 2))
|
|
{
|
|
fstrcpy(srv_name, dest_host);
|
|
}
|
|
else
|
|
{
|
|
fstrcpy(srv_name, "\\\\");
|
|
fstrcat(srv_name, dest_host);
|
|
}
|
|
strupper(srv_name);
|
|
|
|
if (net_use)
|
|
{
|
|
int i;
|
|
uint32 num_uses;
|
|
struct use_info **use;
|
|
cli_net_use_enum(&num_uses, &use);
|
|
|
|
if (num_uses == 0)
|
|
{
|
|
report(out_hnd, "No connections\n");
|
|
}
|
|
else
|
|
{
|
|
report(out_hnd, "Connections:\n");
|
|
|
|
for (i = 0; i < num_uses; i++)
|
|
{
|
|
if (use[i] != NULL && use[i]->connected)
|
|
{
|
|
report(out_hnd, "Server:\t%s\t",
|
|
use[i]->srv_name);
|
|
report(out_hnd, "Key:\t[%d,%x]\t",
|
|
use[i]->key.pid,
|
|
use[i]->key.vuid);
|
|
report(out_hnd, "User:\t%s\t",
|
|
use[i]->user_name);
|
|
report(out_hnd, "Domain:\t%s\n",
|
|
use[i]->domain);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (net_use_add)
|
|
{
|
|
BOOL isnew;
|
|
if (null_pwd)
|
|
{
|
|
set_user_password(&usr.ntc, True, NULL);
|
|
}
|
|
else
|
|
{
|
|
set_user_password(&usr.ntc, got_pwd, password);
|
|
}
|
|
|
|
/* paranoia: destroy the local copy of the password */
|
|
ZERO_STRUCT(password);
|
|
|
|
report(out_hnd, "Server:\t%s:\tUser:\t%s\tDomain:\t%s\n",
|
|
srv_name, usr.ntc.user_name, usr.ntc.domain);
|
|
report(out_hnd, "Connection:\t");
|
|
|
|
if (cli_net_use_add(srv_name, &usr.ntc,
|
|
info->reuse, &isnew) != NULL)
|
|
{
|
|
report(out_hnd, "OK\n");
|
|
}
|
|
else
|
|
{
|
|
report(out_hnd, "FAILED\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BOOL closed;
|
|
report(out_hnd, "Server:\t%s:\tUser:\t%s\tDomain:\t%s\n",
|
|
srv_name, usr.ntc.user_name, usr.ntc.domain);
|
|
report(out_hnd, "Connection:\t");
|
|
|
|
if (!cli_net_use_del(srv_name, &usr.ntc,
|
|
force_close, &closed))
|
|
{
|
|
report(out_hnd, ": Does not exist\n");
|
|
}
|
|
else if (force_close && closed)
|
|
{
|
|
report(out_hnd, ": Forcibly terminated\n");
|
|
}
|
|
else if (closed)
|
|
{
|
|
report(out_hnd, ": Terminated\n");
|
|
}
|
|
else
|
|
{
|
|
report(out_hnd, ": Unlinked\n");
|
|
}
|
|
}
|
|
|
|
/* paranoia: destroy the local copy of the password */
|
|
ZERO_STRUCT(password);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************
|
|
allow or disallow automatic connections. rpctorture, because it
|
|
does not reestablish connections after sys_fork(), fails unless the
|
|
connection is established AFTER the sys_fork()
|
|
******************************************************************/
|
|
static BOOL auto_connect = True;
|
|
void cmd_set_no_autoconnect(void)
|
|
{
|
|
auto_connect = False;
|
|
}
|
|
|
|
#define CMD_STR 0x1
|
|
#define CMD_DBF 0x2
|
|
#define CMD_SVC 0x4
|
|
#define CMD_TERM 0x8
|
|
#define CMD_PASS 0x10
|
|
#define CMD_USER 0x20
|
|
#define CMD_NOPW 0x40
|
|
#define CMD_DBLV 0x80
|
|
#define CMD_HELP 0x100
|
|
#define CMD_SOCK 0x200
|
|
#define CMD_IFACE 0x400
|
|
#define CMD_DOM 0x800
|
|
#define CMD_IP 0x1000
|
|
#define CMD_HOST 0x2000
|
|
#define CMD_NAME 0x4000
|
|
#define CMD_DBG 0x8000
|
|
#define CMD_SCOPE 0x10000
|
|
#define CMD_INTER 0x20000
|
|
|
|
static uint32 cmd_set(struct client_info *info, int argc, char *argv[])
|
|
{
|
|
BOOL interactive = True;
|
|
char *cmd_str = NULL;
|
|
int opt;
|
|
extern FILE *dbf;
|
|
extern char *optarg;
|
|
static pstring servicesf = CONFIGFILE;
|
|
pstring term_code;
|
|
pstring password; /* local copy only, if one is entered */
|
|
fstring srv_name;
|
|
|
|
password[0] = 0;
|
|
usr_creds = &usr;
|
|
info->reuse = False;
|
|
#ifdef KANJI
|
|
pstrcpy(term_code, KANJI);
|
|
#else /* KANJI */
|
|
*term_code = 0;
|
|
#endif /* KANJI */
|
|
|
|
if (argc > 1 && (*argv[1] != '-'))
|
|
{
|
|
if (strnequal("\\\\", argv[1], 2) ||
|
|
strnequal("//", argv[1], 2))
|
|
{
|
|
cmd_set_options |= CMD_HOST;
|
|
pstrcpy(cli_info.dest_host, argv[1] + 2);
|
|
strupper(cli_info.dest_host);
|
|
}
|
|
argc--;
|
|
argv++;
|
|
}
|
|
if (argc > 1 && (*argv[1] != '-'))
|
|
{
|
|
cmd_set_options |= CMD_PASS;
|
|
pstrcpy(password, argv[1]);
|
|
memset(argv[1], 'X', strlen(argv[1]));
|
|
argc--;
|
|
argv++;
|
|
}
|
|
|
|
while ((opt = getopt(argc, argv,
|
|
"PRs:O:M:S:i:Nn:d:l:hI:EB:U:L:t:m:W:T:D:c:A:")) !=
|
|
EOF)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case 'R':
|
|
{
|
|
info->reuse = True;
|
|
break;
|
|
}
|
|
|
|
case 'm':
|
|
{
|
|
/* FIXME ... max_protocol seems to be funny here */
|
|
|
|
int max_protocol = 0;
|
|
max_protocol =
|
|
interpret_protocol(optarg,
|
|
max_protocol);
|
|
fprintf(stderr,
|
|
"max protocol not currently supported\n");
|
|
break;
|
|
}
|
|
|
|
case 'O':
|
|
{
|
|
cmd_set_options |= CMD_SOCK;
|
|
pstrcpy(user_socket_options, optarg);
|
|
break;
|
|
}
|
|
|
|
case 'S':
|
|
{
|
|
cmd_set_options |= CMD_HOST;
|
|
pstrcpy(cli_info.dest_host, optarg);
|
|
strupper(cli_info.dest_host);
|
|
break;
|
|
}
|
|
|
|
case 'U':
|
|
{
|
|
char *lp;
|
|
cmd_set_options |= CMD_USER;
|
|
pstrcpy(usr.ntc.user_name, optarg);
|
|
if ((lp = strchr(usr.ntc.user_name, '%')))
|
|
{
|
|
*lp = 0;
|
|
pstrcpy(password, lp + 1);
|
|
cmd_set_options |= CMD_PASS;
|
|
memset(lp+1, 'X', strlen(password));
|
|
}
|
|
break;
|
|
}
|
|
case 'A':
|
|
{
|
|
FILE *auth;
|
|
fstring buf;
|
|
uint16 len = 0;
|
|
char *ptr, *val, *param;
|
|
|
|
if ((auth=sys_fopen(optarg, "r")) == NULL)
|
|
{
|
|
/* fail if we can't open the credentials file */
|
|
DEBUG(0,("ERROR: Unable to open credentials file!\n"));
|
|
exit (-1);
|
|
}
|
|
|
|
while (!feof(auth))
|
|
{
|
|
/* get a line from the file */
|
|
if (!fgets (buf, sizeof(buf), auth))
|
|
continue;
|
|
len = strlen(buf);
|
|
|
|
if ((len) && (buf[len-1]=='\n'))
|
|
{
|
|
buf[len-1] = '\0';
|
|
len--;
|
|
}
|
|
if (len == 0)
|
|
continue;
|
|
|
|
/* break up the line into parameter & value.
|
|
will need to eat a little whitespace possibly */
|
|
param = buf;
|
|
if (!(ptr = strchr (buf, '=')))
|
|
continue;
|
|
val = ptr+1;
|
|
*ptr = '\0';
|
|
|
|
/* eat leading white space */
|
|
while ((*val!='\0') && ((*val==' ') || (*val=='\t')))
|
|
val++;
|
|
|
|
if (strwicmp("password", param) == 0)
|
|
{
|
|
pstrcpy(password, val);
|
|
cmd_set_options |= CMD_PASS;
|
|
}
|
|
else if (strwicmp("username", param) == 0)
|
|
{
|
|
pstrcpy(usr.ntc.user_name, val);
|
|
cmd_set_options |= CMD_USER;
|
|
}
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
}
|
|
fclose(auth);
|
|
break;
|
|
}
|
|
|
|
case 'W':
|
|
{
|
|
cmd_set_options |= CMD_DOM;
|
|
pstrcpy(usr.ntc.domain, optarg);
|
|
break;
|
|
}
|
|
|
|
case 'P':
|
|
{ /* optarg == prompt string ? */
|
|
info->show_prompt = False;
|
|
break;
|
|
}
|
|
|
|
case 'E':
|
|
{
|
|
cmd_set_options |= CMD_DBG;
|
|
dbf = stderr;
|
|
break;
|
|
}
|
|
|
|
case 'I':
|
|
{
|
|
cmd_set_options |= CMD_IP;
|
|
cli_info.dest_ip = *interpret_addr2(optarg);
|
|
if (zero_ip(cli_info.dest_ip))
|
|
{
|
|
free_connections();
|
|
exit(1);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 'n':
|
|
{
|
|
cmd_set_options |= CMD_NAME;
|
|
fstrcpy(global_myname, optarg);
|
|
break;
|
|
}
|
|
|
|
case 'N':
|
|
{
|
|
cmd_set_options |= CMD_NOPW | CMD_PASS;
|
|
break;
|
|
}
|
|
|
|
case 'd':
|
|
{
|
|
cmd_set_options |= CMD_DBLV;
|
|
if (*optarg == 'A')
|
|
DEBUGLEVEL = 10000;
|
|
else
|
|
DEBUGLEVEL = atoi(optarg);
|
|
break;
|
|
}
|
|
|
|
case 'l':
|
|
{
|
|
cmd_set_options |= CMD_INTER;
|
|
slprintf(debugf, sizeof(debugf) - 1,
|
|
"%s.client", optarg);
|
|
interactive = False;
|
|
break;
|
|
}
|
|
|
|
case 'c':
|
|
{
|
|
cmd_set_options |= CMD_STR;
|
|
cmd_str = optarg;
|
|
break;
|
|
}
|
|
|
|
case 'h':
|
|
{
|
|
cmd_set_options |= CMD_HELP;
|
|
usage(argv[0]);
|
|
break;
|
|
}
|
|
|
|
case 's':
|
|
{
|
|
cmd_set_options |= CMD_SVC;
|
|
pstrcpy(servicesf, optarg);
|
|
break;
|
|
}
|
|
|
|
case 't':
|
|
{
|
|
cmd_set_options |= CMD_TERM;
|
|
pstrcpy(term_code, optarg);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
cmd_set_options |= CMD_HELP;
|
|
usage(argv[0]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cmd_set_options & CMD_INTER) {
|
|
setup_logging(debugf, interactive);
|
|
if (!interactive)
|
|
reopen_logs();
|
|
}
|
|
|
|
strupper(global_myname);
|
|
fstrcpy(cli_info.myhostname, global_myname);
|
|
|
|
if (cmd_set_options & CMD_SVC) {
|
|
if (!lp_load(servicesf, True, False, False))
|
|
{
|
|
fprintf(stderr,
|
|
"Can't load %s - run testparm to debug it\n",
|
|
servicesf);
|
|
}
|
|
|
|
}
|
|
|
|
if (cmd_set_options & CMD_INTER) {
|
|
load_interfaces();
|
|
}
|
|
|
|
DEBUG(10, ("cmd_set: options: %x\n", cmd_set_options));
|
|
|
|
if (cmd_set_options & CMD_HELP) {
|
|
return 0;
|
|
}
|
|
|
|
/* NULL password if specified or is username is empty */
|
|
if ((cmd_set_options & CMD_NOPW) || (strlen(usr.ntc.user_name) == 0)) {
|
|
set_user_password(&usr.ntc, True, NULL);
|
|
}
|
|
else
|
|
{
|
|
set_user_password(&usr.ntc,
|
|
((cmd_set_options & CMD_PASS) != 0),
|
|
password);
|
|
}
|
|
|
|
/* paranoia: destroy the local copy of the password */
|
|
ZERO_STRUCT(password);
|
|
|
|
if (strcmp(cli_info.dest_host, "*") == 0) {
|
|
/* special case - we want the PDC */
|
|
struct in_addr ip;
|
|
if (!resolve_srv_name(cli_info.dest_host, cli_info.dest_host, &ip)) {
|
|
report(out_hnd, "ERROR: Failed to find the PDC\n");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
fstrcpy(srv_name, "\\\\");
|
|
fstrcat(srv_name, cli_info.dest_host);
|
|
strupper(srv_name);
|
|
|
|
|
|
if (auto_connect && !strequal(srv_name, "\\\\."))
|
|
{
|
|
BOOL isnew;
|
|
report(out_hnd, "Server:\t%s:\tUser:\t%s\tDomain:\t%s\n",
|
|
srv_name, usr.ntc.user_name, usr.ntc.domain);
|
|
report(out_hnd, "Connection:\t");
|
|
|
|
if (cli_net_use_add(srv_name, &usr.ntc, info->reuse, &isnew) != NULL)
|
|
{
|
|
report(out_hnd, "OK\n");
|
|
}
|
|
else
|
|
{
|
|
report(out_hnd, "FAILED\n");
|
|
}
|
|
/* ???? --jerry
|
|
usr_creds = NULL; */
|
|
}
|
|
if (cmd_str != NULL)
|
|
{
|
|
return process(&cli_info, cmd_str);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void read_user_env(struct ntuser_creds *u)
|
|
{
|
|
pstring password;
|
|
|
|
password[0] = 0;
|
|
|
|
if (getenv("USER"))
|
|
{
|
|
char *p;
|
|
pstrcpy(u->user_name, getenv("USER"));
|
|
|
|
/* modification to support userid%passwd syntax in the USER var
|
|
25.Aug.97, jdblair@uab.edu */
|
|
|
|
if ((p = strchr(u->user_name, '%')))
|
|
{
|
|
*p = 0;
|
|
pstrcpy(password, p + 1);
|
|
memset(strchr(getenv("USER"), '%') + 1, 'X',
|
|
strlen(password));
|
|
}
|
|
strupper(u->user_name);
|
|
}
|
|
|
|
/* modification to support PASSWD environmental var
|
|
25.Aug.97, jdblair@uab.edu */
|
|
if (getenv("PASSWD"))
|
|
{
|
|
pstrcpy(password, getenv("PASSWD"));
|
|
}
|
|
|
|
if (*u->user_name == 0 && getenv("LOGNAME"))
|
|
{
|
|
pstrcpy(u->user_name, getenv("LOGNAME"));
|
|
strupper(u->user_name);
|
|
}
|
|
|
|
set_user_password(u, True, password);
|
|
|
|
/* paranoia: destroy the local copy of the password */
|
|
ZERO_STRUCT(password);
|
|
}
|
|
|
|
static void readline_init(void)
|
|
{
|
|
#ifdef HAVE_LIBREADLINE
|
|
/* Initialise GNU Readline */ rl_readline_name = "rpcclient";
|
|
rl_attempted_completion_function = completion_fn;
|
|
rl_completion_entry_function = (Function *) complete_cmd_null;
|
|
|
|
/* Initialise history list */
|
|
|
|
using_history();
|
|
|
|
#else
|
|
int x;
|
|
x = 0; /* stop compiler warnings */
|
|
#endif /* HAVE_LIBREADLINE */
|
|
}
|
|
|
|
/****************************************************************************
|
|
main program
|
|
****************************************************************************/
|
|
int command_main(int argc, char *argv[])
|
|
{
|
|
uint32 status;
|
|
mode_t myumask = 0755;
|
|
char progname[255], path[255], *s;
|
|
pstring msg;
|
|
|
|
DEBUGLEVEL = 2;
|
|
|
|
charset_initialise();
|
|
add_command_set(general_commands);
|
|
|
|
copy_user_creds(&usr, NULL);
|
|
|
|
usr_creds = &usr;
|
|
usr.ptr_ntc = 1;
|
|
|
|
out_hnd = stdout;
|
|
|
|
strncpy(path, argv[0], 255);
|
|
for (s = strtok(path, "/"); s; s = strtok(NULL, "/"))
|
|
fstrcpy(progname, s);
|
|
|
|
slprintf(debugf, sizeof(debugf) - 1,
|
|
"%s/log.%s", LOGFILEBASE, progname);
|
|
|
|
pstrcpy(usr.ntc.domain, "");
|
|
pstrcpy(usr.ntc.user_name, "");
|
|
|
|
pstrcpy(cli_info.myhostname, "");
|
|
pstrcpy(cli_info.dest_host, "");
|
|
cli_info.dest_ip.s_addr = 0;
|
|
|
|
cli_info.show_prompt = True;
|
|
|
|
ZERO_STRUCT(cli_info.dom.level3_sid);
|
|
ZERO_STRUCT(cli_info.dom.level5_sid);
|
|
fstrcpy(cli_info.dom.level3_dom, "");
|
|
fstrcpy(cli_info.dom.level5_dom, "");
|
|
|
|
readline_init();
|
|
TimeInit();
|
|
init_connections();
|
|
|
|
myumask = umask(0);
|
|
umask(myumask);
|
|
|
|
if (!get_myname(global_myname))
|
|
{
|
|
fprintf(stderr, "Failed to get my hostname.\n");
|
|
}
|
|
|
|
if (argc < 2)
|
|
{
|
|
usage(argv[0]);
|
|
free_connections();
|
|
exit(1);
|
|
}
|
|
|
|
read_user_env(&usr.ntc);
|
|
|
|
cmd_set_options &= ~CMD_HELP;
|
|
cmd_set_options &= ~CMD_STR;
|
|
cmd_set_options &= ~CMD_NOPW;
|
|
cmd_set_options &= ~CMD_USER;
|
|
cmd_set_options &= ~CMD_PASS;
|
|
|
|
codepage_initialise(lp_client_code_page());
|
|
|
|
status = cmd_set(&cli_info, argc, argv);
|
|
|
|
if (cmd_set_options & (CMD_HELP|CMD_STR)) {
|
|
free_connections();
|
|
get_safe_nt_error_msg(status, msg, sizeof(msg));
|
|
|
|
report(out_hnd, "Exit Status: %s\n", msg);
|
|
/* unix only has 8 bit error codes - blergh */
|
|
exit(status & 0xFF);
|
|
}
|
|
|
|
DEBUG(3, ("%s client started (version %s)\n",
|
|
timestring(False), VERSION));
|
|
|
|
status = process(&cli_info, NULL);
|
|
|
|
free_connections();
|
|
|
|
free_cmd_set_array(num_commands, commands);
|
|
num_commands = 0;
|
|
commands = NULL;
|
|
|
|
get_safe_nt_error_msg(status, msg, sizeof(msg));
|
|
report(out_hnd, "Exit Status: %s\n", msg);
|
|
|
|
return status;
|
|
}
|