From 4c5c26b1ef4be862fc2037dd5fcc120cb35bacca Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 17 Aug 1998 07:15:54 +0000 Subject: 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 used to be commit b3d7014643ec9f2eef6e6f598f5b9db1fe2f930d) --- source3/Makefile.in | 4 +- source3/include/proto.h | 20 +- source3/include/smb.h | 7 + source3/smbd/fileio.c | 117 ++++++++++++ source3/smbd/negprot.c | 415 +++++++++++++++++++++++++++++++++++++++++ source3/smbd/server.c | 485 ------------------------------------------------ 6 files changed, 553 insertions(+), 495 deletions(-) create mode 100644 source3/smbd/fileio.c create mode 100644 source3/smbd/negprot.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 634a37a357..e940afbd93 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -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 diff --git a/source3/include/proto.h b/source3/include/proto.h index 4c7c625397..667fc01a3b 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -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); diff --git a/source3/include/smb.h b/source3/include/smb.h index c68f88cbdd..e88737f046 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -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 diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c new file mode 100644 index 0000000000..edf87f3e7b --- /dev/null +++ b/source3/smbd/fileio.c @@ -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)); +} + diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c new file mode 100644 index 0000000000..8e996cac21 --- /dev/null +++ b/source3/smbd/negprot.c @@ -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); +} + diff --git a/source3/smbd/server.c b/source3/smbd/server.c index a293075741..ccb830637d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -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 -- cgit