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-05-16 09:03:58 +04:00
# ifndef __LIBCLI_SMB2_SMB2_H__
# define __LIBCLI_SMB2_SMB2_H__
2008-02-14 02:12:33 +03:00
# include "libcli/raw/request.h"
2008-05-30 11:03:54 +04:00
# include "libcli/raw/libcliraw.h"
2008-02-14 02:12:33 +03:00
2008-04-19 00:27:24 +04:00
struct smb2_handle ;
2009-03-31 02:57:57 +04:00
struct smb2_lease_break ;
2008-04-19 00:27:24 +04:00
2005-11-11 07:45:38 +03:00
/*
2008-05-30 11:03:54 +04:00
information returned from the negotiate process
2005-11-11 07:45:38 +03:00
*/
struct smb2_negotiate {
DATA_BLOB secblob ;
2008-05-20 05:57:43 +04:00
NTTIME system_time ;
NTTIME server_start_time ;
2008-05-30 11:03:54 +04:00
uint16_t security_mode ;
2009-03-12 18:32:58 +03:00
uint16_t dialect_revision ;
2005-11-11 07:45:38 +03:00
} ;
2009-06-08 18:24:27 +04: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 */
size_t size ;
/* how much has been allocated - on reply the buffer is over-allocated to
prevent too many realloc ( ) calls
*/
size_t allocated ;
/* the start of the SMB2 header - this is always buffer+4 */
uint8_t * hdr ;
/* the packet body */
uint8_t * body ;
size_t body_fixed ;
size_t body_size ;
/* this point to the next dynamic byte that can be used
* this will be moved when some dynamic data is pushed
*/
uint8_t * dynamic ;
/* this is used to range check and align strings and buffers */
struct request_bufinfo bufinfo ;
} ;
2005-11-11 07:45:38 +03:00
/* this is the context for the smb2 transport layer */
struct smb2_transport {
/* socket level info */
struct smbcli_socket * socket ;
struct smb2_negotiate negotiate ;
/* next seqnum to allocate */
uint64_t seqnum ;
2009-06-08 18:24:27 +04:00
/* the details for coumpounded requests */
struct {
uint32_t missing ;
bool related ;
struct smb2_request_buffer buffer ;
} compound ;
2009-06-08 19:59:26 +04:00
struct {
2009-07-13 14:25:40 +04:00
uint16_t charge ;
2009-06-08 19:59:26 +04:00
uint16_t ask_num ;
} credits ;
2005-11-11 07:45:38 +03:00
/* 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 * ) ;
2009-02-02 11:56:47 +03:00
void * private_data ;
2006-07-17 11:45:23 +04:00
uint_t period ;
} idle ;
2008-04-19 00:27:24 +04:00
struct {
/* a oplock break request handler */
bool ( * handler ) ( struct smb2_transport * transport ,
const struct smb2_handle * handle ,
uint8_t level , void * private_data ) ;
/* private data passed to the oplock handler */
void * private_data ;
} oplock ;
2008-05-30 11:03:54 +04:00
2009-03-31 02:57:57 +04:00
struct {
/* a lease break request handler */
bool ( * handler ) ( struct smb2_transport * transport ,
const struct smb2_lease_break * lease_break ,
void * private_data ) ;
/* private data passed to the oplock handler */
void * private_data ;
} lease ;
2008-05-30 11:03:54 +04:00
struct smbcli_options options ;
2008-06-09 23:57:41 +04:00
bool signing_required ;
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 ;
2009-11-19 03:35:16 +03:00
uint32_t pid ;
2008-06-07 19:30:51 +04:00
DATA_BLOB session_key ;
2008-06-09 23:57:41 +04:00
bool signing_active ;
2005-11-11 08:53:54 +03:00
} ;
2005-11-11 12:11:51 +03:00
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 * ) ;
2008-05-16 09:03:58 +04:00
void * private_data ;
2005-11-11 07:45:38 +03:00
} async ;
} ;
2005-11-17 03:48:24 +03:00
# define SMB2_MIN_SIZE 0x42
2008-09-25 05:58:38 +04:00
# define SMB2_MIN_SIZE_NO_BODY 0x40
2005-11-11 07:45:38 +03:00
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 )
2008-05-16 09:03:58 +04:00
# endif