2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) Andrew Tridgell 2003
Copyright ( C ) James J Myers 2003 < myersjj @ samba . org >
2005-11-18 15:38:39 +03:00
Copyright ( C ) Stefan Metzmacher 2004 - 2005
2003-08-13 05:53:07 +04:00
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
2003-08-13 05:53:07 +04: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/>.
2003-08-13 05:53:07 +04:00
*/
2006-01-10 00:44:30 +03:00
# include "libcli/raw/request.h"
2006-03-17 16:55:10 +03:00
# include "libcli/raw/interfaces.h"
2006-03-26 05:23:40 +04:00
# include "lib/events/events.h"
# include "lib/socket/socket.h"
2006-08-30 15:29:34 +04:00
# include "lib/util/dlinklist.h"
2004-11-02 10:18:24 +03:00
2003-08-13 05:53:07 +04:00
/*
this header declares the core context structures associated with smb
sockets , tree connects , requests etc
the idea is that we will eventually get rid of all our global
2005-07-15 13:25:57 +04:00
variables and instead store our state from structures hanging off
2003-08-13 05:53:07 +04:00
these basic elements
*/
2005-12-06 20:59:20 +03:00
struct smbsrv_tcons_context {
/* an id tree used to allocate tids */
struct idr_context * idtree_tid ;
/* this is the limit of vuid values for this connection */
uint32_t idtree_limit ;
/* list of open tree connects */
struct smbsrv_tcon * list ;
} ;
struct smbsrv_sessions_context {
/* an id tree used to allocate vuids */
/* this holds info on session vuids that are already
* validated for this VC */
struct idr_context * idtree_vuid ;
/* this is the limit of vuid values for this connection */
uint64_t idtree_limit ;
/* also kept as a link list so it can be enumerated by
the management code */
struct smbsrv_session * list ;
2006-05-20 12:15:22 +04:00
} ;
struct smbsrv_handles_context {
/* an id tree used to allocate file handles */
struct idr_context * idtree_hid ;
/* this is the limit of handle values for this context */
uint64_t idtree_limit ;
/* also kept as a link list so it can be enumerated by
the management code */
struct smbsrv_handle * list ;
} ;
2005-12-06 20:59:20 +03:00
2003-08-13 05:53:07 +04:00
/* the current user context for a request */
2004-07-14 16:44:31 +04:00
struct smbsrv_session {
struct smbsrv_session * prev , * next ;
struct smbsrv_connection * smb_conn ;
2006-05-20 12:15:22 +04:00
/*
* in SMB2 tcons belong to just one session
* and not to the whole connection
*/
2005-12-06 20:59:20 +03:00
struct smbsrv_tcons_context smb2_tcons ;
2006-05-20 12:15:22 +04:00
/*
* the open file handles for this session ,
* used for SMBexit , SMBulogoff and SMB2 SessionLogoff
*/
struct smbsrv_handle_session_item * handles ;
2005-11-18 15:57:48 +03:00
/*
* an index passed over the wire :
* - 16 bit for smb
* - 64 bit for smb2
*/
uint64_t vuid ;
2003-08-13 05:53:07 +04:00
2004-07-14 16:44:31 +04:00
struct gensec_security * gensec_ctx ;
struct auth_session_info * session_info ;
2005-04-10 11:39:51 +04:00
2006-05-20 12:15:22 +04:00
/* some statistics for the management tools */
2005-11-18 15:57:48 +03:00
struct {
/* the time when the session setup started */
struct timeval connect_time ;
/* the time when the session setup was finished */
struct timeval auth_time ;
2006-03-26 15:32:27 +04:00
/* the time when the last request comes in */
struct timeval last_request_time ;
2005-11-18 15:57:48 +03:00
} statistics ;
2003-08-13 05:53:07 +04:00
} ;
2003-12-12 06:59:09 +03:00
/* we need a forward declaration of the ntvfs_ops strucutre to prevent
include recursion */
2004-09-29 17:17:09 +04:00
struct ntvfs_context ;
2003-12-12 06:59:09 +03:00
2004-06-28 12:27:36 +04:00
struct smbsrv_tcon {
struct smbsrv_tcon * next , * prev ;
2003-12-12 06:59:09 +03:00
/* the server context that this was created on */
2004-06-29 11:40:14 +04:00
struct smbsrv_connection * smb_conn ;
2003-12-12 06:59:09 +03:00
2006-05-20 12:15:22 +04:00
/* the open file handles on this tcon */
struct smbsrv_handles_context handles ;
2005-11-18 15:38:39 +03:00
/*
* an index passed over the wire :
* - 16 bit for smb
* - 32 bit for smb2
*/
uint32_t tid ; /* an index passed over the wire (the TID) */
2005-01-13 21:49:10 +03:00
2006-03-15 20:28:46 +03:00
/* the share name */
const char * share_name ;
2003-12-12 06:59:09 +03:00
2004-09-29 17:17:09 +04:00
/* the NTVFS context - see source/ntvfs/ for details */
2006-03-15 20:28:46 +03:00
struct ntvfs_context * ntvfs ;
2005-07-19 08:26:58 +04:00
2005-11-17 15:52:40 +03:00
/* some stuff to support share level security */
struct {
/* in share level security we need to fake up a session */
struct smbsrv_session * session ;
} sec_share ;
2005-12-06 20:59:20 +03:00
/* some stuff to support share level security */
struct {
/* in SMB2 a tcon always belongs to one session */
struct smbsrv_session * session ;
} smb2 ;
2006-05-20 12:15:22 +04:00
/* some statistics for the management tools */
2005-11-18 15:38:39 +03:00
struct {
2006-03-26 15:32:27 +04:00
/* the time when the tree connect started */
2005-11-18 15:38:39 +03:00
struct timeval connect_time ;
2006-03-26 15:32:27 +04:00
/* the time when the last request comes in */
struct timeval last_request_time ;
2005-11-18 15:38:39 +03:00
} statistics ;
2003-12-12 06:59:09 +03:00
} ;
2006-05-20 12:15:22 +04:00
struct smbsrv_handle {
struct smbsrv_handle * next , * prev ;
/* the tcon the handle belongs to */
struct smbsrv_tcon * tcon ;
/* the session the handle was opened on */
struct smbsrv_session * session ;
/* the smbpid used on the open, used for SMBexit */
uint16_t smbpid ;
/*
* this is for adding the handle into a linked list
* on the smbsrv_session , we can ' t use * next , * prev
* for this because they ' re used for the linked list on the
* smbsrv_tcon
*/
struct smbsrv_handle_session_item {
struct smbsrv_handle_session_item * prev , * next ;
struct smbsrv_handle * handle ;
} session_item ;
/*
* the value passed over the wire
* - 16 bit for smb
2007-05-21 21:23:56 +04:00
* - 32 bit for smb2
2006-05-20 12:15:22 +04:00
* Note : for SMB2 handles are 128 bit
2007-05-21 21:23:56 +04:00
* we ' ll fill them with
* - 32 bit HID
2006-05-20 12:15:22 +04:00
* - 32 bit TID
2007-05-21 21:23:56 +04:00
* - 64 bit VUID
2006-05-20 12:15:22 +04:00
*/
2007-05-21 21:23:56 +04:00
uint32_t hid ;
2006-05-20 12:15:22 +04:00
/*
* the ntvfs handle passed to the ntvfs backend
*/
struct ntvfs_handle * ntvfs ;
/* some statistics for the management tools */
struct {
/* the time when the tree connect started */
struct timeval open_time ;
/* the time when the last request comes in */
struct timeval last_use_time ;
} statistics ;
} ;
2004-10-29 01:48:53 +04:00
/* a set of flags to control handling of request structures */
2006-03-18 14:10:21 +03:00
# define SMBSRV_REQ_CONTROL_LARGE (1<<1) /* allow replies larger than max_xmit */
2004-10-29 01:48:53 +04:00
2006-06-22 01:28:07 +04:00
# define SMBSRV_REQ_DEFAULT_STR_FLAGS(req) (((req)->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII)
2003-08-13 05:53:07 +04:00
/* the context for a single SMB request. This is passed to any request-context
functions */
2004-06-28 12:39:00 +04:00
struct smbsrv_request {
2004-10-28 09:09:42 +04:00
/* the smbsrv_connection needs a list of requests queued for send */
2006-03-16 21:54:19 +03:00
struct smbsrv_request * next , * prev ;
2004-10-28 09:09:42 +04:00
2003-08-13 05:53:07 +04:00
/* the server_context contains all context specific to this SMB socket */
2004-06-29 11:40:14 +04:00
struct smbsrv_connection * smb_conn ;
2003-08-13 05:53:07 +04:00
/* conn is only set for operations that have a valid TID */
2004-06-28 12:27:36 +04:00
struct smbsrv_tcon * tcon ;
2003-08-13 05:53:07 +04:00
2004-07-14 16:44:31 +04:00
/* the session context is derived from the vuid */
struct smbsrv_session * session ;
2003-08-13 05:53:07 +04:00
2006-03-18 14:10:21 +03:00
/* a set of flags to control usage of the request. See SMBSRV_REQ_CONTROL_* */
2006-05-20 16:08:27 +04:00
uint32_t control_flags ;
2003-08-13 05:53:07 +04:00
/* the system time when the request arrived */
struct timeval request_time ;
2006-05-20 16:08:27 +04:00
/* a pointer to the per request union smb_* io structure */
void * io_ptr ;
/* the ntvfs_request */
struct ntvfs_request * ntvfs ;
/* Now the SMB specific stuff */
/* the flags from the SMB request, in raw form (host byte order) */
uint16_t flags2 ;
2003-08-13 05:53:07 +04:00
/* this can contain a fnum from an earlier part of a chained
* message ( such as an SMBOpenX ) , or - 1 */
int chained_fnum ;
/* how far through the chain of SMB commands have we gone? */
unsigned chain_count ;
2004-05-22 15:16:21 +04:00
/* the sequence number for signing */
2004-05-25 17:57:39 +04:00
uint64_t seq_num ;
2004-05-22 15:16:21 +04:00
2006-03-18 14:10:21 +03:00
struct request_buffer in ;
struct request_buffer out ;
2003-08-13 05:53:07 +04:00
} ;
2006-06-03 11:21:51 +04:00
enum security_types { SEC_SHARE , SEC_USER } ;
2006-02-23 18:52:24 +03:00
2004-06-29 11:40:14 +04:00
/* smb server context structure. This should contain all the state
* information associated with a SMB server connection
*/
struct smbsrv_connection {
/* context that has been negotiated between the client and server */
struct {
/* have we already done the NBT session establishment? */
BOOL done_nbt_session ;
/* only one negprot per connection is allowed */
BOOL done_negprot ;
/* multiple session setups are allowed, but some parameters are
ignored in any but the first */
BOOL done_sesssetup ;
/*
* Size of data we can send to client . Set
* by the client for all protocols above CORE .
* Set by us for CORE protocol .
*/
unsigned max_send ; /* init to BUFFER_SIZE */
/*
* Size of the data we can receive . Set by us .
* Can be modified by the max xmit parameter .
*/
unsigned max_recv ; /* init to BUFFER_SIZE */
/* the negotiatiated protocol */
enum protocol_types protocol ;
/* authentication context for multi-part negprot */
struct auth_context * auth_context ;
2005-10-20 07:47:55 +04:00
/* reference to the kerberos keytab, or machine trust account */
struct cli_credentials * server_credentials ;
2004-06-29 11:40:14 +04:00
/* did we tell the client we support encrypted passwords? */
BOOL encrypted_passwords ;
2006-02-09 06:04:48 +03:00
/* Did we choose SPNEGO, or perhaps raw NTLMSSP, or even no extended security at all? */
const char * oid ;
2004-06-29 11:40:14 +04:00
/* client capabilities */
uint32_t client_caps ;
/* the timezone we sent to the client */
int zone_offset ;
2005-01-22 08:36:32 +03:00
/* NBT names only set when done_nbt_session is true */
struct nbt_name * called_name ;
struct nbt_name * calling_name ;
2004-06-29 11:40:14 +04:00
} negotiate ;
2003-08-13 05:53:07 +04:00
2006-05-20 12:15:22 +04:00
/* the context associated with open tree connects on a smb socket, not for SMB2 */
2005-12-06 20:59:20 +03:00
struct smbsrv_tcons_context smb_tcons ;
2003-08-13 05:53:07 +04:00
2004-06-29 11:40:14 +04:00
/* context associated with currently valid session setups */
2005-12-06 20:59:20 +03:00
struct smbsrv_sessions_context sessions ;
2004-05-22 15:16:21 +04:00
2006-07-11 22:15:42 +04:00
/*
* the server_context holds a linked list of pending requests ,
* this is used for finding the request structures on ntcancel requests
2006-07-17 13:44:13 +04:00
* For SMB only
2006-07-11 22:15:42 +04:00
*/
struct smbsrv_request * requests ;
2003-08-13 05:53:07 +04:00
2006-07-17 13:44:13 +04:00
/*
* the server_context holds a linked list of pending requests ,
* and an idtree for finding the request structures on SMB2 Cancel
* For SMB2 only
*/
struct {
/* an id tree used to allocate ids */
struct idr_context * idtree_req ;
/* this is the limit of pending requests values for this connection */
uint32_t idtree_limit ;
/* list of open tree connects */
struct smb2srv_request * list ;
} requests2 ;
2005-01-14 05:10:11 +03:00
struct smb_signing_context signing ;
2006-05-20 12:15:22 +04:00
2005-01-30 03:54:57 +03:00
struct stream_connection * connection ;
2004-10-28 08:36:12 +04:00
/* this holds a partially received request */
2005-11-09 13:51:26 +03:00
struct packet_context * packet ;
2004-10-28 09:09:42 +04:00
2004-12-16 15:31:34 +03:00
/* a list of partially received transaction requests */
struct smbsrv_trans_partial {
struct smbsrv_trans_partial * next , * prev ;
struct smbsrv_request * req ;
struct smb_trans2 * trans ;
uint8_t command ;
} * trans_partial ;
2005-06-20 12:47:52 +04:00
2005-07-21 05:43:26 +04:00
/* configuration parameters */
struct {
enum security_types security ;
BOOL nt_status_support ;
} config ;
2006-03-26 15:32:27 +04:00
/* some statictics for the management tools */
struct {
/* the time when the client connects */
struct timeval connect_time ;
/* the time when the last request comes in */
struct timeval last_request_time ;
} statistics ;
2006-07-23 22:43:07 +04:00
struct share_context * share_context ;
2003-08-13 05:53:07 +04:00
} ;
2005-12-28 01:51:30 +03:00
# include "smb_server/smb_server_proto.h"
2005-12-28 18:38:36 +03:00
# include "smb_server/smb/smb_proto.h"
2006-03-18 14:10:21 +03:00
/* useful way of catching wct errors with file and line number */
# define SMBSRV_CHECK_WCT(req, wcount) do { \
if ( ( req ) - > in . wct ! = ( wcount ) ) { \
2006-09-07 13:49:34 +04:00
DEBUG ( 1 , ( " Unexpected WCT %u at %s(%d) - expected %d \n " , \
2006-03-18 14:10:21 +03:00
( req ) - > in . wct , __FILE__ , __LINE__ , wcount ) ) ; \
smbsrv_send_error ( req , NT_STATUS_DOS ( ERRSRV , ERRerror ) ) ; \
return ; \
} \
} while ( 0 )
/* useful wrapper for talloc with NO_MEMORY reply */
# define SMBSRV_TALLOC_IO_PTR(ptr, type) do { \
ptr = talloc ( req , type ) ; \
if ( ! ptr ) { \
smbsrv_send_error ( req , NT_STATUS_NO_MEMORY ) ; \
return ; \
} \
req - > io_ptr = ptr ; \
} while ( 0 )
# define SMBSRV_SETUP_NTVFS_REQUEST(send_fn, state) do { \
req - > ntvfs = ntvfs_request_create ( req - > tcon - > ntvfs , req , \
req - > session - > session_info , \
SVAL ( req - > in . hdr , HDR_PID ) , \
req - > request_time , \
req , send_fn , state ) ; \
if ( ! req - > ntvfs ) { \
smbsrv_send_error ( req , NT_STATUS_NO_MEMORY ) ; \
return ; \
} \
2006-06-20 13:57:00 +04:00
( void ) talloc_steal ( req - > tcon - > ntvfs , req ) ; \
2006-05-20 12:15:22 +04:00
req - > ntvfs - > frontend_data . private_data = req ; \
} while ( 0 )
# define SMBSRV_CHECK_FILE_HANDLE(handle) do { \
if ( ! handle ) { \
smbsrv_send_error ( req , NT_STATUS_INVALID_HANDLE ) ; \
return ; \
} \
} while ( 0 )
# define SMBSRV_CHECK_FILE_HANDLE_ERROR(handle, _status) do { \
if ( ! handle ) { \
smbsrv_send_error ( req , _status ) ; \
return ; \
} \
} while ( 0 )
# define SMBSRV_CHECK_FILE_HANDLE_NTSTATUS(handle) do { \
if ( ! handle ) { \
return NT_STATUS_INVALID_HANDLE ; \
} \
2006-03-18 14:10:21 +03:00
} while ( 0 )
2006-07-11 22:15:42 +04:00
# define SMBSRV_CHECK(cmd) do {\
NTSTATUS _status ; \
_status = cmd ; \
if ( ! NT_STATUS_IS_OK ( _status ) ) { \
smbsrv_send_error ( req , _status ) ; \
return ; \
} \
} while ( 0 )
2006-03-18 14:10:21 +03:00
/*
check if the backend wants to handle the request asynchronously .
if it wants it handled synchronously then call the send function
immediately
*/
# define SMBSRV_CALL_NTVFS_BACKEND(cmd) do { \
req - > ntvfs - > async_states - > status = cmd ; \
2006-07-11 22:15:42 +04:00
if ( req - > ntvfs - > async_states - > state & NTVFS_ASYNC_STATE_ASYNC ) { \
DLIST_ADD_END ( req - > smb_conn - > requests , req , struct smbsrv_request * ) ; \
} else { \
2006-03-18 14:10:21 +03:00
req - > ntvfs - > async_states - > send_fn ( req - > ntvfs ) ; \
} \
} while ( 0 )
/* check req->ntvfs->async_states->status and if not OK then send an error reply */
# define SMBSRV_CHECK_ASYNC_STATUS_ERR_SIMPLE do { \
req = talloc_get_type ( ntvfs - > async_states - > private_data , struct smbsrv_request ) ; \
if ( NT_STATUS_IS_ERR ( ntvfs - > async_states - > status ) ) { \
smbsrv_send_error ( req , ntvfs - > async_states - > status ) ; \
return ; \
} \
} while ( 0 )
# define SMBSRV_CHECK_ASYNC_STATUS_ERR(ptr, type) do { \
SMBSRV_CHECK_ASYNC_STATUS_ERR_SIMPLE ; \
ptr = talloc_get_type ( req - > io_ptr , type ) ; \
} while ( 0 )
# define SMBSRV_CHECK_ASYNC_STATUS_SIMPLE do { \
req = talloc_get_type ( ntvfs - > async_states - > private_data , struct smbsrv_request ) ; \
if ( ! NT_STATUS_IS_OK ( ntvfs - > async_states - > status ) ) { \
smbsrv_send_error ( req , ntvfs - > async_states - > status ) ; \
return ; \
} \
} while ( 0 )
# define SMBSRV_CHECK_ASYNC_STATUS(ptr, type) do { \
SMBSRV_CHECK_ASYNC_STATUS_SIMPLE ; \
ptr = talloc_get_type ( req - > io_ptr , type ) ; \
} while ( 0 )
/* zero out some reserved fields in a reply */
# define SMBSRV_VWV_RESERVED(start, count) memset(req->out.vwv + VWV(start), 0, (count)*2)