1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

cool! a unix socket smb redirector. code based on smbfilter and

ideas from ssh-agent.

the intent is to be able to share smb sessions using cli_net_use_add()
across multiple processes, where one process knows the target server
name, user name and domain, but not the smb password.
(This used to be commit 294b653f2e)
This commit is contained in:
Luke Leighton 1999-12-03 18:16:08 +00:00
parent 69683dc27a
commit 7d01f964ff
9 changed files with 487 additions and 6 deletions

View File

@ -302,7 +302,8 @@ NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(UBIQX_OBJ) \
DEBUG2HTML_OBJ = utils/debug2html.o $(PARAM_OBJ) $(LIB_OBJ)
SMB_AGENT_OBJ = smb-agent.o $(PARAM_OBJ) $(LIB_OBJ)
SMB_AGENT_OBJ = utils/smb-agent.o $(LIBSMB_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \
$(RPC_PARSE_OBJ2) rpc_client/cli_use.o
SMB_CLIENT_OBJ = smb-client.o $(PARAM_OBJ) $(LIB_OBJ)
@ -481,6 +482,14 @@ bin/rpctorture: $(RPCTORTURE_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(RPCTORTURE_OBJ) $(LDFLAGS) $(LIBS)
bin/smb-client: $(SMB_CLIENT_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(SMB_CLIENT_OBJ) $(LDFLAGS) $(LIBS)
bin/smb-agent: $(SMB_AGENT_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(SMB_AGENT_OBJ) $(LDFLAGS) $(LIBS)
bin/smbfilter: $(SMBFILTER_OBJ) bin/.dummy
@echo Linking $@
@$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS)

View File

@ -126,6 +126,7 @@ struct cli_state
size_t nt_cli_chal_len;
BOOL use_ntlmv2;
BOOL redirect;
uint32 sesskey;
int serverzone;

View File

@ -676,7 +676,8 @@ void unistr2_free(UNISTR2 *name);
/*The following definitions come from libsmb/clientgen.c */
void copy_user_creds(struct user_credentials *to, const struct user_credentials *from);
void copy_user_creds(struct user_credentials *to,
const struct user_credentials *from);
int cli_set_port(struct cli_state *cli, int port);
char *cli_errstr(struct cli_state *cli);
void cli_safe_smb_errstr(struct cli_state *cli, char *msg, size_t len);
@ -852,6 +853,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
/*The following definitions come from libsmb/pwd_cache.c */
void pwd_init(struct pwd_info *pwd);
BOOL pwd_is_nullpwd(const struct pwd_info *pwd);
void pwd_obfuscate_key(struct pwd_info *pwd, uint32 int_key, char *str_key);
BOOL pwd_compare(struct pwd_info *pwd1, struct pwd_info *pwd2);
void pwd_read(struct pwd_info *pwd, char *passwd_report, BOOL do_encrypt);
@ -2184,7 +2186,8 @@ BOOL svc_change_svc_cfg( POLICY_HND *hnd,
void init_cli_use(void);
void free_cli_use(void);
struct cli_state *cli_net_use_add(const char* srv_name,
const struct user_credentials *usr_creds);
const struct user_credentials *usr_creds,
BOOL redir);
BOOL cli_net_use_del(const char* srv_name,
const struct user_credentials *usr_creds,
BOOL force_close,

View File

@ -2930,6 +2930,104 @@ BOOL cli_reestablish_connection(struct cli_state *cli)
return False;
}
static int cli_init_redirect(struct cli_state *cli,
const char* srv_name, struct in_addr *destip,
const struct user_credentials *usr)
{
int sock;
struct sockaddr_un sa;
fstring ip_name;
struct cli_state cli_redir;
pstring data;
uint32 len;
char *p;
char *in = cli->inbuf;
char *out = cli->outbuf;
if (strequal(srv_name, "*SMBSERVER"))
{
fstrcpy(ip_name, "\\\\");
inet_aton(&ip_name[2], destip);
srv_name = ip_name;
}
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
{
DEBUG(0, ("unix socket open failed\n"));
return sock;
}
ZERO_STRUCT(sa);
sa.sun_family = AF_UNIX;
safe_strcpy(sa.sun_path, "/tmp/smb-agent/smb.sock",
sizeof(sa.sun_path)-1);
DEBUG(10, ("socket open succeeded. file name: %s\n", sa.sun_path));
if (connect(sock, (struct sockaddr*) &sa, sizeof(sa)) < 0)
{
DEBUG(0,("socket connect to %s failed\n", sa.sun_path));
close(sock);
return False;
}
DEBUG(10,("connect succeeded\n"));
ZERO_STRUCT(data);
p = &data[4];
safe_strcpy(p, srv_name, 16);
p = skip_string(p, 1);
safe_strcpy(p, usr != NULL ? usr->user_name : "", 16);
p = skip_string(p, 1);
safe_strcpy(p, usr != NULL ? usr->domain : "", 16);
p = skip_string(p, 1);
if (usr != NULL && !pwd_is_nullpwd(&usr->pwd))
{
uchar lm16[16];
uchar nt16[16];
pwd_get_lm_nt_16(&usr->pwd, lm16, nt16);
memcpy(p, lm16, 16);
p += 16;
memcpy(p, nt16, 16);
p += 16;
}
len = PTR_DIFF(p, data);
SIVAL(data, 0, len);
printf("data len: %d\n", len);
out_data(stdout, data, len, 80);
if (write(sock, data, len) <= 0)
{
DEBUG(0,("write failed\n"));
close(sock);
return False;
}
len = read(sock, &cli_redir, sizeof(cli_redir));
if (len != sizeof(cli_redir))
{
DEBUG(0,("read failed\n"));
close(sock);
return False;
}
memcpy(cli, &cli_redir, sizeof(cli_redir));
cli->inbuf = in;
cli->outbuf = out;
cli->fd = sock;
return sock;
}
/****************************************************************************
establishes a connection right up to doing tconX, reading in a password.
****************************************************************************/
@ -2957,6 +3055,19 @@ BOOL cli_establish_connection(struct cli_state *cli,
return False;
}
if (cli->fd == -1 && cli->redirect)
{
if (cli_init_redirect(cli, dest_host, dest_ip, &cli->usr))
{
DEBUG(10,("cli_establish_connection: redirected OK\n"));
return True;
}
else
{
DEBUG(10,("redirect FAILED\n"));
return False;
}
}
if (cli->fd == -1)
{
if (!cli_connect(cli, dest_host, dest_ip))

View File

@ -42,6 +42,14 @@ void pwd_init(struct pwd_info *pwd)
pwd->crypted = False;
}
/****************************************************************************
returns NULL password flag
****************************************************************************/
BOOL pwd_is_nullpwd(const struct pwd_info *pwd)
{
return pwd->null_pwd;
}
/****************************************************************************
de-obfuscates a password
****************************************************************************/

View File

@ -96,7 +96,7 @@ static struct cli_connection *cli_con_get(const char* srv_name,
con->pipe_name = strdup(pipe_name);
}
con->cli = cli_net_use_add(srv_name, usr_creds);
con->cli = cli_net_use_add(srv_name, usr_creds, True);
if (con->cli == NULL)
{

View File

@ -204,7 +204,8 @@ static struct cli_use *cli_use_get(const char* srv_name,
init client state
****************************************************************************/
struct cli_state *cli_net_use_add(const char* srv_name,
const struct user_credentials *usr_creds)
const struct user_credentials *usr_creds,
BOOL redir)
{
struct nmb_name calling;
struct nmb_name called;
@ -225,6 +226,7 @@ struct cli_state *cli_net_use_add(const char* srv_name,
*/
cli = cli_use_get(srv_name, usr_creds);
cli->cli->redirect = redir;
if (resolve_srv_name(srv_name, dest_host, &ip))
{

View File

@ -1493,7 +1493,7 @@ static void cmd_net(struct client_info *info, int argc, char *argv[])
srv_name, u.user_name, u.domain);
report(out_hnd, "Connection:\t");
if (cli_net_use_add(srv_name, &u) != NULL)
if (cli_net_use_add(srv_name, &u, True) != NULL)
{
report(out_hnd, "OK\n");
}

347
source3/utils/smb-agent.c Normal file
View File

@ -0,0 +1,347 @@
/*
Unix SMB/Netbios implementation.
Version 2
SMB agent/socket plugin
Copyright (C) Andrew Tridgell 1999
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.
*/
#include "includes.h"
#include "smb.h"
#define SECURITY_MASK 0
#define SECURITY_SET 0
/* this forces non-unicode */
#define CAPABILITY_MASK CAP_UNICODE
#define CAPABILITY_SET 0
/* and non-unicode for the client too */
#define CLI_CAPABILITY_MASK CAP_UNICODE
#define CLI_CAPABILITY_SET 0
static char *netbiosname;
static char packet[BUFFER_SIZE];
extern int DEBUGLEVEL;
static void agent_reply(char *buf)
{
int msg_type = CVAL(buf,0);
int type = CVAL(buf,smb_com);
unsigned x;
if (msg_type) return;
switch (type) {
case SMBnegprot:
/* force the security bits */
x = CVAL(buf, smb_vwv1);
x = (x | SECURITY_SET) & ~SECURITY_MASK;
SCVAL(buf, smb_vwv1, x);
/* force the capabilities */
x = IVAL(buf,smb_vwv9+1);
x = (x | CAPABILITY_SET) & ~CAPABILITY_MASK;
SIVAL(buf, smb_vwv9+1, x);
break;
}
}
static void agent_request(char *buf)
{
int msg_type = CVAL(buf,0);
int type = CVAL(buf,smb_com);
pstring name1,name2;
unsigned x;
if (msg_type) {
/* it's a netbios special */
switch (msg_type) {
case 0x81:
/* session request */
name_extract(buf,4,name1);
name_extract(buf,4 + name_len(buf + 4),name2);
DEBUG(0,("sesion_request: %s -> %s\n",
name1, name2));
if (netbiosname) {
/* replace the destination netbios name */
name_mangle(netbiosname, buf+4, 0x20);
}
}
return;
}
/* it's an ordinary SMB request */
switch (type) {
case SMBsesssetupX:
/* force the client capabilities */
x = IVAL(buf,smb_vwv11);
x = (x | CLI_CAPABILITY_SET) & ~CLI_CAPABILITY_MASK;
SIVAL(buf, smb_vwv11, x);
break;
}
}
static void agent_child(int c)
{
struct cli_state *s = NULL;
DEBUG(10,("agent_child: %d\n", c));
while (c != -1)
{
fd_set fds;
int num;
int maxfd = 0;
FD_ZERO(&fds);
if (s != NULL)
{
FD_SET(s->fd, &fds);
maxfd = MAX(s->fd, maxfd);
}
if (c != -1)
{
FD_SET(c, &fds);
maxfd = MAX(c, maxfd);
}
num = sys_select(maxfd+1,&fds,NULL, NULL);
if (num <= 0) continue;
if (c != -1 && FD_ISSET(c, &fds))
{
if (s == NULL)
{
pstring buf;
uchar ntpw[16];
uchar lmpw[16];
fstring srv_name;
struct user_credentials usr;
char *p = buf;
int rl;
uint32 len;
DEBUG(10,("first request\n"));
rl = read(c, &buf, sizeof(len));
if (rl != sizeof(len))
{
DEBUG(0,("Unable to read length\n"));
dump_data(0, buf, sizeof(len));
exit(1);
}
len = IVAL(buf, 0);
if (len > sizeof(buf))
{
DEBUG(0,("length %d too long\n", len));
exit(1);
}
rl = read(c, buf, len);
if (rl < 0)
{
DEBUG(0,("Unable to read from connection\n"));
exit(1);
}
#ifdef DEBUG_PASSWORD
dump_data(100, buf, rl);
#endif
fstrcpy(srv_name, p);
p = skip_string(p, 1);
fstrcpy(usr.user_name, p);
p = skip_string(p, 1);
fstrcpy(usr.domain, p);
p = skip_string(p, 1);
if (PTR_DIFF(p, buf) < rl)
{
memcpy(ntpw, p, 16);
p += 16;
memcpy(lmpw, p, 16);
p += 16;
pwd_set_lm_nt_16(&usr.pwd, lmpw, ntpw);
}
else
{
pwd_set_nullpwd(&usr.pwd);
}
if (PTR_DIFF(p, buf) != rl)
{
DEBUG(0,("Buffer size %d %d!\n",
PTR_DIFF(p, buf), rl));
exit(1);
}
s = cli_net_use_add(srv_name, &usr, False);
if (s == NULL)
{
DEBUG(0,("Unable to connect to %s\n", srv_name));
exit(1);
}
if (write(c, s, sizeof(*s)) < 0)
{
DEBUG(0,("Could not write ack\n"));
exit(1);
}
}
else
{
if (!receive_smb(c, packet, 0))
{
DEBUG(0,("client closed connection\n"));
exit(0);
}
if (!send_smb(s->fd, packet))
{
DEBUG(0,("server is dead\n"));
exit(1);
}
}
}
if (s != NULL && FD_ISSET(s->fd, &fds))
{
if (!receive_smb(s->fd, packet, 0))
{
DEBUG(0,("server closed connection\n"));
exit(0);
}
#if 0
agent_reply(packet);
#endif
if (!send_smb(c, packet))
{
DEBUG(0,("client is dead\n"));
cli_shutdown(s);
free(s);
exit(1);
}
}
}
DEBUG(0,("Connection closed\n"));
if (s != NULL)
{
cli_shutdown(s);
free(s);
}
exit(0);
}
static void start_agent(void)
{
int s, c;
struct sockaddr_un sa;
CatchChild();
/* start listening on unix socket */
mkdir("/tmp/smb-agent", 700);
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0)
{
fprintf(stderr, "socket open failed\n");
exit(1);
}
ZERO_STRUCT(sa);
sa.sun_family = AF_UNIX;
safe_strcpy(sa.sun_path, "/tmp/smb-agent/smb.sock",
sizeof(sa.sun_path)-1);
if (bind(s, (struct sockaddr*) &sa, sizeof(sa)) < 0)
{
fprintf(stderr, "socket bind to %s failed\n", sa.sun_path);
close(s);
remove("/tmp/smb-agent/smb.sock");
exit(1);
}
if (s == -1) {
DEBUG(0,("bind failed\n"));
remove("/tmp/smb-agent/smb.sock");
exit(1);
}
if (listen(s, 5) == -1)
{
DEBUG(0,("listen failed\n"));
remove("/tmp/smb-agent/smb.sock");
}
while (1)
{
fd_set fds;
int num;
struct sockaddr_un addr;
int in_addrlen = sizeof(addr);
FD_ZERO(&fds);
FD_SET(s, &fds);
num = sys_select(s+1,&fds,NULL, NULL);
if (num > 0)
{
c = accept(s, (struct sockaddr*)&addr, &in_addrlen);
if (c != -1) {
if (fork() == 0)
{
close(s);
agent_child(c);
exit(0);
} else {
close(c);
}
}
}
}
}
int main(int argc, char *argv[])
{
pstring configfile;
TimeInit();
setup_logging(argv[0],True);
charset_initialise();
pstrcpy(configfile,CONFIGFILE);
if (!lp_load(configfile,True,False,False)) {
DEBUG(0,("Unable to load config file\n"));
}
start_agent();
return 0;
}