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

now that we have no global arrays we can start to split up the monster

server.c without breaking things.

this splits off netprot.c and fileio.c for negprot and read/write/seek
handling respectively.
This commit is contained in:
Andrew Tridgell 0001-01-01 00:00:00 +00:00
parent 1eb9ae2996
commit b3d7014643
6 changed files with 553 additions and 495 deletions

View File

@ -122,8 +122,8 @@ PASSDB_OBJ = passdb/passdb.o passdb/smbpassfile.o passdb/smbpass.o \
passdb/pass_check.o passdb/ldap.o passdb/nispass.o
SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o \
smbd/groupname.o smbd/ipc.o smbd/mangle.o \
smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o smbd/fileio.o \
smbd/groupname.o smbd/ipc.o smbd/mangle.o smbd/negprot.o \
smbd/message.o smbd/nttrans.o smbd/pipes.o smbd/predict.o \
smbd/quotas.o smbd/reply.o smbd/ssl.o smbd/trans2.o smbd/uid.o

View File

@ -1960,6 +1960,12 @@ void DirCacheAdd( char *path, char *name, char *dname, int snum );
char *DirCacheCheck( char *path, char *name, int snum );
void DirCacheFlush(int snum);
/*The following definitions come from smbd/fileio.c */
int seek_file(files_struct *fsp,uint32 pos);
int read_file(files_struct *fsp,char *data,uint32 pos,int n);
int write_file(files_struct *fsp,char *data,int n);
/*The following definitions come from smbd/files.c */
files_struct *file_new(void );
@ -2005,6 +2011,12 @@ int reply_sendtxt(connection_struct *conn,
int reply_sendend(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize);
/*The following definitions come from smbd/negprot.c */
int reply_negprot(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size,
int dum_buffsize);
/*The following definitions come from smbd/nttrans.c */
int reply_ntcreate_and_X(connection_struct *conn,
@ -2159,9 +2171,6 @@ int check_share_mode( share_mode_entry *share, int deny_mode, char *fname,
BOOL fcbopen, int *flags);
void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun,
int mode,int oplock_request, int *Access,int *action);
int seek_file(files_struct *fsp,uint32 pos);
int read_file(files_struct *fsp,char *data,uint32 pos,int n);
int write_file(files_struct *fsp,char *data,int n);
BOOL become_service(connection_struct *conn,BOOL do_chdir);
int find_service(char *service);
int cached_error_packet(char *inbuf,char *outbuf,files_struct *fsp,int line);
@ -2174,11 +2183,6 @@ BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int tim
BOOL reload_services(BOOL test);
connection_struct *make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid, int *ecode);
BOOL attempt_close_oplocked_file(files_struct *fsp);
int reply_corep(char *outbuf);
int reply_coreplus(char *outbuf);
int reply_lanman1(char *outbuf);
int reply_lanman2(char *outbuf);
int reply_nt1(char *outbuf);
void close_cnum(connection_struct *conn, uint16 vuid);
void exit_server(char *reason);
char *smb_fn_name(int type);

View File

@ -200,6 +200,13 @@ implemented */
#define aDIR (1L<<4)
#define aARCH (1L<<5)
/* for readability... */
#define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
#define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
#define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
#define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
#define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
/* deny modes */
#define DENY_DOS 0
#define DENY_ALL 1

117
source/smbd/fileio.c Normal file
View File

