2005-11-17 11:00:48 +03:00
/*
Unix SMB / CIFS implementation .
process incoming packets - main loop
Copyright ( C ) Andrew Tridgell 1992 - 2005
Copyright ( C ) James J Myers 2003 < myersjj @ samba . org >
Copyright ( C ) Stefan Metzmacher 2004 - 2005
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-11-17 11:00:48 +03:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-11-17 11:00:48 +03:00
*/
# include "includes.h"
# include "system/time.h"
2017-01-01 23:00:55 +03:00
# include "lib/util/server_id.h"
2020-11-20 17:27:17 +03:00
# include "samba/service_stream.h"
2005-11-17 11:00:48 +03:00
# include "smb_server/smb_server.h"
2006-09-16 20:27:46 +04:00
# include "system/filesys.h"
2007-09-08 16:42:09 +04:00
# include "param/param.h"
2011-05-02 04:05:46 +04:00
# include "cluster/cluster.h"
2005-11-17 11:00:48 +03:00
/*
send an oplock break request to a client
*/
2006-05-20 12:15:22 +04:00
NTSTATUS smbsrv_send_oplock_break ( void * p , struct ntvfs_handle * ntvfs , uint8_t level )
2005-11-17 11:00:48 +03:00
{
2006-03-15 20:28:46 +03:00
struct smbsrv_tcon * tcon = talloc_get_type ( p , struct smbsrv_tcon ) ;
2005-11-17 11:00:48 +03:00
struct smbsrv_request * req ;
2006-03-06 19:19:27 +03:00
req = smbsrv_init_request ( tcon - > smb_conn ) ;
2006-03-15 20:28:46 +03:00
NT_STATUS_HAVE_NO_MEMORY ( req ) ;
2005-11-17 11:00:48 +03:00
2006-03-06 19:19:27 +03:00
smbsrv_setup_reply ( req , 8 , 0 ) ;
2006-03-15 20:28:46 +03:00
2005-11-17 11:00:48 +03:00
SCVAL ( req - > out . hdr , HDR_COM , SMBlockingX ) ;
SSVAL ( req - > out . hdr , HDR_TID , tcon - > tid ) ;
SSVAL ( req - > out . hdr , HDR_PID , 0xFFFF ) ;
SSVAL ( req - > out . hdr , HDR_UID , 0 ) ;
SSVAL ( req - > out . hdr , HDR_MID , 0xFFFF ) ;
SCVAL ( req - > out . hdr , HDR_FLG , 0 ) ;
SSVAL ( req - > out . hdr , HDR_FLG2 , 0 ) ;
SSVAL ( req - > out . vwv , VWV ( 0 ) , SMB_CHAIN_NONE ) ;
SSVAL ( req - > out . vwv , VWV ( 1 ) , 0 ) ;
2006-05-20 12:15:22 +04:00
smbsrv_push_fnum ( req - > out . vwv , VWV ( 2 ) , ntvfs ) ;
2005-11-17 11:00:48 +03:00
SCVAL ( req - > out . vwv , VWV ( 3 ) , LOCKING_ANDX_OPLOCK_RELEASE ) ;
SCVAL ( req - > out . vwv , VWV ( 3 ) + 1 , level ) ;
SIVAL ( req - > out . vwv , VWV ( 4 ) , 0 ) ;
SSVAL ( req - > out . vwv , VWV ( 6 ) , 0 ) ;
SSVAL ( req - > out . vwv , VWV ( 7 ) , 0 ) ;
2006-03-06 19:19:27 +03:00
smbsrv_send_reply ( req ) ;
2006-03-15 20:28:46 +03:00
return NT_STATUS_OK ;
2005-11-17 11:00:48 +03:00
}
static void switch_message ( int type , struct smbsrv_request * req ) ;
/*
These flags determine some of the permissions required to do an operation
*/
2006-03-16 21:26:14 +03:00
# define NEED_SESS (1<<0)
# define NEED_TCON (1<<1)
# define SIGNING_NO_REPLY (1<<2)
2008-03-10 13:06:12 +03:00
/* does VWV(0) of the request hold chaining information */
# define AND_X (1<<3)
/* The 64Kb question: are requests > 64K valid? */
# define LARGE_REQUEST (1<<4)
2005-11-17 11:00:48 +03:00
/*
define a list of possible SMB messages and their corresponding
functions . Any message that has a NULL function is unimplemented -
please feel free to contribute implementations !
*/
static const struct smb_message_struct
{
const char * name ;
void ( * fn ) ( struct smbsrv_request * ) ;
2008-03-10 13:06:12 +03:00
# define message_flags(type) smb_messages[(type) & 0xff].flags
2005-11-17 11:00:48 +03:00
int flags ;
}
smb_messages [ 256 ] = {
2006-03-16 21:26:14 +03:00
/* 0x00 */ { " SMBmkdir " , smbsrv_reply_mkdir , NEED_SESS | NEED_TCON } ,
/* 0x01 */ { " SMBrmdir " , smbsrv_reply_rmdir , NEED_SESS | NEED_TCON } ,
/* 0x02 */ { " SMBopen " , smbsrv_reply_open , NEED_SESS | NEED_TCON } ,
/* 0x03 */ { " SMBcreate " , smbsrv_reply_mknew , NEED_SESS | NEED_TCON } ,
/* 0x04 */ { " SMBclose " , smbsrv_reply_close , NEED_SESS | NEED_TCON } ,
/* 0x05 */ { " SMBflush " , smbsrv_reply_flush , NEED_SESS | NEED_TCON } ,
/* 0x06 */ { " SMBunlink " , smbsrv_reply_unlink , NEED_SESS | NEED_TCON } ,
/* 0x07 */ { " SMBmv " , smbsrv_reply_mv , NEED_SESS | NEED_TCON } ,
/* 0x08 */ { " SMBgetatr " , smbsrv_reply_getatr , NEED_SESS | NEED_TCON } ,
/* 0x09 */ { " SMBsetatr " , smbsrv_reply_setatr , NEED_SESS | NEED_TCON } ,
/* 0x0a */ { " SMBread " , smbsrv_reply_read , NEED_SESS | NEED_TCON } ,
/* 0x0b */ { " SMBwrite " , smbsrv_reply_write , NEED_SESS | NEED_TCON } ,
/* 0x0c */ { " SMBlock " , smbsrv_reply_lock , NEED_SESS | NEED_TCON } ,
/* 0x0d */ { " SMBunlock " , smbsrv_reply_unlock , NEED_SESS | NEED_TCON } ,
/* 0x0e */ { " SMBctemp " , smbsrv_reply_ctemp , NEED_SESS | NEED_TCON } ,
/* 0x0f */ { " SMBmknew " , smbsrv_reply_mknew , NEED_SESS | NEED_TCON } ,
2011-07-12 11:26:53 +04:00
/* 0x10 */ { " SMBcheckpath " , smbsrv_reply_chkpth , NEED_SESS | NEED_TCON } ,
2006-03-16 21:26:14 +03:00
/* 0x11 */ { " SMBexit " , smbsrv_reply_exit , NEED_SESS } ,
/* 0x12 */ { " SMBlseek " , smbsrv_reply_lseek , NEED_SESS | NEED_TCON } ,
/* 0x13 */ { " SMBlockread " , smbsrv_reply_lockread , NEED_SESS | NEED_TCON } ,
/* 0x14 */ { " SMBwriteunlock " , smbsrv_reply_writeunlock , NEED_SESS | NEED_TCON } ,
2005-11-17 11:00:48 +03:00
/* 0x15 */ { NULL , NULL , 0 } ,
/* 0x16 */ { NULL , NULL , 0 } ,
/* 0x17 */ { NULL , NULL , 0 } ,
/* 0x18 */ { NULL , NULL , 0 } ,
/* 0x19 */ { NULL , NULL , 0 } ,
2006-03-16 21:26:14 +03:00
/* 0x1a */ { " SMBreadbraw " , smbsrv_reply_readbraw , NEED_SESS | NEED_TCON } ,
/* 0x1b */ { " SMBreadBmpx " , smbsrv_reply_readbmpx , NEED_SESS | NEED_TCON } ,
/* 0x1c */ { " SMBreadBs " , NULL , 0 } ,
/* 0x1d */ { " SMBwritebraw " , smbsrv_reply_writebraw , NEED_SESS | NEED_TCON } ,
/* 0x1e */ { " SMBwriteBmpx " , smbsrv_reply_writebmpx , NEED_SESS | NEED_TCON } ,
/* 0x1f */ { " SMBwriteBs " , smbsrv_reply_writebs , NEED_SESS | NEED_TCON } ,
/* 0x20 */ { " SMBwritec " , NULL , 0 } ,
2005-11-17 11:00:48 +03:00
/* 0x21 */ { NULL , NULL , 0 } ,
2006-03-16 21:26:14 +03:00
/* 0x22 */ { " SMBsetattrE " , smbsrv_reply_setattrE , NEED_SESS | NEED_TCON } ,
/* 0x23 */ { " SMBgetattrE " , smbsrv_reply_getattrE , NEED_SESS | NEED_TCON } ,
2008-03-10 13:06:12 +03:00
/* 0x24 */ { " SMBlockingX " , smbsrv_reply_lockingX , NEED_SESS | NEED_TCON | AND_X } ,
2006-03-16 21:26:14 +03:00
/* 0x25 */ { " SMBtrans " , smbsrv_reply_trans , NEED_SESS | NEED_TCON } ,
/* 0x26 */ { " SMBtranss " , smbsrv_reply_transs , NEED_SESS | NEED_TCON } ,
/* 0x27 */ { " SMBioctl " , smbsrv_reply_ioctl , NEED_SESS | NEED_TCON } ,
/* 0x28 */ { " SMBioctls " , NULL , NEED_SESS | NEED_TCON } ,
/* 0x29 */ { " SMBcopy " , smbsrv_reply_copy , NEED_SESS | NEED_TCON } ,
/* 0x2a */ { " SMBmove " , NULL , NEED_SESS | NEED_TCON } ,
/* 0x2b */ { " SMBecho " , smbsrv_reply_echo , 0 } ,
/* 0x2c */ { " SMBwriteclose " , smbsrv_reply_writeclose , NEED_SESS | NEED_TCON } ,
2008-03-10 13:06:12 +03:00
/* 0x2d */ { " SMBopenX " , smbsrv_reply_open_and_X , NEED_SESS | NEED_TCON | AND_X } ,
/* 0x2e */ { " SMBreadX " , smbsrv_reply_read_and_X , NEED_SESS | NEED_TCON | AND_X } ,
/* 0x2f */ { " SMBwriteX " , smbsrv_reply_write_and_X , NEED_SESS | NEED_TCON | AND_X | LARGE_REQUEST } ,
2005-11-17 11:00:48 +03:00
/* 0x30 */ { NULL , NULL , 0 } ,
/* 0x31 */ { NULL , NULL , 0 } ,
2006-03-16 21:26:14 +03:00
/* 0x32 */ { " SMBtrans2 " , smbsrv_reply_trans2 , NEED_SESS | NEED_TCON } ,
/* 0x33 */ { " SMBtranss2 " , smbsrv_reply_transs2 , NEED_SESS | NEED_TCON } ,
/* 0x34 */ { " SMBfindclose " , smbsrv_reply_findclose , NEED_SESS | NEED_TCON } ,
/* 0x35 */ { " SMBfindnclose " , smbsrv_reply_findnclose , NEED_SESS | NEED_TCON } ,
2005-11-17 11:00:48 +03:00
/* 0x36 */ { NULL , NULL , 0 } ,
/* 0x37 */ { NULL , NULL , 0 } ,
/* 0x38 */ { NULL , NULL , 0 } ,
/* 0x39 */ { NULL , NULL , 0 } ,
/* 0x3a */ { NULL , NULL , 0 } ,
/* 0x3b */ { NULL , NULL , 0 } ,
/* 0x3c */ { NULL , NULL , 0 } ,
/* 0x3d */ { NULL , NULL , 0 } ,
/* 0x3e */ { NULL , NULL , 0 } ,
/* 0x3f */ { NULL , NULL , 0 } ,
/* 0x40 */ { NULL , NULL , 0 } ,
/* 0x41 */ { NULL , NULL , 0 } ,
/* 0x42 */ { NULL , NULL , 0 } ,
/* 0x43 */ { NULL , NULL , 0 } ,
/* 0x44 */ { NULL , NULL , 0 } ,
/* 0x45 */ { NULL , NULL , 0 } ,
/* 0x46 */ { NULL , NULL , 0 } ,
/* 0x47 */ { NULL , NULL , 0 } ,
/* 0x48 */ { NULL , NULL , 0 } ,
/* 0x49 */ { NULL , NULL , 0 } ,
/* 0x4a */ { NULL , NULL , 0 } ,
/* 0x4b */ { NULL , NULL , 0 } ,
/* 0x4c */ { NULL , NULL , 0 } ,
/* 0x4d */ { NULL , NULL , 0 } ,
/* 0x4e */ { NULL , NULL , 0 } ,
/* 0x4f */ { NULL , NULL , 0 } ,
/* 0x50 */ { NULL , NULL , 0 } ,
/* 0x51 */ { NULL , NULL , 0 } ,
/* 0x52 */ { NULL , NULL , 0 } ,
/* 0x53 */ { NULL , NULL , 0 } ,
/* 0x54 */ { NULL , NULL , 0 } ,
/* 0x55 */ { NULL , NULL , 0 } ,
/* 0x56 */ { NULL , NULL , 0 } ,
/* 0x57 */ { NULL , NULL , 0 } ,
/* 0x58 */ { NULL , NULL , 0 } ,
/* 0x59 */ { NULL , NULL , 0 } ,
/* 0x5a */ { NULL , NULL , 0 } ,
/* 0x5b */ { NULL , NULL , 0 } ,
/* 0x5c */ { NULL , NULL , 0 } ,
/* 0x5d */ { NULL , NULL , 0 } ,
/* 0x5e */ { NULL , NULL , 0 } ,
/* 0x5f */ { NULL , NULL , 0 } ,
/* 0x60 */ { NULL , NULL , 0 } ,
/* 0x61 */ { NULL , NULL , 0 } ,
/* 0x62 */ { NULL , NULL , 0 } ,
/* 0x63 */ { NULL , NULL , 0 } ,
/* 0x64 */ { NULL , NULL , 0 } ,
/* 0x65 */ { NULL , NULL , 0 } ,
/* 0x66 */ { NULL , NULL , 0 } ,
/* 0x67 */ { NULL , NULL , 0 } ,
/* 0x68 */ { NULL , NULL , 0 } ,
/* 0x69 */ { NULL , NULL , 0 } ,
/* 0x6a */ { NULL , NULL , 0 } ,
/* 0x6b */ { NULL , NULL , 0 } ,
/* 0x6c */ { NULL , NULL , 0 } ,
/* 0x6d */ { NULL , NULL , 0 } ,
/* 0x6e */ { NULL , NULL , 0 } ,
/* 0x6f */ { NULL , NULL , 0 } ,
2006-03-16 21:26:14 +03:00
/* 0x70 */ { " SMBtcon " , smbsrv_reply_tcon , NEED_SESS } ,
2006-03-26 01:29:45 +03:00
/* 0x71 */ { " SMBtdis " , smbsrv_reply_tdis , NEED_TCON } ,
2006-03-16 21:26:14 +03:00
/* 0x72 */ { " SMBnegprot " , smbsrv_reply_negprot , 0 } ,
2008-03-10 13:06:12 +03:00
/* 0x73 */ { " SMBsesssetupX " , smbsrv_reply_sesssetup , AND_X } ,
/* 0x74 */ { " SMBulogoffX " , smbsrv_reply_ulogoffX , NEED_SESS | AND_X } , /* ulogoff doesn't give a valid TID */
/* 0x75 */ { " SMBtconX " , smbsrv_reply_tcon_and_X , NEED_SESS | AND_X } ,
2005-11-17 11:00:48 +03:00
/* 0x76 */ { NULL , NULL , 0 } ,
/* 0x77 */ { NULL , NULL , 0 } ,
/* 0x78 */ { NULL , NULL , 0 } ,
/* 0x79 */ { NULL , NULL , 0 } ,
/* 0x7a */ { NULL , NULL , 0 } ,
/* 0x7b */ { NULL , NULL , 0 } ,
/* 0x7c */ { NULL , NULL , 0 } ,
/* 0x7d */ { NULL , NULL , 0 } ,
/* 0x7e */ { NULL , NULL , 0 } ,
/* 0x7f */ { NULL , NULL , 0 } ,
2006-03-16 21:26:14 +03:00
/* 0x80 */ { " SMBdskattr " , smbsrv_reply_dskattr , NEED_SESS | NEED_TCON } ,
/* 0x81 */ { " SMBsearch " , smbsrv_reply_search , NEED_SESS | NEED_TCON } ,
/* 0x82 */ { " SMBffirst " , smbsrv_reply_search , NEED_SESS | NEED_TCON } ,
/* 0x83 */ { " SMBfunique " , smbsrv_reply_search , NEED_SESS | NEED_TCON } ,
/* 0x84 */ { " SMBfclose " , smbsrv_reply_fclose , NEED_SESS | NEED_TCON } ,
2005-11-17 11:00:48 +03:00
/* 0x85 */ { NULL , NULL , 0 } ,
/* 0x86 */ { NULL , NULL , 0 } ,
/* 0x87 */ { NULL , NULL , 0 } ,
/* 0x88 */ { NULL , NULL , 0 } ,
/* 0x89 */ { NULL , NULL , 0 } ,
/* 0x8a */ { NULL , NULL , 0 } ,
/* 0x8b */ { NULL , NULL , 0 } ,
/* 0x8c */ { NULL , NULL , 0 } ,
/* 0x8d */ { NULL , NULL , 0 } ,
/* 0x8e */ { NULL , NULL , 0 } ,
/* 0x8f */ { NULL , NULL , 0 } ,
/* 0x90 */ { NULL , NULL , 0 } ,
/* 0x91 */ { NULL , NULL , 0 } ,
/* 0x92 */ { NULL , NULL , 0 } ,
/* 0x93 */ { NULL , NULL , 0 } ,
/* 0x94 */ { NULL , NULL , 0 } ,
/* 0x95 */ { NULL , NULL , 0 } ,
/* 0x96 */ { NULL , NULL , 0 } ,
/* 0x97 */ { NULL , NULL , 0 } ,
/* 0x98 */ { NULL , NULL , 0 } ,
/* 0x99 */ { NULL , NULL , 0 } ,
/* 0x9a */ { NULL , NULL , 0 } ,
/* 0x9b */ { NULL , NULL , 0 } ,
/* 0x9c */ { NULL , NULL , 0 } ,
/* 0x9d */ { NULL , NULL , 0 } ,
/* 0x9e */ { NULL , NULL , 0 } ,
/* 0x9f */ { NULL , NULL , 0 } ,
2008-03-10 13:06:12 +03:00
/* 0xa0 */ { " SMBnttrans " , smbsrv_reply_nttrans , NEED_SESS | NEED_TCON | LARGE_REQUEST } ,
2006-03-16 21:26:14 +03:00
/* 0xa1 */ { " SMBnttranss " , smbsrv_reply_nttranss , NEED_SESS | NEED_TCON } ,
2008-03-10 13:06:12 +03:00
/* 0xa2 */ { " SMBntcreateX " , smbsrv_reply_ntcreate_and_X , NEED_SESS | NEED_TCON | AND_X } ,
2005-11-17 11:00:48 +03:00
/* 0xa3 */ { NULL , NULL , 0 } ,
2006-03-16 21:26:14 +03:00
/* 0xa4 */ { " SMBntcancel " , smbsrv_reply_ntcancel , NEED_SESS | NEED_TCON | SIGNING_NO_REPLY } ,
/* 0xa5 */ { " SMBntrename " , smbsrv_reply_ntrename , NEED_SESS | NEED_TCON } ,
2005-11-17 11:00:48 +03:00
/* 0xa6 */ { NULL , NULL , 0 } ,
/* 0xa7 */ { NULL , NULL , 0 } ,
/* 0xa8 */ { NULL , NULL , 0 } ,
/* 0xa9 */ { NULL , NULL , 0 } ,
/* 0xaa */ { NULL , NULL , 0 } ,
/* 0xab */ { NULL , NULL , 0 } ,
/* 0xac */ { NULL , NULL , 0 } ,
/* 0xad */ { NULL , NULL , 0 } ,
/* 0xae */ { NULL , NULL , 0 } ,
/* 0xaf */ { NULL , NULL , 0 } ,
/* 0xb0 */ { NULL , NULL , 0 } ,
/* 0xb1 */ { NULL , NULL , 0 } ,
/* 0xb2 */ { NULL , NULL , 0 } ,
/* 0xb3 */ { NULL , NULL , 0 } ,
/* 0xb4 */ { NULL , NULL , 0 } ,
/* 0xb5 */ { NULL , NULL , 0 } ,
/* 0xb6 */ { NULL , NULL , 0 } ,
/* 0xb7 */ { NULL , NULL , 0 } ,
/* 0xb8 */ { NULL , NULL , 0 } ,
/* 0xb9 */ { NULL , NULL , 0 } ,
/* 0xba */ { NULL , NULL , 0 } ,
/* 0xbb */ { NULL , NULL , 0 } ,
/* 0xbc */ { NULL , NULL , 0 } ,
/* 0xbd */ { NULL , NULL , 0 } ,
/* 0xbe */ { NULL , NULL , 0 } ,
/* 0xbf */ { NULL , NULL , 0 } ,
2006-03-16 21:26:14 +03:00
/* 0xc0 */ { " SMBsplopen " , smbsrv_reply_printopen , NEED_SESS | NEED_TCON } ,
/* 0xc1 */ { " SMBsplwr " , smbsrv_reply_printwrite , NEED_SESS | NEED_TCON } ,
/* 0xc2 */ { " SMBsplclose " , smbsrv_reply_printclose , NEED_SESS | NEED_TCON } ,
/* 0xc3 */ { " SMBsplretq " , smbsrv_reply_printqueue , NEED_SESS | NEED_TCON } ,
2005-11-17 11:00:48 +03:00
/* 0xc4 */ { NULL , NULL , 0 } ,
/* 0xc5 */ { NULL , NULL , 0 } ,
/* 0xc6 */ { NULL , NULL , 0 } ,
/* 0xc7 */ { NULL , NULL , 0 } ,
/* 0xc8 */ { NULL , NULL , 0 } ,
/* 0xc9 */ { NULL , NULL , 0 } ,
/* 0xca */ { NULL , NULL , 0 } ,
/* 0xcb */ { NULL , NULL , 0 } ,
/* 0xcc */ { NULL , NULL , 0 } ,
/* 0xcd */ { NULL , NULL , 0 } ,
/* 0xce */ { NULL , NULL , 0 } ,
/* 0xcf */ { NULL , NULL , 0 } ,
2006-03-16 21:26:14 +03:00
/* 0xd0 */ { " SMBsends " , NULL , 0 } ,
2006-03-06 18:31:01 +03:00
/* 0xd1 */ { " SMBsendb " , NULL , 0 } ,
/* 0xd2 */ { " SMBfwdname " , NULL , 0 } ,
/* 0xd3 */ { " SMBcancelf " , NULL , 0 } ,
/* 0xd4 */ { " SMBgetmac " , NULL , 0 } ,
2006-03-16 21:26:14 +03:00
/* 0xd5 */ { " SMBsendstrt " , NULL , 0 } ,
/* 0xd6 */ { " SMBsendend " , NULL , 0 } ,
/* 0xd7 */ { " SMBsendtxt " , NULL , 0 } ,
2005-11-17 11:00:48 +03:00
/* 0xd8 */ { NULL , NULL , 0 } ,
/* 0xd9 */ { NULL , NULL , 0 } ,
/* 0xda */ { NULL , NULL , 0 } ,
/* 0xdb */ { NULL , NULL , 0 } ,
/* 0xdc */ { NULL , NULL , 0 } ,
/* 0xdd */ { NULL , NULL , 0 } ,
/* 0xde */ { NULL , NULL , 0 } ,
/* 0xdf */ { NULL , NULL , 0 } ,
/* 0xe0 */ { NULL , NULL , 0 } ,
/* 0xe1 */ { NULL , NULL , 0 } ,
/* 0xe2 */ { NULL , NULL , 0 } ,
/* 0xe3 */ { NULL , NULL , 0 } ,
/* 0xe4 */ { NULL , NULL , 0 } ,
/* 0xe5 */ { NULL , NULL , 0 } ,
/* 0xe6 */ { NULL , NULL , 0 } ,
/* 0xe7 */ { NULL , NULL , 0 } ,
/* 0xe8 */ { NULL , NULL , 0 } ,
/* 0xe9 */ { NULL , NULL , 0 } ,
/* 0xea */ { NULL , NULL , 0 } ,
/* 0xeb */ { NULL , NULL , 0 } ,
/* 0xec */ { NULL , NULL , 0 } ,
/* 0xed */ { NULL , NULL , 0 } ,
/* 0xee */ { NULL , NULL , 0 } ,
/* 0xef */ { NULL , NULL , 0 } ,
/* 0xf0 */ { NULL , NULL , 0 } ,
/* 0xf1 */ { NULL , NULL , 0 } ,
/* 0xf2 */ { NULL , NULL , 0 } ,
/* 0xf3 */ { NULL , NULL , 0 } ,
/* 0xf4 */ { NULL , NULL , 0 } ,
/* 0xf5 */ { NULL , NULL , 0 } ,
/* 0xf6 */ { NULL , NULL , 0 } ,
/* 0xf7 */ { NULL , NULL , 0 } ,
/* 0xf8 */ { NULL , NULL , 0 } ,
/* 0xf9 */ { NULL , NULL , 0 } ,
/* 0xfa */ { NULL , NULL , 0 } ,
/* 0xfb */ { NULL , NULL , 0 } ,
/* 0xfc */ { NULL , NULL , 0 } ,
/* 0xfd */ { NULL , NULL , 0 } ,
/* 0xfe */ { NULL , NULL , 0 } ,
/* 0xff */ { NULL , NULL , 0 }
} ;
2008-03-10 13:03:38 +03:00
/****************************************************************************
receive a SMB request header from the wire , forming a request_context
from the result
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-02-02 10:39:45 +03:00
NTSTATUS smbsrv_recv_smb_request ( void * private_data , DATA_BLOB blob )
2008-03-10 13:03:38 +03:00
{
2009-02-02 10:39:45 +03:00
struct smbsrv_connection * smb_conn = talloc_get_type ( private_data , struct smbsrv_connection ) ;
2008-03-10 13:03:38 +03:00
struct smbsrv_request * req ;
struct timeval cur_time = timeval_current ( ) ;
uint8_t command ;
smb_conn - > statistics . last_request_time = cur_time ;
/* see if its a special NBT packet */
if ( CVAL ( blob . data , 0 ) ! = 0 ) {
req = smbsrv_init_request ( smb_conn ) ;
NT_STATUS_HAVE_NO_MEMORY ( req ) ;
ZERO_STRUCT ( req - > in ) ;
req - > in . buffer = talloc_steal ( req , blob . data ) ;
req - > in . size = blob . length ;
req - > request_time = cur_time ;
smbsrv_reply_special ( req ) ;
return NT_STATUS_OK ;
}
if ( ( NBT_HDR_SIZE + MIN_SMB_SIZE ) > blob . length ) {
DEBUG ( 2 , ( " Invalid SMB packet: length %ld \n " , ( long ) blob . length ) ) ;
smbsrv_terminate_connection ( smb_conn , " Invalid SMB packet " ) ;
return NT_STATUS_OK ;
}
/* Make sure this is an SMB packet */
if ( IVAL ( blob . data , NBT_HDR_SIZE ) ! = SMB_MAGIC ) {
DEBUG ( 2 , ( " Non-SMB packet of length %ld. Terminating connection \n " ,
( long ) blob . length ) ) ;
smbsrv_terminate_connection ( smb_conn , " Non-SMB packet " ) ;
return NT_STATUS_OK ;
}
req = smbsrv_init_request ( smb_conn ) ;
NT_STATUS_HAVE_NO_MEMORY ( req ) ;
req - > in . buffer = talloc_steal ( req , blob . data ) ;
req - > in . size = blob . length ;
req - > request_time = cur_time ;
req - > chained_fnum = - 1 ;
req - > in . allocated = req - > in . size ;
req - > in . hdr = req - > in . buffer + NBT_HDR_SIZE ;
req - > in . vwv = req - > in . hdr + HDR_VWV ;
req - > in . wct = CVAL ( req - > in . hdr , HDR_WCT ) ;
2008-03-10 13:06:12 +03:00
command = CVAL ( req - > in . hdr , HDR_COM ) ;
2008-03-10 13:03:38 +03:00
if ( req - > in . vwv + VWV ( req - > in . wct ) < = req - > in . buffer + req - > in . size ) {
req - > in . data = req - > in . vwv + VWV ( req - > in . wct ) + 2 ;
req - > in . data_size = SVAL ( req - > in . vwv , VWV ( req - > in . wct ) ) ;
2009-08-05 14:23:12 +04:00
/* special handling for oversize calls. Windows seems
to take the maximum of the BCC value and the
computed buffer size . This handles oversized writeX
calls , and possibly oversized SMBtrans calls */
if ( ( message_flags ( command ) & LARGE_REQUEST ) & &
( ! ( message_flags ( command ) & AND_X ) | |
( req - > in . wct < 1 | | SVAL ( req - > in . vwv , VWV ( 0 ) ) = = SMB_CHAIN_NONE ) ) & &
req - > in . data_size < req - > in . size - PTR_DIFF ( req - > in . data , req - > in . buffer ) ) {
2008-03-10 13:03:38 +03:00
req - > in . data_size = req - > in . size - PTR_DIFF ( req - > in . data , req - > in . buffer ) ;
}
}
if ( NBT_HDR_SIZE + MIN_SMB_SIZE + 2 * req - > in . wct > req - > in . size ) {
DEBUG ( 2 , ( " Invalid SMB word count %d \n " , req - > in . wct ) ) ;
smbsrv_terminate_connection ( req - > smb_conn , " Invalid SMB packet " ) ;
return NT_STATUS_OK ;
}
if ( NBT_HDR_SIZE + MIN_SMB_SIZE + 2 * req - > in . wct + req - > in . data_size > req - > in . size ) {
DEBUG ( 2 , ( " Invalid SMB buffer length count %d \n " ,
( int ) req - > in . data_size ) ) ;
smbsrv_terminate_connection ( req - > smb_conn , " Invalid SMB packet " ) ;
return NT_STATUS_OK ;
}
req - > flags2 = SVAL ( req - > in . hdr , HDR_FLG2 ) ;
/* fix the bufinfo */
smbsrv_setup_bufinfo ( req ) ;
if ( ! smbsrv_signing_check_incoming ( req ) ) {
smbsrv_send_error ( req , NT_STATUS_ACCESS_DENIED ) ;
return NT_STATUS_OK ;
}
command = CVAL ( req - > in . hdr , HDR_COM ) ;
switch_message ( command , req ) ;
return NT_STATUS_OK ;
}
2005-11-17 11:00:48 +03:00
/****************************************************************************
return a string containing the function name of a SMB command
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const char * smb_fn_name ( uint8_t type )
{
const char * unknown_name = " SMBunknown " ;
if ( smb_messages [ type ] . name = = NULL )
return unknown_name ;
return smb_messages [ type ] . name ;
}
/****************************************************************************
Do a switch on the message type and call the specific reply function for this
message . Unlike earlier versions of Samba the reply functions are responsible
for sending the reply themselves , rather than returning a size to this function
The reply functions may also choose to delay the processing by pushing the message
onto the message queue
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void switch_message ( int type , struct smbsrv_request * req )
{
int flags ;
struct smbsrv_connection * smb_conn = req - > smb_conn ;
NTSTATUS status ;
2015-04-28 14:30:58 +03:00
struct server_id_buf idbuf ;
2005-11-17 11:00:48 +03:00
type & = 0xff ;
errno = 0 ;
if ( smb_messages [ type ] . fn = = NULL ) {
DEBUG ( 0 , ( " Unknown message type %d! \n " , type ) ) ;
2006-03-06 18:31:01 +03:00
smbsrv_reply_unknown ( req ) ;
2005-11-17 11:00:48 +03:00
return ;
}
flags = smb_messages [ type ] . flags ;
2006-03-26 15:32:27 +04:00
req - > tcon = smbsrv_smb_tcon_find ( smb_conn , SVAL ( req - > in . hdr , HDR_TID ) , req - > request_time ) ;
2005-11-17 11:00:48 +03:00
2005-11-17 15:52:40 +03:00
if ( ! req - > session ) {
2005-11-17 11:00:48 +03:00
/* setup the user context for this request if it
hasn ' t already been initialised ( to cope with SMB
chaining ) */
2011-11-02 00:43:43 +04:00
req - > session = smbsrv_session_find ( req - > smb_conn , SVAL ( req - > in . hdr , HDR_UID ) , req - > request_time ) ;
2005-11-17 11:00:48 +03:00
}
2015-04-28 14:30:58 +03:00
DEBUG ( 5 , ( " switch message %s (task_id %s) \n " ,
smb_fn_name ( type ) ,
server_id_str_buf ( req - > smb_conn - > connection - > server_id ,
& idbuf ) ) ) ;
2005-11-17 11:00:48 +03:00
/* this must be called before we do any reply */
if ( flags & SIGNING_NO_REPLY ) {
2006-03-06 19:19:27 +03:00
smbsrv_signing_no_reply ( req ) ;
2005-11-17 11:00:48 +03:00
}
/* see if the vuid is valid */
2006-03-16 21:26:14 +03:00
if ( ( flags & NEED_SESS ) & & ! req - > session ) {
2006-07-27 22:06:09 +04:00
status = NT_STATUS_DOS ( ERRSRV , ERRbaduid ) ;
2005-11-17 11:00:48 +03:00
/* amazingly, the error code depends on the command */
switch ( type ) {
2006-07-27 22:06:09 +04:00
case SMBntcreateX :
case SMBntcancel :
case SMBulogoffX :
break ;
default :
if ( req - > smb_conn - > config . nt_status_support & &
req - > smb_conn - > negotiate . client_caps & CAP_STATUS32 ) {
2005-11-17 11:00:48 +03:00
status = NT_STATUS_INVALID_HANDLE ;
2006-07-27 22:06:09 +04:00
}
break ;
2005-11-17 11:00:48 +03:00
}
/*
* TODO :
* don ' t know how to handle smb signing for this case
* so just skip the reply
*/
if ( ( flags & SIGNING_NO_REPLY ) & &
( req - > smb_conn - > signing . signing_state ! = SMB_SIGNING_ENGINE_OFF ) ) {
DEBUG ( 1 , ( " SKIP ERROR REPLY: %s %s because of unknown smb signing case \n " ,
smb_fn_name ( type ) , nt_errstr ( status ) ) ) ;
2006-03-06 18:38:07 +03:00
talloc_free ( req ) ;
2005-11-17 11:00:48 +03:00
return ;
}
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , status ) ;
2005-11-17 11:00:48 +03:00
return ;
}
/* does this protocol need a valid tree connection? */
2006-03-16 21:26:14 +03:00
if ( ( flags & NEED_TCON ) & & ! req - > tcon ) {
2006-07-27 22:06:09 +04:00
status = NT_STATUS_DOS ( ERRSRV , ERRinvnid ) ;
2005-11-17 11:00:48 +03:00
/* amazingly, the error code depends on the command */
switch ( type ) {
2006-07-27 22:06:09 +04:00
case SMBntcreateX :
case SMBntcancel :
case SMBtdis :
break ;
default :
if ( req - > smb_conn - > config . nt_status_support & &
req - > smb_conn - > negotiate . client_caps & CAP_STATUS32 ) {
2005-11-17 11:00:48 +03:00
status = NT_STATUS_INVALID_HANDLE ;
2006-07-27 22:06:09 +04:00
}
break ;
2005-11-17 11:00:48 +03:00
}
/*
* TODO :
* don ' t know how to handle smb signing for this case
* so just skip the reply
*/
if ( ( flags & SIGNING_NO_REPLY ) & &
( req - > smb_conn - > signing . signing_state ! = SMB_SIGNING_ENGINE_OFF ) ) {
DEBUG ( 1 , ( " SKIP ERROR REPLY: %s %s because of unknown smb signing case \n " ,
smb_fn_name ( type ) , nt_errstr ( status ) ) ) ;
2006-03-06 18:38:07 +03:00
talloc_free ( req ) ;
2005-11-17 11:00:48 +03:00
return ;
}
2006-03-06 19:19:27 +03:00
smbsrv_send_error ( req , status ) ;
2005-11-17 11:00:48 +03:00
return ;
}
smb_messages [ type ] . fn ( req ) ;
}
/*
we call this when first first part of a possibly chained request has been completed
and we need to call the 2 nd part , if any
*/
2006-03-06 18:00:42 +03:00
void smbsrv_chain_reply ( struct smbsrv_request * req )
2005-11-17 11:00:48 +03:00
{
uint16_t chain_cmd , chain_offset ;
uint8_t * vwv , * data ;
uint16_t wct ;
uint16_t data_size ;
if ( req - > in . wct < 2 | | req - > out . wct < 2 ) {
2006-03-06 21:29:48 +03:00
smbsrv_send_error ( req , NT_STATUS_DOS ( ERRSRV , ERRerror ) ) ;
2005-11-17 11:00:48 +03:00
return ;
}
chain_cmd = CVAL ( req - > in . vwv , VWV ( 0 ) ) ;
chain_offset = SVAL ( req - > in . vwv , VWV ( 1 ) ) ;
if ( chain_cmd = = SMB_CHAIN_NONE ) {
/* end of chain */
SSVAL ( req - > out . vwv , VWV ( 0 ) , SMB_CHAIN_NONE ) ;
SSVAL ( req - > out . vwv , VWV ( 1 ) , 0 ) ;
2006-03-06 19:19:27 +03:00
smbsrv_send_reply ( req ) ;
2005-11-17 11:00:48 +03:00
return ;
}
if ( chain_offset + req - > in . hdr > = req - > in . buffer + req - > in . size ) {
goto error ;
}
wct = CVAL ( req - > in . hdr , chain_offset ) ;
vwv = req - > in . hdr + chain_offset + 1 ;
if ( vwv + VWV ( wct ) + 2 > req - > in . buffer + req - > in . size ) {
goto error ;
}
data_size = SVAL ( vwv , VWV ( wct ) ) ;
data = vwv + VWV ( wct ) + 2 ;
if ( data + data_size > req - > in . buffer + req - > in . size ) {
goto error ;
}
/* all seems legit */
req - > in . vwv = vwv ;
req - > in . wct = wct ;
req - > in . data = data ;
req - > in . data_size = data_size ;
req - > in . ptr = data ;
2008-02-14 02:12:33 +03:00
/* fix the bufinfo */
smbsrv_setup_bufinfo ( req ) ;
2005-11-17 11:00:48 +03:00
req - > chain_count + + ;
SSVAL ( req - > out . vwv , VWV ( 0 ) , chain_cmd ) ;
SSVAL ( req - > out . vwv , VWV ( 1 ) , req - > out . size - NBT_HDR_SIZE ) ;
2006-03-18 14:10:21 +03:00
/* cleanup somestuff for the next request */
2012-03-20 02:52:25 +04:00
DLIST_REMOVE ( req - > smb_conn - > requests , req ) ;
2012-05-24 13:57:02 +04:00
talloc_unlink ( req , req - > ntvfs ) ;
2006-03-18 14:10:21 +03:00
req - > ntvfs = NULL ;
talloc_free ( req - > io_ptr ) ;
req - > io_ptr = NULL ;
2005-11-17 11:00:48 +03:00
switch_message ( chain_cmd , req ) ;
return ;
error :
SSVAL ( req - > out . vwv , VWV ( 0 ) , SMB_CHAIN_NONE ) ;
SSVAL ( req - > out . vwv , VWV ( 1 ) , 0 ) ;
2006-03-06 21:29:48 +03:00
smbsrv_send_error ( req , NT_STATUS_DOS ( ERRSRV , ERRerror ) ) ;
2005-11-17 11:00:48 +03:00
}
2005-11-18 11:44:36 +03:00
/*
* init the SMB protocol related stuff
*/
2007-12-03 00:32:11 +03:00
NTSTATUS smbsrv_init_smb_connection ( struct smbsrv_connection * smb_conn , struct loadparm_context * lp_ctx )
2005-11-18 11:44:36 +03:00
{
NTSTATUS status ;
/* now initialise a few default values associated with this smb socket */
smb_conn - > negotiate . max_send = 0xFFFF ;
/* this is the size that w2k uses, and it appears to be important for
good performance */
2010-07-16 08:32:42 +04:00
smb_conn - > negotiate . max_recv = lpcfg_max_xmit ( lp_ctx ) ;
2005-11-18 11:44:36 +03:00
smb_conn - > negotiate . zone_offset = get_time_zone ( time ( NULL ) ) ;
2010-07-16 08:32:42 +04:00
smb_conn - > config . nt_status_support = lpcfg_nt_status_support ( lp_ctx ) ;
2005-11-18 11:44:36 +03:00
2005-11-18 15:57:48 +03:00
status = smbsrv_init_sessions ( smb_conn , UINT16_MAX ) ;
2005-11-18 11:44:36 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2005-12-06 20:59:20 +03:00
status = smbsrv_smb_init_tcons ( smb_conn ) ;
2005-11-18 11:44:36 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2006-03-06 19:19:27 +03:00
smbsrv_init_signing ( smb_conn ) ;
2005-11-18 11:44:36 +03:00
return NT_STATUS_OK ;
}