1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-23 09:57:40 +03:00
Andrew Bartlett eee925861a This change reworkes the connection code for both rpcclient and net new
'net' untility.

This should make it easier to port rpcclient code across to net.

It also allows SPNEGO (the NTLMSSP subsystem in particular) to work, becouse
it kills off the early destruction of the clear-text password.

Andrew Bartlett
-

361 lines
10 KiB
C

/*
Samba Unix/Linux SMB client library
Version 3.0
Distributed SMB/CIFS Server Management Utility
Copyright (C) 2001 Steve French (sfrench@us.ibm.com)
Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
Originally written by Steve and Jim. Largely rewritten by tridge in
November 2001.
Reworked again by abartlet in December 2001
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. */
/*****************************************************/
/* */
/* Distributed SMB/CIFS Server Management Utility */
/* */
/* The intent was to make the syntax similar */
/* to the NET utility (first developed in DOS */
/* with additional interesting & useful functions */
/* added in later SMB server network operating */
/* systems). */
/* */
/*****************************************************/
#include "includes.h"
#include "../utils/net.h"
/***********************************************************************/
/* Beginning of internationalization section. Translatable constants */
/* should be kept in this area and referenced in the rest of the code. */
/* */
/* No functions, outside of Samba or LSB (Linux Standards Base) should */
/* be used (if possible). */
/***********************************************************************/
#define YES_STRING "Yes"
#define NO_STRING "No"
/************************************************************************************/
/* end of internationalization section */
/************************************************************************************/
extern int optind, opterr, optopt;
/* Yes, these buggers are globals.... */
char *opt_requester_name = NULL;
char *opt_host = NULL;
char *opt_password = NULL;
char *opt_user_name = NULL;
char *opt_workgroup = NULL;
int opt_long_list_entries = 0;
int opt_port = 0;
int opt_maxusers = -1;
char *opt_comment = "";
int opt_flags = -1;
int opt_jobid = 0;
char *opt_target_workgroup = NULL;
static BOOL got_pass = False;
static BOOL have_ip = False;
static struct in_addr dest_ip;
/*
run a function from a function table. If not found then
call the specified usage function
*/
int net_run_function(int argc, const char **argv, struct functable *table,
int (*usage_fn)(int argc, const char **argv))
{
int i;
if (argc < 1) {
d_printf("\nUsage: \n");
return usage_fn(argc, argv);
}
for (i=0; table[i].funcname; i++) {
if (StrCaseCmp(argv[0], table[i].funcname) == 0)
return table[i].fn(argc-1, argv+1);
}
d_printf("No command: %s\n", argv[0]);
return usage_fn(argc, argv);
}
/****************************************************************************
connect to \\server\ipc$
****************************************************************************/
static struct cli_state *connect_to_ipc(struct in_addr *server_ip, const char *server_name)
{
struct cli_state *c;
NTSTATUS nt_status;
if (!got_pass) {
char *pass = getpass("Password:");
if (pass) {
opt_password = strdup(pass);
}
}
nt_status = cli_full_connection(&c, opt_requester_name, server_name,
server_ip, opt_port,
"IPC$", "IPC",
opt_user_name, opt_workgroup,
opt_password, strlen(opt_password));
if (NT_STATUS_IS_OK(nt_status)) {
return c;
} else {
DEBUG(1,("Cannot connect to server. Error was %s\n", get_nt_error_msg(nt_status)));
return NULL;
}
}
struct cli_state *net_make_ipc_connection(unsigned flags)
{
char *server_name = opt_host;
struct in_addr server_ip;
struct cli_state *cli;
if (have_ip) {
server_ip = dest_ip;
if (!server_name) {
server_name = strdup(inet_ntoa(dest_ip));
}
} else if (server_name) {
/* resolve the IP address */
if (!resolve_name(server_name, &server_ip, 0x20)) {
DEBUG(1,("Unable to resolve server name\n"));
return NULL;
}
} else if (flags & NET_FLAGS_DMB) {
struct in_addr *ip_list;
int addr_count;
char *our_workgroup = lp_workgroup();
struct in_addr msbrow_ip;
/* if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */
if (!get_dmb_list(&ip_list,&addr_count)){
DEBUG(1,("Unable to resolve global master browser via name lookup"));
if (!resolve_name(our_workgroup, &msbrow_ip, 0x1D)) {
DEBUG(1,("Unable to resolve domain browser via name lookup\n"));
return NULL;
} else {
server_ip = msbrow_ip;
}
} else {
server_ip = *ip_list;
}
} else if (flags & NET_FLAGS_MASTER) {
char *temp_workgroup = lp_workgroup();
char our_workgroup[16];
struct in_addr brow_ips;
/* find target server based on workgroup or domain */
if((temp_workgroup == 0) || (temp_workgroup[0] == 0))
temp_workgroup = lp_workgroup(); /* by default enum our local workgroup or domain */
safe_strcpy(our_workgroup, temp_workgroup,15);
if (!resolve_name(our_workgroup, &brow_ips, 0x1D)) {
/* go looking for workgroups */
DEBUG(1,("Unable to resolve master browser via name lookup\n"));
return NULL;
} else {
server_ip = brow_ips;
}
} else if (!(flags & NET_FLAGS_LOCALHOST_DEFAULT_INSANE)) {
extern struct in_addr loopback_ip;
server_ip = loopback_ip;
server_name = "127.0.0.1";
}
if (!server_name) {
DEBUG(1,("no server to connect to\n"));
return NULL;
}
cli = connect_to_ipc(&server_ip, server_name);
if(!cli) {
d_printf("\nUnable to connect to target server\n");
return NULL;
}
return cli;
}
static int net_usage(int argc, const char **argv)
{
d_printf(" net ads [command]\tto run ADS commands\n"\
" net rap [command]\tto run RAP (pre-RPC) commands\n"\
" net rpc [command]\tto run RPC commands\n"\
" net rap help\n"\
"\nType \"net help <option>\" to get more information on that option\n");
return -1;
}
static int help_usage(int argc, const char **argv)
{
d_printf("\n"\
"Usage: net help <function>\n"\
"\n"\
"Valid functions are:\n"\
" RPC RAP ADS\n");
return -1;
}
/*
handle "net help *" subcommands
*/
static int net_help(int argc, const char **argv)
{
struct functable func[] = {
{"ADS", net_ads_usage},
{"RAP", net_rap_usage},
{"RPC", net_rpc_usage},
{"HELP", help_usage},
{NULL, NULL}};
return net_run_function(argc, argv, func, help_usage);
}
/* main function table */
static struct functable net_func[] = {
{"RPC", net_rpc},
{"RAP", net_rap},
{"ADS", net_ads},
{"HELP", net_help},
{NULL, NULL}
};
/****************************************************************************
main program
****************************************************************************/
int main(int argc, const char **argv)
{
int opt,i;
char *p;
int rc = 0;
int argc_new = 0;
const char ** argv_new;
poptContext pc;
static char *servicesf = dyn_CONFIGFILE;
extern pstring global_myname;
static int debuglevel;
struct poptOption long_options[] = {
{"help", 'h', POPT_ARG_NONE, 0, 'h'},
{"workgroup", 'w', POPT_ARG_STRING, &opt_target_workgroup},
{"myworkgroup", 'W', POPT_ARG_STRING, &opt_workgroup},
{"user", 'U', POPT_ARG_STRING, &opt_user_name, 'U'},
{"ipaddress", 'I', POPT_ARG_STRING, 0, 'I'},
{"port", 'p', POPT_ARG_INT, &opt_port},
{"myname", 'n', POPT_ARG_STRING, &opt_requester_name},
{"conf", 's', POPT_ARG_STRING, &servicesf},
{"debug", 'd', POPT_ARG_INT, &debuglevel, 'd'},
{"debuglevel", 'd', POPT_ARG_INT, &debuglevel, 'd'},
{"server", 'S', POPT_ARG_STRING, &opt_host},
{"comment", 'C', POPT_ARG_STRING, &opt_comment},
{"maxusers", 'M', POPT_ARG_INT, &opt_maxusers},
{"flags", 'F', POPT_ARG_INT, &opt_flags},
{"jobid", 'j', POPT_ARG_INT, &opt_jobid},
{"long", 'l', POPT_ARG_NONE, &opt_long_list_entries},
{ 0, 0, 0, 0}
};
got_pass = 0;
zero_ip(&dest_ip);
dbf = x_stdout;
pc = poptGetContext(NULL, argc, (const char **) argv, long_options,
POPT_CONTEXT_KEEP_FIRST);
while((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
case 'h':
net_usage(argc, argv);
exit(0);
break;
case 'I':
dest_ip = *interpret_addr2(poptGetOptArg(pc));
if (is_zero_ip(dest_ip))
d_printf("\nInvalid ip address specified\n");
else
have_ip = True;
break;
case 'U':
opt_user_name = strdup(opt_user_name);
p = strchr(opt_user_name,'%');
if (p) {
*p = 0;
opt_password = p+1;
got_pass = 1;
}
break;
default:
d_printf("\nInvalid option %c (%d)\n", (char)opt, opt);
net_usage(argc, argv);
}
}
DEBUGLEVEL = debuglevel;
lp_load(servicesf,True,False,False);
argv_new = (const char **)poptGetArgs(pc);
argc_new = argc;
for (i=0; i<argc; i++) {
if (argv_new[i] == NULL) {
argc_new = i;
break;
}
}
if (!opt_requester_name) {
static fstring myname;
get_myname(myname);
opt_requester_name = myname;
}
if (!opt_user_name && getenv("LOGNAME")) {
opt_user_name = getenv("LOGNAME");
}
if (!opt_workgroup) {
opt_workgroup = lp_workgroup();
}
if (!*global_myname) {
char *p2;
fstrcpy(global_myname, myhostname());
p2 = strchr_m(global_myname, '.');
if (p2)
*p2 = 0;
}
load_interfaces();
rc = net_run_function(argc_new-1, argv_new+1, net_func, net_usage);
DEBUG(2,("return code = %d\n", rc));
return rc;
}