@ -0,0 +1,117 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
read/write to a files_struct
Copyright (C) Andrew Tridgell 1992-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.
*/
#include "includes.h"
extern int DEBUGLEVEL;
/****************************************************************************
seek a file. Try to avoid the seek if possible
****************************************************************************/
int seek_file(files_struct *fsp,uint32 pos)
{
uint32 offset = 0;
if (fsp->print_file && lp_postscript(fsp->conn->service))
offset = 3;
fsp->pos = (int)(lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET) - offset);
return(fsp->pos);
}
/****************************************************************************
read from a file
****************************************************************************/
int read_file(files_struct *fsp,char *data,uint32 pos,int n)
{
int ret=0,readret;
#if USE_READ_PREDICTION
if (!fsp->can_write)
{
ret = read_predict(fsp->fd_ptr->fd,pos,data,NULL,n);
data += ret;
n -= ret;
pos += ret;
}
#endif
#if WITH_MMAP
if (fsp->mmap_ptr)
{
int num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1;
num = MIN(n,num);
if (num > 0)
{
memcpy(data,fsp->mmap_ptr+pos,num);
data += num;
pos += num;
n -= num;
ret += num;
}
}
#endif
if (n <= 0)
return(ret);
if (seek_file(fsp,pos) != pos)
{
DEBUG(3,("Failed to seek to %d\n",pos));
return(ret);
}
if (n > 0) {
readret = read(fsp->fd_ptr->fd,data,n);
if (readret > 0) ret += readret;
}
return(ret);
}
/****************************************************************************
write to a file
****************************************************************************/
int write_file(files_struct *fsp,char *data,int n)
{
if (!fsp->can_write) {
errno = EPERM;
return(0);
}
if (!fsp->modified) {
struct stat st;
fsp->modified = True;
if (fstat(fsp->fd_ptr->fd,&st) == 0) {
int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) {
dos_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st);
}
}
}
return(write_data(fsp->fd_ptr->fd,data,n));
}

415
source/smbd/negprot.c Normal file
View File

