2009-05-15 13:20:34 +04:00
/*
Unix SMB / CIFS implementation .
Core SMB2 server
Copyright ( C ) Stefan Metzmacher 2009
2010-05-18 00:05:22 +04:00
Copyright ( C ) Jeremy Allison 2010
2009-05-15 13:20:34 +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
the Free Software Foundation ; either version 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2011-03-22 18:57:01 +03:00
# include "smbd/smbd.h"
2009-05-15 13:20:34 +04:00
# include "smbd/globals.h"
2009-08-12 19:52:55 +04:00
# include "../libcli/smb/smb_common.h"
2011-07-26 09:11:47 +04:00
# include "../auth/gensec/gensec.h"
2011-03-24 15:46:20 +03:00
# include "auth.h"
2011-06-16 18:03:03 +04:00
# include "../lib/tsocket/tsocket.h"
2011-07-19 05:57:05 +04:00
# include "../libcli/security/security.h"
2012-05-12 12:16:41 +04:00
# include "../lib/util/tevent_ntstatus.h"
2009-05-15 13:20:34 +04:00
2012-05-12 12:16:41 +04:00
static struct tevent_req * smbd_smb2_session_setup_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct smbd_smb2_request * smb2req ,
uint64_t in_session_id ,
uint8_t in_flags ,
uint8_t in_security_mode ,
uint64_t in_previous_session_id ,
DATA_BLOB in_security_buffer ) ;
static NTSTATUS smbd_smb2_session_setup_recv ( struct tevent_req * req ,
uint16_t * out_session_flags ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * out_security_buffer ,
uint64_t * out_session_id ) ;
2012-05-12 12:20:55 +04:00
static void smbd_smb2_request_sesssetup_done ( struct tevent_req * subreq ) ;
2010-05-18 00:05:22 +04:00
NTSTATUS smbd_smb2_request_process_sesssetup ( struct smbd_smb2_request * smb2req )
2009-05-15 13:20:34 +04:00
{
const uint8_t * inhdr ;
const uint8_t * inbody ;
2010-05-18 00:05:22 +04:00
int i = smb2req - > current_idx ;
2009-05-15 13:20:34 +04:00
uint64_t in_session_id ;
2012-05-12 11:48:19 +04:00
uint8_t in_flags ;
2009-05-23 00:58:39 +04:00
uint8_t in_security_mode ;
2012-04-18 17:00:06 +04:00
uint64_t in_previous_session_id ;
2009-05-15 13:20:34 +04:00
uint16_t in_security_offset ;
uint16_t in_security_length ;
DATA_BLOB in_security_buffer ;
NTSTATUS status ;
2012-05-12 12:20:55 +04:00
struct tevent_req * subreq ;
2009-05-15 13:20:34 +04:00
2011-09-06 16:01:43 +04:00
status = smbd_smb2_request_verify_sizes ( smb2req , 0x19 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return smbd_smb2_request_error ( smb2req , status ) ;
2009-05-15 13:20:34 +04:00
}
2011-09-06 16:01:43 +04:00
inhdr = ( const uint8_t * ) smb2req - > in . vector [ i + 0 ] . iov_base ;
2010-05-18 00:05:22 +04:00
inbody = ( const uint8_t * ) smb2req - > in . vector [ i + 1 ] . iov_base ;
2009-05-15 13:20:34 +04:00
2012-04-18 17:00:06 +04:00
in_session_id = BVAL ( inhdr , SMB2_HDR_SESSION_ID ) ;
2012-05-12 11:48:19 +04:00
in_flags = CVAL ( inbody , 0x02 ) ;
2012-04-18 17:00:06 +04:00
in_security_mode = CVAL ( inbody , 0x03 ) ;
/* Capabilities = IVAL(inbody, 0x04) */
/* Channel = IVAL(inbody, 0x08) */
2009-05-15 13:20:34 +04:00
in_security_offset = SVAL ( inbody , 0x0C ) ;
in_security_length = SVAL ( inbody , 0x0E ) ;
2012-04-18 17:00:06 +04:00
in_previous_session_id = BVAL ( inbody , 0x10 ) ;
2009-05-15 13:20:34 +04:00
2011-09-06 16:01:43 +04:00
if ( in_security_offset ! = ( SMB2_HDR_BODY + smb2req - > in . vector [ i + 1 ] . iov_len ) ) {
2010-05-18 00:05:22 +04:00
return smbd_smb2_request_error ( smb2req , NT_STATUS_INVALID_PARAMETER ) ;
2009-05-15 13:20:34 +04:00
}
2010-05-18 00:05:22 +04:00
if ( in_security_length > smb2req - > in . vector [ i + 2 ] . iov_len ) {
return smbd_smb2_request_error ( smb2req , NT_STATUS_INVALID_PARAMETER ) ;
2009-05-15 13:20:34 +04:00
}
2010-05-18 00:05:22 +04:00
in_security_buffer . data = ( uint8_t * ) smb2req - > in . vector [ i + 2 ] . iov_base ;
2009-05-15 13:20:34 +04:00
in_security_buffer . length = in_security_length ;
2012-05-12 12:20:55 +04:00
subreq = smbd_smb2_session_setup_send ( smb2req ,
smb2req - > sconn - > ev_ctx ,
smb2req ,
in_session_id ,
in_flags ,
in_security_mode ,
in_previous_session_id ,
in_security_buffer ) ;
if ( subreq = = NULL ) {
return smbd_smb2_request_error ( smb2req , NT_STATUS_NO_MEMORY ) ;
}
tevent_req_set_callback ( subreq , smbd_smb2_request_sesssetup_done , smb2req ) ;
return smbd_smb2_request_pending_queue ( smb2req , subreq , 500 ) ;
}
static void smbd_smb2_request_sesssetup_done ( struct tevent_req * subreq )
{
struct smbd_smb2_request * smb2req =
tevent_req_callback_data ( subreq ,
struct smbd_smb2_request ) ;
int i = smb2req - > current_idx ;
uint8_t * outhdr ;
DATA_BLOB outbody ;
DATA_BLOB outdyn ;
uint16_t out_session_flags ;
uint64_t out_session_id ;
uint16_t out_security_offset ;
DATA_BLOB out_security_buffer = data_blob_null ;
NTSTATUS status ;
NTSTATUS error ; /* transport error */
status = smbd_smb2_session_setup_recv ( subreq ,
& out_session_flags ,
smb2req ,
& out_security_buffer ,
& out_session_id ) ;
TALLOC_FREE ( subreq ) ;
2009-05-15 13:20:34 +04:00
if ( ! NT_STATUS_IS_OK ( status ) & &
! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
status = nt_status_squash ( status ) ;
2012-05-12 12:20:55 +04:00
error = smbd_smb2_request_error ( smb2req , status ) ;
if ( ! NT_STATUS_IS_OK ( error ) ) {
smbd_server_connection_terminate ( smb2req - > sconn ,
nt_errstr ( error ) ) ;
return ;
}
return ;
2009-05-15 13:20:34 +04:00
}
out_security_offset = SMB2_HDR_BODY + 0x08 ;
2010-05-18 00:05:22 +04:00
outhdr = ( uint8_t * ) smb2req - > out . vector [ i ] . iov_base ;
2009-05-15 13:20:34 +04:00
2010-05-18 00:05:22 +04:00
outbody = data_blob_talloc ( smb2req - > out . vector , NULL , 0x08 ) ;
2009-05-15 13:20:34 +04:00
if ( outbody . data = = NULL ) {
2012-05-12 12:20:55 +04:00
error = smbd_smb2_request_error ( smb2req , NT_STATUS_NO_MEMORY ) ;
if ( ! NT_STATUS_IS_OK ( error ) ) {
smbd_server_connection_terminate ( smb2req - > sconn ,
nt_errstr ( error ) ) ;
return ;
}
return ;
2009-05-15 13:20:34 +04:00
}
SBVAL ( outhdr , SMB2_HDR_SESSION_ID , out_session_id ) ;
SSVAL ( outbody . data , 0x00 , 0x08 + 1 ) ; /* struct size */
2009-05-23 00:58:39 +04:00
SSVAL ( outbody . data , 0x02 ,
out_session_flags ) ; /* session flags */
2009-05-15 13:20:34 +04:00
SSVAL ( outbody . data , 0x04 ,
out_security_offset ) ; /* security buffer offset */
SSVAL ( outbody . data , 0x06 ,
out_security_buffer . length ) ; /* security buffer length */
outdyn = out_security_buffer ;
2012-05-12 12:20:55 +04:00
error = smbd_smb2_request_done_ex ( smb2req , status , outbody , & outdyn ,
__location__ ) ;
if ( ! NT_STATUS_IS_OK ( error ) ) {
smbd_server_connection_terminate ( smb2req - > sconn ,
nt_errstr ( error ) ) ;
return ;
}
2009-05-15 13:20:34 +04:00
}
static int smbd_smb2_session_destructor ( struct smbd_smb2_session * session )
{
2009-08-07 17:21:07 +04:00
if ( session - > sconn = = NULL ) {
2009-05-15 13:20:34 +04:00
return 0 ;
}
2012-03-12 21:04:01 +04:00
file_close_user ( session - > sconn , session - > vuid ) ;
2009-05-15 13:50:20 +04:00
/* first free all tcons */
while ( session - > tcons . list ) {
talloc_free ( session - > tcons . list ) ;
}
2009-08-07 17:21:07 +04:00
idr_remove ( session - > sconn - > smb2 . sessions . idtree , session - > vuid ) ;
DLIST_REMOVE ( session - > sconn - > smb2 . sessions . list , session ) ;
2009-08-11 20:08:26 +04:00
invalidate_vuid ( session - > sconn , session - > vuid ) ;
2009-05-15 13:20:34 +04:00
2009-05-15 13:40:19 +04:00
session - > vuid = 0 ;
session - > status = NT_STATUS_USER_SESSION_DELETED ;
2009-08-07 17:21:07 +04:00
session - > sconn = NULL ;
2009-05-15 13:40:19 +04:00
2009-05-15 13:20:34 +04:00
return 0 ;
}
2012-01-25 12:02:15 +04:00
static NTSTATUS smbd_smb2_auth_generic_return ( struct smbd_smb2_session * session ,
2010-05-18 00:05:22 +04:00
struct smbd_smb2_request * smb2req ,
uint8_t in_security_mode ,
2012-04-18 17:00:06 +04:00
uint64_t in_previous_session_id ,
2010-05-18 00:05:22 +04:00
DATA_BLOB in_security_buffer ,
2010-05-18 05:22:19 +04:00
uint16_t * out_session_flags ,
uint64_t * out_session_id )
2010-05-18 00:05:22 +04:00
{
2011-09-21 05:56:30 +04:00
bool guest = false ;
2009-05-23 00:58:39 +04:00
if ( ( in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED ) | |
2011-11-02 22:07:45 +04:00
lp_server_signing ( ) = = SMB_SIGNING_REQUIRED ) {
2009-05-23 00:58:39 +04:00
session - > do_signing = true ;
}
2011-07-19 05:57:05 +04:00
if ( security_session_user_level ( session - > session_info , NULL ) < SECURITY_USER ) {
2009-05-23 00:58:39 +04:00
/* we map anonymous to guest internally */
* out_session_flags | = SMB2_SESSION_FLAG_IS_GUEST ;
* out_session_flags | = SMB2_SESSION_FLAG_IS_NULL ;
/* force no signing */
session - > do_signing = false ;
2011-09-21 05:56:30 +04:00
guest = true ;
2009-05-23 00:58:39 +04:00
}
2011-02-14 03:35:21 +03:00
session - > session_key = session - > session_info - > session_key ;
2009-05-23 00:58:39 +04:00
2012-06-05 14:04:15 +04:00
session - > compat_vuser = talloc_zero ( session , struct user_struct ) ;
2009-05-27 20:33:45 +04:00
if ( session - > compat_vuser = = NULL ) {
TALLOC_FREE ( session ) ;
return NT_STATUS_NO_MEMORY ;
}
2011-12-26 07:23:15 +04:00
session - > compat_vuser - > gensec_security = session - > gensec_security ;
2009-05-27 20:33:45 +04:00
session - > compat_vuser - > homes_snum = - 1 ;
2011-02-21 12:25:52 +03:00
session - > compat_vuser - > session_info = session - > session_info ;
2009-05-27 20:33:45 +04:00
session - > compat_vuser - > session_keystr = NULL ;
session - > compat_vuser - > vuid = session - > vuid ;
2012-03-03 08:41:43 +04:00
DLIST_ADD ( session - > sconn - > users , session - > compat_vuser ) ;
session - > sconn - > num_users + + ;
2009-05-27 20:33:45 +04:00
2011-07-19 05:57:05 +04:00
if ( security_session_user_level ( session - > session_info , NULL ) > = SECURITY_USER ) {
2010-05-18 05:22:19 +04:00
session - > compat_vuser - > homes_snum =
2011-07-15 09:55:31 +04:00
register_homes_share ( session - > session_info - > unix_info - > unix_name ) ;
2010-05-18 05:22:19 +04:00
}
2010-08-16 10:00:48 +04:00
if ( ! session_claim ( session - > sconn , session - > compat_vuser ) ) {
2010-05-18 05:22:19 +04:00
DEBUG ( 1 , ( " smb2: Failed to claim session "
2012-06-05 20:17:15 +04:00
" for vuid=%llu \n " ,
( unsigned long long ) session - > compat_vuser - > vuid ) ) ;
2010-05-18 05:22:19 +04:00
TALLOC_FREE ( session ) ;
return NT_STATUS_LOGON_FAILURE ;
}
2012-01-25 08:22:38 +04:00
set_current_user_info ( session - > session_info - > unix_info - > sanitized_username ,
session - > session_info - > unix_info - > unix_name ,
session - > session_info - > info - > domain_name ) ;
reload_services ( smb2req - > sconn , conn_snum_used , true ) ;
2010-05-18 05:22:19 +04:00
2009-05-23 00:58:39 +04:00
session - > status = NT_STATUS_OK ;
/*
* we attach the session to the request
* so that the response can be signed
*/
2010-05-18 00:05:22 +04:00
smb2req - > session = session ;
2011-09-21 05:56:30 +04:00
if ( ! guest ) {
2010-05-18 00:05:22 +04:00
smb2req - > do_signing = true ;
}
global_client_caps | = ( CAP_LEVEL_II_OPLOCKS | CAP_STATUS32 ) ;
2010-05-18 05:22:19 +04:00
* out_session_id = session - > vuid ;
2010-05-18 00:05:22 +04:00
return NT_STATUS_OK ;
}
2012-01-25 12:02:15 +04:00
static NTSTATUS smbd_smb2_auth_generic ( struct smbd_smb2_session * session ,
struct smbd_smb2_request * smb2req ,
uint8_t in_security_mode ,
2012-04-18 17:00:06 +04:00
uint64_t in_previous_session_id ,
2012-01-25 12:02:15 +04:00
DATA_BLOB in_security_buffer ,
uint16_t * out_session_flags ,
DATA_BLOB * out_security_buffer ,
uint64_t * out_session_id )
2010-05-18 00:05:22 +04:00
{
NTSTATUS status ;
2011-09-23 00:42:56 +04:00
* out_security_buffer = data_blob_null ;
2011-12-26 07:23:15 +04:00
if ( session - > gensec_security = = NULL ) {
2011-12-26 05:13:21 +04:00
status = auth_generic_prepare ( session , session - > sconn - > remote_address ,
2011-12-26 07:23:15 +04:00
& session - > gensec_security ) ;
2010-05-18 00:05:22 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( session ) ;
return status ;
}
2011-07-26 04:19:54 +04:00
2011-12-26 07:23:15 +04:00
gensec_want_feature ( session - > gensec_security , GENSEC_FEATURE_SESSION_KEY ) ;
2012-01-12 01:25:38 +04:00
gensec_want_feature ( session - > gensec_security , GENSEC_FEATURE_UNIX_TOKEN ) ;
2011-07-26 04:19:54 +04:00
2012-02-03 04:54:32 +04:00
status = gensec_start_mech_by_oid ( session - > gensec_security , GENSEC_OID_SPNEGO ) ;
2011-07-26 04:19:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( session ) ;
return status ;
}
2010-05-18 00:05:22 +04:00
}
2012-01-25 12:02:15 +04:00
become_root ( ) ;
2011-12-26 07:23:15 +04:00
status = gensec_update ( session - > gensec_security ,
2011-10-18 14:13:16 +04:00
smb2req , NULL ,
in_security_buffer ,
out_security_buffer ) ;
2012-01-25 12:02:15 +04:00
unbecome_root ( ) ;
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) & &
! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( session ) ;
return nt_status_squash ( status ) ;
}
2010-05-18 00:05:22 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
* out_session_id = session - > vuid ;
return status ;
}
2010-07-16 22:05:34 +04:00
2011-12-26 07:23:15 +04:00
status = gensec_session_info ( session - > gensec_security ,
2011-10-18 13:58:47 +04:00
session ,
& session - > session_info ) ;
2010-07-16 22:05:34 +04:00
2010-05-18 00:05:22 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( session ) ;
return status ;
}
* out_session_id = session - > vuid ;
2012-01-25 12:02:15 +04:00
return smbd_smb2_auth_generic_return ( session ,
smb2req ,
in_security_mode ,
2012-04-18 17:00:06 +04:00
in_previous_session_id ,
2012-01-25 12:02:15 +04:00
in_security_buffer ,
out_session_flags ,
out_session_id ) ;
2010-05-18 00:05:22 +04:00
}
static NTSTATUS smbd_smb2_session_setup ( struct smbd_smb2_request * smb2req ,
uint64_t in_session_id ,
2012-05-12 11:48:19 +04:00
uint8_t in_flags ,
2010-05-18 00:05:22 +04:00
uint8_t in_security_mode ,
2012-04-18 17:00:06 +04:00
uint64_t in_previous_session_id ,
2010-05-18 00:05:22 +04:00
DATA_BLOB in_security_buffer ,
uint16_t * out_session_flags ,
DATA_BLOB * out_security_buffer ,
uint64_t * out_session_id )
{
struct smbd_smb2_session * session ;
* out_session_flags = 0 ;
* out_session_id = 0 ;
if ( in_session_id = = 0 ) {
int id ;
/* create a new session */
session = talloc_zero ( smb2req - > sconn , struct smbd_smb2_session ) ;
if ( session = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
session - > status = NT_STATUS_MORE_PROCESSING_REQUIRED ;
id = idr_get_new_random ( smb2req - > sconn - > smb2 . sessions . idtree ,
session ,
smb2req - > sconn - > smb2 . sessions . limit ) ;
if ( id = = - 1 ) {
return NT_STATUS_INSUFFICIENT_RESOURCES ;
}
session - > vuid = id ;
session - > tcons . idtree = idr_init ( session ) ;
if ( session - > tcons . idtree = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
session - > tcons . limit = 0x0000FFFE ;
session - > tcons . list = NULL ;
DLIST_ADD_END ( smb2req - > sconn - > smb2 . sessions . list , session ,
struct smbd_smb2_session * ) ;
session - > sconn = smb2req - > sconn ;
talloc_set_destructor ( session , smbd_smb2_session_destructor ) ;
} else {
void * p ;
/* lookup an existing session */
p = idr_find ( smb2req - > sconn - > smb2 . sessions . idtree , in_session_id ) ;
if ( p = = NULL ) {
return NT_STATUS_USER_SESSION_DELETED ;
}
session = talloc_get_type_abort ( p , struct smbd_smb2_session ) ;
}
if ( NT_STATUS_IS_OK ( session - > status ) ) {
return NT_STATUS_REQUEST_NOT_ACCEPTED ;
}
2012-01-25 12:02:15 +04:00
return smbd_smb2_auth_generic ( session ,
smb2req ,
in_security_mode ,
2012-04-18 17:00:06 +04:00
in_previous_session_id ,
2012-01-25 12:02:15 +04:00
in_security_buffer ,
out_session_flags ,
out_security_buffer ,
out_session_id ) ;
2009-05-15 13:20:34 +04:00
}
2012-05-12 12:16:41 +04:00
struct smbd_smb2_session_setup_state {
struct tevent_context * ev ;
struct smbd_smb2_request * smb2req ;
uint64_t in_session_id ;
uint8_t in_flags ;
uint8_t in_security_mode ;
uint64_t in_previous_session_id ;
DATA_BLOB in_security_buffer ;
uint16_t out_session_flags ;
DATA_BLOB out_security_buffer ;
uint64_t out_session_id ;
} ;
static struct tevent_req * smbd_smb2_session_setup_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct smbd_smb2_request * smb2req ,
uint64_t in_session_id ,
uint8_t in_flags ,
uint8_t in_security_mode ,
uint64_t in_previous_session_id ,
DATA_BLOB in_security_buffer )
{
struct tevent_req * req ;
struct smbd_smb2_session_setup_state * state ;
NTSTATUS status ;
req = tevent_req_create ( mem_ctx , & state ,
struct smbd_smb2_session_setup_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > ev = ev ;
state - > smb2req = smb2req ;
state - > in_session_id = in_session_id ;
state - > in_flags = in_flags ;
state - > in_security_mode = in_security_mode ;
state - > in_previous_session_id = in_previous_session_id ;
state - > in_security_buffer = in_security_buffer ;
status = smbd_smb2_session_setup ( smb2req ,
in_session_id ,
in_flags ,
in_security_mode ,
in_previous_session_id ,
in_security_buffer ,
& state - > out_session_flags ,
& state - > out_security_buffer ,
& state - > out_session_id ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) | |
NT_STATUS_IS_OK ( status ) )
{
talloc_steal ( state , state - > out_security_buffer . data ) ;
}
if ( tevent_req_nterror ( req , status ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
static NTSTATUS smbd_smb2_session_setup_recv ( struct tevent_req * req ,
uint16_t * out_session_flags ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * out_security_buffer ,
uint64_t * out_session_id )
{
struct smbd_smb2_session_setup_state * state =
tevent_req_data ( req ,
struct smbd_smb2_session_setup_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
tevent_req_received ( req ) ;
2012-05-16 17:32:08 +04:00
return nt_status_squash ( status ) ;
2012-05-12 12:16:41 +04:00
}
} else {
status = NT_STATUS_OK ;
}
* out_session_flags = state - > out_session_flags ;
* out_security_buffer = state - > out_security_buffer ;
* out_session_id = state - > out_session_id ;
talloc_steal ( mem_ctx , out_security_buffer - > data ) ;
tevent_req_received ( req ) ;
return status ;
}
2009-05-15 13:40:19 +04:00
NTSTATUS smbd_smb2_request_process_logoff ( struct smbd_smb2_request * req )
{
2011-09-06 16:01:43 +04:00
NTSTATUS status ;
2009-05-15 13:40:19 +04:00
DATA_BLOB outbody ;
2011-09-06 16:01:43 +04:00
status = smbd_smb2_request_verify_sizes ( req , 0x04 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return smbd_smb2_request_error ( req , status ) ;
2009-05-15 13:40:19 +04:00
}
/*
* TODO : cancel all outstanding requests on the session
* and delete all tree connections .
*/
smbd_smb2_session_destructor ( req - > session ) ;
/*
* we may need to sign the response , so we need to keep
* the session until the response is sent to the wire .
*/
talloc_steal ( req , req - > session ) ;
outbody = data_blob_talloc ( req - > out . vector , NULL , 0x04 ) ;
if ( outbody . data = = NULL ) {
return smbd_smb2_request_error ( req , NT_STATUS_NO_MEMORY ) ;
}
SSVAL ( outbody . data , 0x00 , 0x04 ) ; /* struct size */
SSVAL ( outbody . data , 0x02 , 0 ) ; /* reserved */
return smbd_smb2_request_done ( req , outbody , NULL ) ;
}