2005-11-11 07:45:38 +03:00
/*
Unix SMB / CIFS implementation .
SMB2 client library header
Copyright ( C ) Andrew Tridgell 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-11 07:45:38 +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-11 07:45:38 +03:00
*/
2008-02-14 02:12:33 +03:00
# include "libcli/raw/request.h"
2005-11-11 07:45:38 +03:00
struct smb2_options {
uint32_t timeout ;
} ;
/*
information returned from the negotiate response
*/
struct smb2_negotiate {
DATA_BLOB secblob ;
} ;
/* this is the context for the smb2 transport layer */
struct smb2_transport {
/* socket level info */
struct smbcli_socket * socket ;
struct smb2_options options ;
struct smb2_negotiate negotiate ;
/* next seqnum to allocate */
uint64_t seqnum ;
/* a list of requests that are pending for receive on this
connection */
struct smb2_request * pending_recv ;
/* context of the stream -> packet parser */
struct packet_context * packet ;
2006-07-17 11:45:23 +04:00
/* an idle function - if this is defined then it will be
called once every period microseconds while we are waiting
for a packet */
struct {
void ( * func ) ( struct smb2_transport * , void * ) ;
void * private ;
uint_t period ;
} idle ;
2005-11-11 07:45:38 +03:00
} ;
2005-11-11 12:11:51 +03:00
/*
SMB2 tree context
*/
struct smb2_tree {
struct smb2_session * session ;
2005-11-11 15:37:16 +03:00
uint32_t tid ;
2005-11-11 12:11:51 +03:00
} ;
2005-11-11 08:53:54 +03:00
/*
SMB2 session context
*/
struct smb2_session {
struct smb2_transport * transport ;
2005-11-11 09:26:42 +03:00
struct gensec_security * gensec ;
2005-11-11 10:23:45 +03:00
uint64_t uid ;
2005-11-25 08:23:55 +03:00
DATA_BLOB session_key ;
2005-11-11 08:53:54 +03:00
} ;
2005-11-11 12:11:51 +03:00
2005-11-11 07:45:38 +03:00
struct smb2_request_buffer {
/* the raw SMB2 buffer, including the 4 byte length header */
uint8_t * buffer ;
/* the size of the raw buffer, including 4 byte header */
2006-04-24 13:36:09 +04:00
size_t size ;
2005-11-11 07:45:38 +03:00
/* how much has been allocated - on reply the buffer is over-allocated to
prevent too many realloc ( ) calls
*/
2006-04-24 13:36:09 +04:00
size_t allocated ;
2005-11-11 07:45:38 +03:00
/* the start of the SMB2 header - this is always buffer+4 */
uint8_t * hdr ;
/* the packet body */
uint8_t * body ;
2006-06-30 03:11:07 +04:00
size_t body_fixed ;
2006-04-24 13:36:09 +04:00
size_t body_size ;
2005-11-16 14:01:15 +03:00
/* this point to the next dynamic byte that can be used
* this will be moved when some dynamic data is pushed
*/
uint8_t * dynamic ;
2008-02-14 02:12:33 +03:00
/* this is used to range check and align strings and buffers */
struct request_bufinfo bufinfo ;
2005-11-11 07:45:38 +03:00
} ;
/*
a client request moves between the following 4 states .
*/
enum smb2_request_state { SMB2_REQUEST_INIT , /* we are creating the request */
SMB2_REQUEST_RECV , /* we are waiting for a matching reply */
SMB2_REQUEST_DONE , /* the request is finished */
SMB2_REQUEST_ERROR } ; /* a packet or transport level error has occurred */
/* the context for a single SMB2 request */
struct smb2_request {
/* allow a request to be part of a list of requests */
struct smb2_request * next , * prev ;
/* each request is in one of 3 possible states */
enum smb2_request_state state ;
struct smb2_transport * transport ;
2005-11-12 04:08:43 +03:00
struct smb2_session * session ;
struct smb2_tree * tree ;
2005-11-11 07:45:38 +03:00
uint64_t seqnum ;
2006-07-17 13:36:52 +04:00
struct {
2007-08-27 22:10:19 +04:00
bool do_cancel ;
bool can_cancel ;
2006-07-17 13:36:52 +04:00
uint32_t pending_id ;
} cancel ;
2005-11-11 07:45:38 +03:00
/* the NT status for this request. Set by packet receive code
or code detecting error . */
NTSTATUS status ;
struct smb2_request_buffer in ;
struct smb2_request_buffer out ;
/* information on what to do with a reply when it is received
asyncronously . If this is not setup when a reply is received then
the reply is discarded
The private pointer is private to the caller of the client
library ( the application ) , not private to the library
*/
struct {
void ( * fn ) ( struct smb2_request * ) ;
void * private ;
} async ;
} ;
2005-11-17 03:48:24 +03:00
# define SMB2_MIN_SIZE 0x42
2005-11-11 07:45:38 +03:00
2008-02-12 09:00:35 +03:00
/* offsets into header elements for a sync SMB2 request */
# define SMB2_HDR_PROTOCOL_ID 0x00
2006-07-01 18:14:11 +04:00
# define SMB2_HDR_LENGTH 0x04
2008-02-12 09:00:35 +03:00
# define SMB2_HDR_EPOCH 0x06
2006-07-01 18:14:11 +04:00
# define SMB2_HDR_STATUS 0x08
# define SMB2_HDR_OPCODE 0x0c
2008-02-12 09:00:35 +03:00
# define SMB2_HDR_CREDIT 0x0e
2006-07-01 18:14:11 +04:00
# define SMB2_HDR_FLAGS 0x10
2008-02-12 09:00:35 +03:00
# define SMB2_HDR_NEXT_COMMAND 0x14
# define SMB2_HDR_MESSAGE_ID 0x18
2006-07-01 18:14:11 +04:00
# define SMB2_HDR_PID 0x20
# define SMB2_HDR_TID 0x24
2008-02-12 09:00:35 +03:00
# define SMB2_HDR_SESSION_ID 0x28
# define SMB2_HDR_SIGNATURE 0x30 /* 16 bytes */
2006-07-01 18:14:11 +04:00
# define SMB2_HDR_BODY 0x40
2005-11-11 07:45:38 +03:00
/* SMB2 opcodes */
# define SMB2_OP_NEGPROT 0x00
# define SMB2_OP_SESSSETUP 0x01
2005-11-25 14:04:42 +03:00
# define SMB2_OP_LOGOFF 0x02
2005-11-11 07:45:38 +03:00
# define SMB2_OP_TCON 0x03
# define SMB2_OP_TDIS 0x04
# define SMB2_OP_CREATE 0x05
# define SMB2_OP_CLOSE 0x06
2005-11-25 14:33:57 +03:00
# define SMB2_OP_FLUSH 0x07
2005-11-11 07:45:38 +03:00
# define SMB2_OP_READ 0x08
# define SMB2_OP_WRITE 0x09
2005-12-01 03:18:29 +03:00
# define SMB2_OP_LOCK 0x0a
# define SMB2_OP_IOCTL 0x0b
2005-11-12 10:48:56 +03:00
# define SMB2_OP_CANCEL 0x0c
2005-11-25 14:51:15 +03:00
# define SMB2_OP_KEEPALIVE 0x0d
2005-11-11 07:45:38 +03:00
# define SMB2_OP_FIND 0x0e
2005-11-12 10:48:56 +03:00
# define SMB2_OP_NOTIFY 0x0f
2005-11-12 05:45:49 +03:00
# define SMB2_OP_GETINFO 0x10
# define SMB2_OP_SETINFO 0x11
# define SMB2_OP_BREAK 0x12
2005-11-11 07:45:38 +03:00
# define SMB2_MAGIC 0x424D53FE /* 0xFE 'S' 'M' 'B' */
2008-02-14 09:11:36 +03:00
/* the dialect we support */
# define SMB2_DIALECT_REVISION 0x202
2008-02-13 02:13:28 +03:00
/* SMB2 negotiate security_mode */
# define SMB2_NEGOTIATE_SIGNING_ENABLED 0x01
# define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x02
/* SMB2 capabilities - only 1 so far. I'm sure more will be added */
# define SMB2_CAP_DFS 0x0
/* so we can spot new caps as added */
# define SMB2_CAP_ALL SMB2_CAP_DFS
/* SMB2 share flags */
# define SMB2_SHAREFLAG_MANUAL_CACHING 0x0000
# define SMB2_SHAREFLAG_AUTO_CACHING 0x0010
# define SMB2_SHAREFLAG_VDO_CACHING 0x0020
# define SMB2_SHAREFLAG_NO_CACHING 0x0030
# define SMB2_SHAREFLAG_DFS 0x0001
# define SMB2_SHAREFLAG_DFS_ROOT 0x0002
# define SMB2_SHAREFLAG_RESTRICT_EXCLUSIVE_OPENS 0x0100
# define SMB2_SHAREFLAG_FORCE_SHARED_DELETE 0x0200
# define SMB2_SHAREFLAG_ALLOW_NAMESPACE_CACHING 0x0400
# define SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM 0x0800
# define SMB2_SHAREFLAG_ALL 0x0F33
2008-02-13 07:05:44 +03:00
/* SMB2 create security flags */
# define SMB2_SECURITY_DYNAMIC_TRACKING 0x01
# define SMB2_SECURITY_EFFECTIVE_ONLY 0x02
/* SMB2 requested oplock levels */
# define SMB2_OPLOCK_LEVEL_NONE 0x00
# define SMB2_OPLOCK_LEVEL_II 0x01
# define SMB2_OPLOCK_LEVEL_EXCLUSIVE 0x08
# define SMB2_OPLOCK_LEVEL_BATCH 0x09
/* SMB2 impersonation levels */
# define SMB2_IMPERSONATION_ANONYMOUS 0x00
# define SMB2_IMPERSONATION_IDENTIFICATION 0x01
# define SMB2_IMPERSONATION_IMPERSONATION 0x02
# define SMB2_IMPERSONATION_DELEGATE 0x03
/* SMB2 create tags */
# define SMB2_CREATE_TAG_EXTA "ExtA"
# define SMB2_CREATE_TAG_MXAC "MxAc"
# define SMB2_CREATE_TAG_SECD "SecD"
# define SMB2_CREATE_TAG_DHNQ "DHnQ"
# define SMB2_CREATE_TAG_DHNC "DHnC"
# define SMB2_CREATE_TAG_ALSI "AlSi"
# define SMB2_CREATE_TAG_TWRP "TWrp"
# define SMB2_CREATE_TAG_QFID "QFid"
2005-11-12 02:27:47 +03:00
/*
2005-11-16 14:01:15 +03:00
check that a body has the expected size
2005-11-12 02:27:47 +03:00
*/
2005-11-16 14:01:15 +03:00
# define SMB2_CHECK_PACKET_RECV(req, size, dynamic) do { \
2006-04-24 13:36:09 +04:00
size_t is_size = req - > in . body_size ; \
2005-11-16 14:01:15 +03:00
uint16_t field_size = SVAL ( req - > in . body , 0 ) ; \
uint16_t want_size = ( ( dynamic ) ? ( size ) + 1 : ( size ) ) ; \
if ( is_size < ( size ) ) { \
DEBUG ( 0 , ( " %s: buffer too small 0x%x. Expected 0x%x \n " , \
2006-09-09 14:05:58 +04:00
__location__ , ( unsigned ) is_size , ( unsigned ) want_size ) ) ; \
2005-11-16 14:01:15 +03:00
return NT_STATUS_BUFFER_TOO_SMALL ; \
} \
if ( field_size ! = want_size ) { \
DEBUG ( 0 , ( " %s: unexpected fixed body size 0x%x. Expected 0x%x \n " , \
2006-09-09 14:05:58 +04:00
__location__ , ( unsigned ) field_size , ( unsigned ) want_size ) ) ; \
2005-11-12 02:27:47 +03:00
return NT_STATUS_INVALID_PARAMETER ; \
} \
} while ( 0 )