@ -0,0 +1,415 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
negprot reply code
Copyright (C) Andrew Tridgell 1992-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.
*/
#include "includes.h"
extern int DEBUGLEVEL;
extern int Protocol;
extern int max_recv;
extern fstring global_myworkgroup;
extern fstring remote_machine;
extern pstring myhostname;
/****************************************************************************
reply for the core protocol
****************************************************************************/
static int reply_corep(char *outbuf)
{
int outsize = set_message(outbuf,1,0,True);
Protocol = PROTOCOL_CORE;
return outsize;
}
/****************************************************************************
reply for the coreplus protocol
****************************************************************************/
static int reply_coreplus(char *outbuf)
{
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
int outsize = set_message(outbuf,13,0,True);
SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
readbraw and writebraw (possibly) */
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
Protocol = PROTOCOL_COREPLUS;
return outsize;
}
/****************************************************************************
reply for the lanman 1.0 protocol
****************************************************************************/
static int reply_lanman1(char *outbuf)
{
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
set_message(outbuf,13,doencrypt?8:0,True);
SSVAL(outbuf,smb_vwv1,secword);
/* Create a token value and add it to the outgoing packet. */
if (doencrypt)
generate_next_challenge(smb_buf(outbuf));
Protocol = PROTOCOL_LANMAN1;
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
SSVAL(outbuf,smb_vwv2,max_recv);
SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
SSVAL(outbuf,smb_vwv4,1);
SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
readbraw writebraw (possibly) */
SIVAL(outbuf,smb_vwv6,getpid());
SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
put_dos_date(outbuf,smb_vwv8,t);
return (smb_len(outbuf)+4);
}
/****************************************************************************
reply for the lanman 2.0 protocol
****************************************************************************/
static int reply_lanman2(char *outbuf)
{
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
struct cli_state *cli = NULL;
char cryptkey[8];
char crypt_len = 0;
if (lp_security() == SEC_SERVER) {
cli = server_cryptkey();
}
if (cli) {
DEBUG(3,("using password server validation\n"));
doencrypt = ((cli->sec_mode & 2) != 0);
}
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
if (doencrypt) {
crypt_len = 8;
if (!cli) {
generate_next_challenge(cryptkey);
} else {
memcpy(cryptkey, cli->cryptkey, 8);
set_challenge(cli->cryptkey);
}
}
set_message(outbuf,13,crypt_len,True);
SSVAL(outbuf,smb_vwv1,secword);
SIVAL(outbuf,smb_vwv6,getpid());
if (doencrypt)
memcpy(smb_buf(outbuf), cryptkey, 8);
Protocol = PROTOCOL_LANMAN2;
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
SSVAL(outbuf,smb_vwv2,max_recv);
SSVAL(outbuf,smb_vwv3,lp_maxmux());
SSVAL(outbuf,smb_vwv4,1);
SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
put_dos_date(outbuf,smb_vwv8,t);
return (smb_len(outbuf)+4);
}
/****************************************************************************
reply for the nt protocol
****************************************************************************/
static int reply_nt1(char *outbuf)
{
/* dual names + lock_and_read + nt SMBs + remote API calls */
int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS |CAP_NT_SMBS;
/*
other valid capabilities which we may support at some time...
CAP_LARGE_FILES|
CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
*/
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
int data_len;
struct cli_state *cli = NULL;
char cryptkey[8];
char crypt_len = 0;
if (lp_security() == SEC_SERVER) {
cli = server_cryptkey();
}
if (cli) {
DEBUG(3,("using password server validation\n"));
doencrypt = ((cli->sec_mode & 2) != 0);
}
if (doencrypt) {
crypt_len = 8;
if (!cli) {
generate_next_challenge(cryptkey);
} else {
memcpy(cryptkey, cli->cryptkey, 8);
set_challenge(cli->cryptkey);
}
}
if (lp_readraw() && lp_writeraw()) {
capabilities |= CAP_RAW_MODE;
}
if (lp_security() >= SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
/* decide where (if) to put the encryption challenge, and
follow it with the OEM'd domain name
*/
data_len = crypt_len + strlen(global_myworkgroup) + 1;
set_message(outbuf,17,data_len,True);
pstrcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup);
CVAL(outbuf,smb_vwv1) = secword;
SSVALS(outbuf,smb_vwv16+1,crypt_len);
if (doencrypt)
memcpy(smb_buf(outbuf), cryptkey, 8);
Protocol = PROTOCOL_NT1;
SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
put_long_date(outbuf+smb_vwv11+1,t);
SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
return (smb_len(outbuf)+4);
}
/* these are the protocol lists used for auto architecture detection:
WinNT 3.51:
protocol [PC NETWORK PROGRAM 1.0]
protocol [XENIX CORE]
protocol [MICROSOFT NETWORKS 1.03]
protocol [LANMAN1.0]
protocol [Windows for Workgroups 3.1a]
protocol [LM1.2X002]
protocol [LANMAN2.1]
protocol [NT LM 0.12]
Win95:
protocol [PC NETWORK PROGRAM 1.0]
protocol [XENIX CORE]
protocol [MICROSOFT NETWORKS 1.03]
protocol [LANMAN1.0]
protocol [Windows for Workgroups 3.1a]
protocol [LM1.2X002]
protocol [LANMAN2.1]
protocol [NT LM 0.12]
OS/2:
protocol [PC NETWORK PROGRAM 1.0]
protocol [XENIX CORE]
protocol [LANMAN1.0]
protocol [LM1.2X002]
protocol [LANMAN2.1]
*/
/*
* Modified to recognize the architecture of the remote machine better.
*
* This appears to be the matrix of which protocol is used by which
* MS product.
Protocol WfWg Win95 WinNT OS/2
PC NETWORK PROGRAM 1.0 1 1 1 1
XENIX CORE 2 2
MICROSOFT NETWORKS 3.0 2 2
DOS LM1.2X002 3 3
MICROSOFT NETWORKS 1.03 3
DOS LANMAN2.1 4 4
LANMAN1.0 4 3
Windows for Workgroups 3.1a 5 5 5
LM1.2X002 6 4
LANMAN2.1 7 5
NT LM 0.12 6 8
*
* tim@fsg.com 09/29/95
*/
#define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
#define ARCH_WIN95 0x2
#define ARCH_OS2 0xC /* Again OS/2 is like NT */
#define ARCH_WINNT 0x8
#define ARCH_SAMBA 0x10
#define ARCH_ALL 0x1F
/* List of supported protocols, most desired first */
static struct {
char *proto_name;
char *short_name;
int (*proto_reply_fn)(char *);
int protocol_level;
} supported_protocols[] = {
{"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
{"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
{"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
{"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
{"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
{"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
{"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
{"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
{"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
{NULL,NULL},
};
/****************************************************************************
reply to a negprot
****************************************************************************/
int reply_negprot(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size,
int dum_buffsize)
{
int outsize = set_message(outbuf,1,0,True);
int Index=0;
int choice= -1;
int protocol;
char *p;
int bcc = SVAL(smb_buf(inbuf),-2);
int arch = ARCH_ALL;
p = smb_buf(inbuf)+1;
while (p < (smb_buf(inbuf) + bcc))
{
Index++;
DEBUG(3,("Requested protocol [%s]\n",p));
if (strcsequal(p,"Windows for Workgroups 3.1a"))
arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
else if (strcsequal(p,"DOS LM1.2X002"))
arch &= ( ARCH_WFWG | ARCH_WIN95 );
else if (strcsequal(p,"DOS LANMAN2.1"))
arch &= ( ARCH_WFWG | ARCH_WIN95 );
else if (strcsequal(p,"NT LM 0.12"))
arch &= ( ARCH_WIN95 | ARCH_WINNT );
else if (strcsequal(p,"LANMAN2.1"))
arch &= ( ARCH_WINNT | ARCH_OS2 );
else if (strcsequal(p,"LM1.2X002"))
arch &= ( ARCH_WINNT | ARCH_OS2 );
else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
arch &= ARCH_WINNT;
else if (strcsequal(p,"XENIX CORE"))
arch &= ( ARCH_WINNT | ARCH_OS2 );
else if (strcsequal(p,"Samba")) {
arch = ARCH_SAMBA;
break;
}
p += strlen(p) + 2;
}
switch ( arch ) {
case ARCH_SAMBA:
set_remote_arch(RA_SAMBA);
break;
case ARCH_WFWG:
set_remote_arch(RA_WFWG);
break;
case ARCH_WIN95:
set_remote_arch(RA_WIN95);
break;
case ARCH_WINNT:
set_remote_arch(RA_WINNT);
break;
case ARCH_OS2:
set_remote_arch(RA_OS2);
break;
default:
set_remote_arch(RA_UNKNOWN);
break;
}
/* possibly reload - change of architecture */
reload_services(True);
/* a special case to stop password server loops */
if (Index == 1 && strequal(remote_machine,myhostname) &&
(lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN))
exit_server("Password server loop!");
/* Check for protocols, most desirable first */
for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
{
p = smb_buf(inbuf)+1;
Index = 0;
if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
while (p < (smb_buf(inbuf) + bcc))
{
if (strequal(p,supported_protocols[protocol].proto_name))
choice = Index;
Index++;
p += strlen(p) + 2;
}
if(choice != -1)
break;
}
SSVAL(outbuf,smb_vwv0,choice);
if(choice != -1) {
extern fstring remote_proto;
fstrcpy(remote_proto,supported_protocols[protocol].short_name);
reload_services(True);
outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
}
else {
DEBUG(0,("No protocol supported !\n"));
}
SSVAL(outbuf,smb_vwv0,choice);
DEBUG( 5, ( "negprot index=%d\n", choice ) );
return(outsize);
}

View File

@ -65,8 +65,6 @@ extern int dcelogin_atmost_once;
*/
extern DOM_SID global_machine_sid;
extern int Protocol;
/*
* Size of data we can send to client. Set
* by the client for all protocols above CORE.
@ -100,13 +98,6 @@ extern int extra_time_offset;
extern pstring myhostname;
/* for readability... */
#define IS_DOS_READONLY(test_mode) (((test_mode) & aRONLY) != 0)
#define IS_DOS_DIR(test_mode) (((test_mode) & aDIR) != 0)
#define IS_DOS_ARCHIVE(test_mode) (((test_mode) & aARCH) != 0)
#define IS_DOS_SYSTEM(test_mode) (((test_mode) & aSYSTEM) != 0)
#define IS_DOS_HIDDEN(test_mode) (((test_mode) & aHIDDEN) != 0)
/****************************************************************************
when exiting, take the whole family
****************************************************************************/
@ -1988,97 +1979,6 @@ dev = %x, inode = %x\n", oplock_request, fname, dev, inode));
unlock_share_entry( conn, dev, inode, token);
}
/****************************************************************************
seek a file. Try to avoid the seek if possible
****************************************************************************/
int seek_file(files_struct *fsp,uint32 pos)
{
uint32 offset = 0;
if (fsp->print_file && lp_postscript(fsp->conn->service))
offset = 3;
fsp->pos = (int)(lseek(fsp->fd_ptr->fd,pos+offset,SEEK_SET) - offset);
return(fsp->pos);
}
/****************************************************************************
read from a file
****************************************************************************/
int read_file(files_struct *fsp,char *data,uint32 pos,int n)
{
int ret=0,readret;
#if USE_READ_PREDICTION
if (!fsp->can_write)
{
ret = read_predict(fsp->fd_ptr->fd,pos,data,NULL,n);
data += ret;
n -= ret;
pos += ret;
}
#endif
#if WITH_MMAP
if (fsp->mmap_ptr)
{
int num = (fsp->mmap_size > pos) ? (fsp->mmap_size - pos) : -1;
num = MIN(n,num);
if (num > 0)
{
memcpy(data,fsp->mmap_ptr+pos,num);
data += num;
pos += num;
n -= num;
ret += num;
}
}
#endif
if (n <= 0)
return(ret);
if (seek_file(fsp,pos) != pos)
{
DEBUG(3,("Failed to seek to %d\n",pos));
return(ret);
}
if (n > 0) {
readret = read(fsp->fd_ptr->fd,data,n);
if (readret > 0) ret += readret;
}
return(ret);
}
/****************************************************************************
write to a file
****************************************************************************/
int write_file(files_struct *fsp,char *data,int n)
{
if (!fsp->can_write) {
errno = EPERM;
return(0);
}
if (!fsp->modified) {
struct stat st;
fsp->modified = True;
if (fstat(fsp->fd_ptr->fd,&st) == 0) {
int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) {
dos_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st);
}
}
}
return(write_data(fsp->fd_ptr->fd,data,n));
}
/****************************************************************************
load parameters specific to a connection/service
@ -3657,391 +3557,6 @@ BOOL attempt_close_oplocked_file(files_struct *fsp)
}
/****************************************************************************
reply for the core protocol
****************************************************************************/
int reply_corep(char *outbuf)
{
int outsize = set_message(outbuf,1,0,True);
Protocol = PROTOCOL_CORE;
return outsize;
}
/****************************************************************************
reply for the coreplus protocol
****************************************************************************/
int reply_coreplus(char *outbuf)
{
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
int outsize = set_message(outbuf,13,0,True);
SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
readbraw and writebraw (possibly) */
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
Protocol = PROTOCOL_COREPLUS;
return outsize;
}
/****************************************************************************
reply for the lanman 1.0 protocol
****************************************************************************/
int reply_lanman1(char *outbuf)
{
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
set_message(outbuf,13,doencrypt?8:0,True);
SSVAL(outbuf,smb_vwv1,secword);
/* Create a token value and add it to the outgoing packet. */
if (doencrypt)
generate_next_challenge(smb_buf(outbuf));
Protocol = PROTOCOL_LANMAN1;
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
SSVAL(outbuf,smb_vwv2,max_recv);
SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
SSVAL(outbuf,smb_vwv4,1);
SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
readbraw writebraw (possibly) */
SIVAL(outbuf,smb_vwv6,getpid());
SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
put_dos_date(outbuf,smb_vwv8,t);
return (smb_len(outbuf)+4);
}
/****************************************************************************
reply for the lanman 2.0 protocol
****************************************************************************/
int reply_lanman2(char *outbuf)
{
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
struct cli_state *cli = NULL;
char cryptkey[8];
char crypt_len = 0;
if (lp_security() == SEC_SERVER) {
cli = server_cryptkey();
}
if (cli) {
DEBUG(3,("using password server validation\n"));
doencrypt = ((cli->sec_mode & 2) != 0);
}
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
if (doencrypt) {
crypt_len = 8;
if (!cli) {
generate_next_challenge(cryptkey);
} else {
memcpy(cryptkey, cli->cryptkey, 8);
set_challenge(cli->cryptkey);
}
}
set_message(outbuf,13,crypt_len,True);
SSVAL(outbuf,smb_vwv1,secword);
SIVAL(outbuf,smb_vwv6,getpid());
if (doencrypt)
memcpy(smb_buf(outbuf), cryptkey, 8);
Protocol = PROTOCOL_LANMAN2;
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
SSVAL(outbuf,smb_vwv2,max_recv);
SSVAL(outbuf,smb_vwv3,lp_maxmux());
SSVAL(outbuf,smb_vwv4,1);
SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
put_dos_date(outbuf,smb_vwv8,t);
return (smb_len(outbuf)+4);
}
/****************************************************************************
reply for the nt protocol
****************************************************************************/
int reply_nt1(char *outbuf)
{
/* dual names + lock_and_read + nt SMBs + remote API calls */
int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS |CAP_NT_SMBS;
/*
other valid capabilities which we may support at some time...
CAP_LARGE_FILES|
CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
*/
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
int data_len;
struct cli_state *cli = NULL;
char cryptkey[8];
char crypt_len = 0;
if (lp_security() == SEC_SERVER) {
cli = server_cryptkey();
}
if (cli) {
DEBUG(3,("using password server validation\n"));
doencrypt = ((cli->sec_mode & 2) != 0);
}
if (doencrypt) {
crypt_len = 8;
if (!cli) {
generate_next_challenge(cryptkey);
} else {
memcpy(cryptkey, cli->cryptkey, 8);
set_challenge(cli->cryptkey);
}
}
if (lp_readraw() && lp_writeraw()) {
capabilities |= CAP_RAW_MODE;
}
if (lp_security() >= SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
/* decide where (if) to put the encryption challenge, and
follow it with the OEM'd domain name
*/
data_len = crypt_len + strlen(global_myworkgroup) + 1;
set_message(outbuf,17,data_len,True);
pstrcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup);
CVAL(outbuf,smb_vwv1) = secword;
SSVALS(outbuf,smb_vwv16+1,crypt_len);
if (doencrypt)
memcpy(smb_buf(outbuf), cryptkey, 8);
Protocol = PROTOCOL_NT1;
SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
put_long_date(outbuf+smb_vwv11+1,t);
SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
return (smb_len(outbuf)+4);
}
/* these are the protocol lists used for auto architecture detection:
WinNT 3.51:
protocol [PC NETWORK PROGRAM 1.0]
protocol [XENIX CORE]
protocol [MICROSOFT NETWORKS 1.03]
protocol [LANMAN1.0]
protocol [Windows for Workgroups 3.1a]
protocol [LM1.2X002]
protocol [LANMAN2.1]
protocol [NT LM 0.12]
Win95:
protocol [PC NETWORK PROGRAM 1.0]
protocol [XENIX CORE]
protocol [MICROSOFT NETWORKS 1.03]
protocol [LANMAN1.0]
protocol [Windows for Workgroups 3.1a]
protocol [LM1.2X002]
protocol [LANMAN2.1]
protocol [NT LM 0.12]
OS/2:
protocol [PC NETWORK PROGRAM 1.0]
protocol [XENIX CORE]
protocol [LANMAN1.0]
protocol [LM1.2X002]
protocol [LANMAN2.1]
*/
/*
* Modified to recognize the architecture of the remote machine better.
*
* This appears to be the matrix of which protocol is used by which
* MS product.
Protocol WfWg Win95 WinNT OS/2
PC NETWORK PROGRAM 1.0 1 1 1 1
XENIX CORE 2 2
MICROSOFT NETWORKS 3.0 2 2
DOS LM1.2X002 3 3
MICROSOFT NETWORKS 1.03 3
DOS LANMAN2.1 4 4
LANMAN1.0 4 3
Windows for Workgroups 3.1a 5 5 5
LM1.2X002 6 4
LANMAN2.1 7 5
NT LM 0.12 6 8
*
* tim@fsg.com 09/29/95
*/
#define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
#define ARCH_WIN95 0x2
#define ARCH_OS2 0xC /* Again OS/2 is like NT */
#define ARCH_WINNT 0x8
#define ARCH_SAMBA 0x10
#define ARCH_ALL 0x1F
/* List of supported protocols, most desired first */
struct {
char *proto_name;
char *short_name;
int (*proto_reply_fn)(char *);
int protocol_level;
} supported_protocols[] = {
{"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
{"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
{"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
{"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
{"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
{"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
{"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
{"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
{"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
{NULL,NULL},
};
/****************************************************************************
reply to a negprot
****************************************************************************/
static int reply_negprot(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size,
int dum_buffsize)
{
int outsize = set_message(outbuf,1,0,True);
int Index=0;
int choice= -1;
int protocol;
char *p;
int bcc = SVAL(smb_buf(inbuf),-2);
int arch = ARCH_ALL;
p = smb_buf(inbuf)+1;
while (p < (smb_buf(inbuf) + bcc))
{
Index++;
DEBUG(3,("Requested protocol [%s]\n",p));
if (strcsequal(p,"Windows for Workgroups 3.1a"))
arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
else if (strcsequal(p,"DOS LM1.2X002"))
arch &= ( ARCH_WFWG | ARCH_WIN95 );
else if (strcsequal(p,"DOS LANMAN2.1"))
arch &= ( ARCH_WFWG | ARCH_WIN95 );
else if (strcsequal(p,"NT LM 0.12"))
arch &= ( ARCH_WIN95 | ARCH_WINNT );
else if (strcsequal(p,"LANMAN2.1"))
arch &= ( ARCH_WINNT | ARCH_OS2 );
else if (strcsequal(p,"LM1.2X002"))
arch &= ( ARCH_WINNT | ARCH_OS2 );
else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
arch &= ARCH_WINNT;
else if (strcsequal(p,"XENIX CORE"))
arch &= ( ARCH_WINNT | ARCH_OS2 );
else if (strcsequal(p,"Samba")) {
arch = ARCH_SAMBA;
break;
}
p += strlen(p) + 2;
}
switch ( arch ) {
case ARCH_SAMBA:
set_remote_arch(RA_SAMBA);
break;
case ARCH_WFWG:
set_remote_arch(RA_WFWG);
break;
case ARCH_WIN95:
set_remote_arch(RA_WIN95);
break;
case ARCH_WINNT:
set_remote_arch(RA_WINNT);
break;
case ARCH_OS2:
set_remote_arch(RA_OS2);
break;
default:
set_remote_arch(RA_UNKNOWN);
break;
}
/* possibly reload - change of architecture */
reload_services(True);
/* a special case to stop password server loops */
if (Index == 1 && strequal(remote_machine,myhostname) &&
(lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN))
exit_server("Password server loop!");
/* Check for protocols, most desirable first */
for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
{
p = smb_buf(inbuf)+1;
Index = 0;
if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
while (p < (smb_buf(inbuf) + bcc))
{
if (strequal(p,supported_protocols[protocol].proto_name))
choice = Index;
Index++;
p += strlen(p) + 2;
}
if(choice != -1)
break;
}
SSVAL(outbuf,smb_vwv0,choice);
if(choice != -1) {
extern fstring remote_proto;
fstrcpy(remote_proto,supported_protocols[protocol].short_name);
reload_services(True);
outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
}
else {
DEBUG(0,("No protocol supported !\n"));
}
SSVAL(outbuf,smb_vwv0,choice);
DEBUG( 5, ( "negprot index=%d\n", choice ) );
return(outsize);
}
/****************************************************************************
close a cnum